在我的顶栏中,我有一个 <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
而不是employee。那么你就不需要一个自定义的转换器了。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
因此,它是可选的,只有当你在同一个数据库或文件系统中实际跟踪图像被更改的时间戳时才有用。然后,你应该真正使用它来代替最优化的缓存。一个 "随机 "的日期绝对不是正确的方式。