简体   繁体   English

o:graphicImage 缓存可能吗?

[英]o:graphicImage caching possible?

In my topbar I have a <o:graphicImage> to show picture from my user.在我的顶栏中,我有一个<o:graphicImage>来显示我的用户的图片。

<o:graphicImage dataURI="true" height="32" width="32" styleClass="img-circle"
    value="#{employeeProfileMenuPictureRequestController.getPicture_32_32(loginBean.currentEmployee)}" 
    lastModified="#{employeeProfileMenuPictureRequestController.lastUpdate}" />

My backend bean is the following:我的后端 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;
    }
}

Unfortunatelly the getPicture_32_32(Employee) is called for every page request / page navigation.不幸的是,每个页面请求/页面导航都会调用getPicture_32_32(Employee) This means it´s also everytime a request against the database, which takes time.这意味着它也是每次对数据库的请求,这需要时间。

I´ve tried already to add lastModified to the <o:graphicImage> , but the function is called also everytime for each page request.我已经尝试将lastModified添加到<o:graphicImage> ,但是每次页面请求都会调用 function 。

Can anybody help me to solve this?有人可以帮我解决这个问题吗?

According to <o:graphicImage> documentation:根据<o:graphicImage>文档:

Data URI数据 URI

[...] [...]

This approach is however not recommended for "permanent" and/or "large" images as it doesn't offer the browser any opportunity to cache the images for reuse, ~10KB would typically be the max even less so if there are more such images on the same page.但是,建议将这种方法用于“永久”和/或“大”图像,因为它没有为浏览器提供任何缓存图像以供重复使用的机会,通常最大 10KB 甚至更少,所以如果有更多这样的图像在同一页上。

So, it does not support caching at all.因此,它根本不支持缓存。 The technical reason is that it basically embeds whole contents of the image in the HTML output.技术原因是它基本上将图像的全部内容嵌入到 HTML output 中。 It does not embed an URL to the image.它不会将 URL 嵌入到图像中。 The lastModified is basically ignored. lastModified基本上被忽略了。 I should probably better document that.我可能应该更好地记录这一点。 At least, you should absolutely remove the dataURI attribute.至少,您应该绝对删除dataURI属性。 It's only useful for eg preview of an uploaded image.它仅对上传图像的预览有用。

And,和,

Image streaming图像流

[...] [...]

In case the property is a method expression taking arguments, each of those arguments will be converted to a string HTTP request parameter and back to actual objects using the converters registered by class as available via Application.createConverter(Class) . In case the property is a method expression taking arguments, each of those arguments will be converted to a string HTTP request parameter and back to actual objects using the converters registered by class as available via Application.createConverter(Class) . So, most of standard types like Long are already implicitly supported.因此,像Long这样的大多数标准类型已经被隐式支持。 In case you need to supply a custom object as argument for some reason, you need to explicitly register a converter for it yourself via @FacesConverter(forClass) .如果您出于某种原因需要提供自定义 object 作为参数,您需要通过@FacesConverter(forClass)为它自己显式注册一个转换器

So, because your method take a Employee argument, you basically need to have a @FacesConverter(forClass=Employee.class) so that JSF can automatically convert it from and to String .因此,因为您的方法采用Employee参数,所以您基本上需要有一个@FacesConverter(forClass=Employee.class)以便 JSF 可以自动将其从 String 转换为String How to create converters can be found here: Conversion Error setting value for 'null Converter' - Why do I need a Converter in JSF?如何创建转换器可在此处找到: “null Converter”的转换错误设置值 - 为什么我需要 JSF 中的转换器?

You should end up with something like this:你应该得到这样的结果:

@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.
    }

}

An alternative is to adjust your getPicture_32_32() method to take employee ID as eg Long instead of employee.另一种方法是调整您的getPicture_32_32()方法以将员工 ID 设为例如Long而不是员工。 Then you don't need a custom converter.那么你就不需要自定义转换器了。 JSF has already a built-in converter for Long . JSF 已经内置了Long转换器。

public byte[] getPicture_32_32(Long employeeId) {
    // ...
}
<o:graphicImage
    value="#{employeeProfileMenuPictureRequestController.getPicture_32_32(loginBean.currentEmployee.id)}" />

Coming back to caching, the documentation says this:回到缓存,文档说:

Caching缓存

[...] [...]

When unspecified, then the "default resource maximum age" as set in either the Mojarra specific context parameter com.sun.faces.defaultResourceMaxAge or MyFaces specific context parameter org.apache.myfaces.RESOURCE_MAX_TIME_EXPIRES will be used, else a default of 1 week will be assumed .如果未指定,则在 Mojarra 特定上下文参数com.sun.faces.defaultResourceMaxAge或 MyFaces 特定上下文参数org.apache.myfaces.RESOURCE_MAX_TIME_EXPIRES中设置的“默认资源最大年龄”将使用其他默认值假设

So, when you have no resource age settings, it's already by default cached for 1 week.因此,当您没有资源年龄设置时,默认情况下它已经缓存了 1 周。 The lastModified is thus optional and only useful when you actually track a timestamp in the same database or filesystem when the image is actually changed.因此, lastModified是可选的,仅当您在实际更改图像时实际跟踪同一数据库或文件系统中的时间戳时才有用。 You should then really use that instead for most optimal caching.然后,您应该真正使用它来获得最佳缓存。 A "random" date is absolutely not the correct way. “随机”日期绝对不是正确的方法。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM