jsf - o:graphicImage 缓存可能吗?
问题描述
在我的顶部栏中,我有一个<o:graphicImage>
要显示我的用户的图片。
<o:graphicImage dataURI="true" height="32" width="32" styleClass="img-circle"
value="#{employeeProfileMenuPictureRequestController.getPicture_32_32(loginBean.currentEmployee)}"
lastModified="#{employeeProfileMenuPictureRequestController.lastUpdate}" />
我的后端 bean 如下:
@GraphicImageBean
public class EmployeeProfileMenuPictureRequestController implements Serializable {
private Date lastUpdate = new Date();
public byte[] getPicture_32_32(Employee employee) throws StorageAttachmentNotFoundException, IOException {
try {
String path = employeeProfilePictureService.findProfileImageByEmployee(employee, FileSizeType.SIZE_32_32.toString());
if (employee == null || path == null || path.isEmpty()) {
return Utils.toByteArray(Faces.getResourceAsStream("/resources/images/no-photo-icon.png"));
}
Path fileLocation = Paths.get(path);
byte[] data = Files.readAllBytes(fileLocation);
LOGGER.info("END getPicture_32_32");
return data;
catch (Exception e) {
LOGGER.error(ExceptionUtils.getFullStackTrace(e));
}
return Utils.toByteArray(Faces.getResourceAsStream("/resources/images/no-photo-icon.png"));
}
public Date getLastUpdate() {
return lastUpdate;
}
}
不幸的getPicture_32_32(Employee)
是,每个页面请求/页面导航都会调用。这意味着它也是每次对数据库的请求,这需要时间。
我已经尝试添加lastModified
到<o:graphicImage>
,但每次页面请求时也会调用该函数。
有人可以帮我解决这个问题吗?
解决方案
数据 URI
[...]
但是,不建议将这种方法用于“永久”和/或“大”图像,因为它没有为浏览器提供任何缓存图像以供重复使用的机会,~10KB 通常是最大值甚至更少,所以如果有更多这样的图像在同一页上。
因此,它根本不支持缓存。技术原因是它基本上将图像的全部内容嵌入到 HTML 输出中。它不会在图像中嵌入 URL。基本lastModified
无视。我可能应该更好地记录这一点。至少,您应该绝对删除该dataURI
属性。它仅对上传图像的预览有用。
和,
图像流
[...]
如果属性是带参数的方法表达式,则每个参数都将转换为字符串 HTTP 请求参数,并使用类注册的转换器转换回实际对象,这些转换器可通过
Application.createConverter(Class)
. 因此,大多数标准类型Long
已经被隐式支持。如果您出于某种原因需要提供自定义对象作为参数,则需要通过@FacesConverter(forClass)
.
所以,因为你的方法有一个Employee
参数,所以你基本上需要有一个@FacesConverter(forClass=Employee.class)
,以便 JSF 可以自动将它从和转换为String
. 如何创建转换器可以在这里找到:“null Converter”的转换错误设置值 - 为什么我需要 JSF 中的转换器?
你应该得到这样的结果:
@FacesConverter(forClass=Employee.class)
public class EmployeeConverter implements Converter {
@Override
public String getAsString(FacesContext context, UIComponent component, Object modelValue) {
// Write code here which converts Employee to its unique String representation.
}
@Override
public Object getAsObject(FacesContext context, UIComponent component, String submittedValue) {
// Write code here which coverts the Employee unique String representation
// as created in above method back to the original Employee object.
}
}
另一种方法是调整您的getPicture_32_32()
方法以将员工 ID 作为例如Long
而不是员工。那么你就不需要自定义转换器了。JSF 已经为Long
.
public byte[] getPicture_32_32(Long employeeId) {
// ...
}
<o:graphicImage
value="#{employeeProfileMenuPictureRequestController.getPicture_32_32(loginBean.currentEmployee.id)}" />
回到缓存,文档说:
缓存
[...]
如果未指定,则将使用在 Mojarra 特定上下文参数
com.sun.faces.defaultResourceMaxAge
或 MyFaces 特定上下文参数中设置的“默认资源最大年龄”org.apache.myfaces.RESOURCE_MAX_TIME_EXPIRES
,否则将假定默认值为 1 周。
因此,当您没有资源年龄设置时,默认情况下它已经缓存了 1 周。因此,这lastModified
是可选的,并且仅当您在实际更改图像时实际跟踪同一数据库或文件系统中的时间戳时才有用。然后,您应该真正使用它来获得最佳缓存。“随机”日期绝对不是正确的方法。
推荐阅读
- sql - 如何通过 VB.net 从 Visual Studio 将多个 ComboBox 值输入到 Access 数据库
- objective-c - 如何检查 NSDictionary 是否为空并读取目标 c 中的 JSON 值
- python - 来自迭代器的 numpy ndarrays 的运行平均值
- javascript - Ionic 和 ssh2:错误:不支持 process.binding
- postgresql - 如何查询名称同时包含大小写的表?
- qt - 如何在 QML 文件中直接监听 QGuiApplication::applicationStateChanged 信号
- javascript - 将函数推送到数组,将 let 转换为 var
- javascript - document.getElementsByClassName 不起作用
- elasticsearch - 在 Vega 中引用子存储桶的语法
- serialization - 如何调试无效的 POST 正文?