Static resources like css, js images etc. need not be reloaded from the server every time until and unless we want the old one needs to be replaced by the new one.

Sometimes we need to cache static resources so that performance of the site can be improved over the time.

Cache is defined as hardware or software feature that stores data in temporary storage space that permits quick access to stored data.

Web browsers like Chrome, Firefox, Internet Explorer etc. use the cache for regularly accessed web pages. This feature enables the browser to retrieve data from cache than from web page files.

The primary goal of the cache memory is to make the performance better by loading the web pages quickly.

So here I am going to give an example how caching mechanism works in java based web application.

Create some Enums first

The below enum constants are used in http headers.

public enum Cacheability {   
    PUBLIC("public"),
   
    PRIVATE("private");

    private String value;

    private Cacheability(String value) {
        this.value = value;
    }
   
    public String getValue() {
        return this.value;
    }

}
public enum CacheConfigParameter {

    STATIC("static"),

    PRIVATE("private"),

    EXPIRATION_TIME("expirationTime");

    private String name;

    private CacheConfigParameter(String name) {
        this.name = name;
    }
   
    public String getName() {
        return this.name;
    }

}
public enum HTTPCacheHeader {
   
    CACHE_CONTROL("Cache-Control"),
   
    EXPIRES("Expires"),
   
    PRAGMA("Pragma"),
 
    ETAG("ETag");

    private String name;

    private HTTPCacheHeader(String name) {
        this.name = name;
    }
   
    public String getName() {
        return this.name;
    }

}

Now create filters

The below Servlet Filter is used to set cache expiry time for static resources like js, css, image after which the static resources need to be served from server side.

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.HttpServletResponse;
import com.nissan.admin.filters.util.CacheConfigParameter;
import com.nissan.admin.filters.util.Cacheability;
import com.nissan.admin.filters.util.HTTPCacheHeader;

/**
 * Servlet Filter implementation class CacheFilter
 *
 * @author Soumitra
 */
public class CacheFilter implements Filter {
    private Cacheability cacheability;

    private boolean isStatic;

    private long seconds;

    /**
     * Default constructor.
     */
    public CacheFilter() {
    }

    public void destroy() {      
    }

    public void doFilter(ServletRequest request, ServletResponse response,
            FilterChain chain) throws IOException, ServletException {
       
        HttpServletResponse httpServletResponse = (HttpServletResponse) response;
        StringBuilder cacheControl = new StringBuilder(cacheability.getValue())
                .append(", max-age=").append(seconds);

        if (!isStatic) {
            cacheControl.append(", must-revalidate");
        }

        // Set cache directives
        httpServletResponse.setHeader(HTTPCacheHeader.CACHE_CONTROL.getName(),
                cacheControl.toString());
        httpServletResponse.setDateHeader(HTTPCacheHeader.EXPIRES.getName(),
                System.currentTimeMillis() + seconds * 1000L);

        if (httpServletResponse.containsHeader("Pragma")) {
            httpServletResponse.setHeader(HTTPCacheHeader.PRAGMA.getName(),
                    null);
        }

        // pass the request along the filter chain
        chain.doFilter(request, response);
    }

    public void init(FilterConfig fConfig) throws ServletException {
        cacheability = (Boolean.valueOf(fConfig
                .getInitParameter(CacheConfigParameter.PRIVATE.getName()))) ? Cacheability.PRIVATE
                : Cacheability.PUBLIC;
        isStatic = Boolean.valueOf(fConfig
                .getInitParameter(CacheConfigParameter.STATIC.getName()));

        try {
            seconds = Long.valueOf(fConfig
                    .getInitParameter(CacheConfigParameter.EXPIRATION_TIME
                            .getName()));
        } catch (NumberFormatException e) {
            throw new ServletException(new StringBuilder(
                    "The initialization parameter ")
                    .append(CacheConfigParameter.EXPIRATION_TIME.getName())
                    .append(" is missing for filter ")
                    .append(fConfig.getFilterName()).append(".").toString());
        }

    }

}

 

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.HttpServletResponse;


