JSF Cache Static Resources Filter

后端 未结 3 812
不思量自难忘°
不思量自难忘° 2020-11-28 07:31

How do I write a filter which will appropriately cache static resources as recommended by Google (https://developers.google.com/speed/docs/best-practices/caching).

I

相关标签:
3条回答
  • 2020-11-28 08:10

    No need to write a Filter, Tomcat 7 already has ExpiryFilter which add Cache-Control to your resources. It can be based on the modification or access time. See this blog:

    http://kahimyang.info/kauswagan/howto_blogs/1574-improving_page_load_with_mod_expires_and_expiresfilter_in_jsf_applications

    0 讨论(0)
  • 2020-11-28 08:13

    How do I write a filter which will appropriately cache static resources as recommended by Google

    If you mean with JSF resources the files in /resources folder which are fully handled by JSF builtin resource handler (and thus all referenced via <h:outputStylesheet>, <h:outputScript>, <h:graphicImage>, #{resource} and thus not via the plain HTML way), then you don't need to homegrow a filter for the job. The only thing which you need to do to satisfy Google recommendations is to set the Expires date a bit further in the future. It namely defaults to 7 days (604800000 milliseconds) while performance testing tools like Google Page Speed and Yahoo YSlow recommends a minimum of 30 days (2592000000 milliseconds).

    In Mojarra, you can set it with the following context parameter in web.xml:

    <context-param>
        <param-name>com.sun.faces.defaultResourceMaxAge</param-name>
        <param-value>2592000000</param-value> <!-- 30 days -->  
    </context-param>
    

    And in MyFaces with the following one:

    <context-param>
        <param-name>org.apache.myfaces.RESOURCE_MAX_TIME_EXPIRES</param-name>
        <param-value>2592000000</param-value> <!-- 30 days -->  
    </context-param>
    

    Is it sufficient to create a filter which sets the last-modified date to some static date (this will change every time the server restarts)?

    You don't and shouldn't need to set the Last-Modified. The JSF resource handler already does that automatically. If you'd like to force reloading by resources because you changed them, then use resource library versioning. See also What is the JSF resource library for and how should it be used?

    Note that changing it everytime the server restarts makes no sense as the Expires header would still keep telling the browser to re-test the validity of the cache after a certain period only. Until the browser actually requests the resource, the browser would never notice the change in the Last-Modified of a resource. The only thing which forces the browser hard to re-request the resource fully is a change in the URL, usually achieved by a changed query string parameter value. The JSF resource library versioning does exactly that.

    Also note that the OmniFaces CombinedResourceHandler uses the resource's last modified timestamp as "resource version" in the query string instead of the resource library version. So if you're using that, you don't necessarily need resource library versioning mechanism.


    The link above seems to suggest you need to specify Expires or Cache-Control. Why is that necessary?

    The Expires header tells the browser when to re-test the validity of the cached resource by a conditional GET request. So, until that time the browser won't do that and will keep using the one in the cache. The Cache-Control tells the browser which caching strategy to use. Note that when it's set to e.g. no-cache instead of public, then the Expires header would have no effect. Also note that the absence of Cache-Control header implies public (as done by JSF resources).

    0 讨论(0)
  • 2020-11-28 08:32

    Here is how i wrote my cache filter. works like a charm.

    Writing a cache filter to improve performance of the static content of JSF/Servlet screens

    Add following in your web.xml

    <filter>
        <filter-name>cache</filter-name>
        <filter-class>au.com.webapp.config.CacheFilter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>cache</filter-name>
        <url-pattern>*.xhtml</url-pattern>
    </filter-mapping>
    

    In your au.com.webapp.config package create a class CacheFilter as follows:

    package au.com.webapp.config;
    
    import java.io.IOException;
    
    import javax.servlet.Filter;
    import javax.servlet.FilterChain;
    import javax.servlet.FilterConfig;
    import javax.servlet.ServletException;
    import javax.servlet.ServletRequest;
    import javax.servlet.ServletResponse;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    
    public class CacheFilter implements Filter {
        private static long maxAge = 86400 * 30; // 30 days in seconds
    
        @Override
        public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
                throws IOException, ServletException {
            HttpServletResponse httpResponse = (HttpServletResponse) response;
            String uri = ((HttpServletRequest) request).getRequestURI();
            if (uri.contains(".js") || uri.contains(".css") || uri.contains(".svg") || uri.contains(".gif")
                    || uri.contains(".woff") || uri.contains(".png")) {
                httpResponse.setHeader("Cache-Control", "max-age=" + maxAge);
            }
            chain.doFilter(request, response);
        }
    
        @Override
        public void init(FilterConfig filterConfig) throws ServletException {
            System.out.println("Cache Filter started: ");
    
        }
    
        @Override
        public void destroy() {
        }
    }
    

    How to verify if my screen is using cache

    To see if your contents are already usign gzip and cache, In your Google Chrome Browser -> right click on your screen -> inspect -> click network tab -> refresh your screen. Click on the images, icons, stylesheets and see if you see following in response header

    Cache-Control:max-age=2592000

    Also when you refresh the page, if the status of element is 304 in stead of 200 (coming from cache), you are done.

    Other performance improvements such as gzip

    Refer to following link for additional simple performance improvements that can change your webapp or website performance significantly such as gzip or JQuery UI components. https://stackoverflow.com/a/35567464/5076414

    0 讨论(0)
提交回复
热议问题