/**
 * Servlet Filter implementation class NoCacheFilter
 *
 * @author Soumitra Sarkar
 */
public class NoCacheFilter implements Filter {
   
    public NoCacheFilter() {     
    }
   
    public void destroy() {       
    }
   
    public void doFilter(ServletRequest request, ServletResponse response,
            FilterChain chain) throws IOException, ServletException {
      
        HttpServletResponse httpServletResponse = (HttpServletResponse) response;

      
        httpServletResponse.setHeader(HTTPCacheHeader.CACHE_CONTROL.getName(),
                "no-cache, no-store, must-revalidate");
        httpServletResponse
                .setDateHeader(HTTPCacheHeader.EXPIRES.getName(), 0L);

       
        chain.doFilter(request, response);
    }
   
    public void init(FilterConfig fConfig) throws ServletException {
       
    }

}

 Now put entries in web.xml file

The below entries are required in order to let Servlet Filter know for which requests the cache headers need to be applied.

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
    id="WebApp_ID" version="2.5">
    <display-name>filters</display-name>
    <welcome-file-list>
        <welcome-file>index.html</welcome-file>
        <welcome-file>index.htm</welcome-file>
        <welcome-file>index.jsp</welcome-file>
        <welcome-file>default.html</welcome-file>
        <welcome-file>default.htm</welcome-file>
        <welcome-file>default.jsp</welcome-file>
    </welcome-file-list>
    <filter>
        <display-name>NoCacheFilter</display-name>
        <filter-name>NoCacheFilter</filter-name>
        <filter-class>com.nissan.admin.filters.NoCacheFilter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>NoCacheFilter</filter-name>
        <url-pattern>/NoCacheFilter</url-pattern>
    </filter-mapping>
    <filter-mapping>
        <filter-name>NoCacheFilter</filter-name>
        <url-pattern>*.jsf</url-pattern>
        <dispatcher>REQUEST</dispatcher>
        <dispatcher>FORWARD</dispatcher>
    </filter-mapping>
    <filter>
        <filter-name>imagesCache</filter-name>
        <filter-class>com.nissan.admin.filters.CacheFilter</filter-class>
        <init-param>
            <param-name>static</param-name>
            <param-value>true</param-value>
        </init-param>
        <init-param>
            <param-name>expirationTime</param-name>
            <param-value>2592000</param-value>
        </init-param>
    </filter>
    <filter>
        <filter-name>cssCache</filter-name>
        <filter-class>com.nissan.admin.filters.CacheFilter</filter-class>
        <init-param>
            <param-name>expirationTime</param-name>
            <param-value>604800</param-value>
        </init-param>
    </filter>
    <filter>
        <filter-name>jsCache</filter-name>
        <filter-class>com.nissan.admin.filters.CacheFilter</filter-class>
        <init-param>
            <param-name>private</param-name>
            <param-value>true</param-value>
        </init-param>
        <init-param>
            <param-name>expirationTime</param-name>
            <param-value>216000</param-value>
        </init-param>
    </filter>
    <filter-mapping>
        <filter-name>imagesCache</filter-name>
        <url-pattern>/img/*</url-pattern>
    </filter-mapping>

    <filter-mapping>
        <filter-name>cssCache</filter-name>
        <url-pattern>*.css</url-pattern>
    </filter-mapping>

    <filter-mapping>
        <filter-name>jsCache</filter-name>
        <url-pattern>*.js</url-pattern>
    </filter-mapping>
</web-app>

That’s all. Thanks for your patience. Please leave a comment.

Tags:

I am a professional Web developer, Enterprise Application developer, Software Engineer and Blogger. Connect me on Roy Tutorials | TwitterFacebook Google PlusLinkedin | Reddit

Leave a Reply

Your email address will not be published. Required fields are marked *