JavaXT
|
|
Advanced Caching ExampleThe HttpServletResponse class includes a convenient write() method that you can use to send a java.io.File to the client. The write method includes an option to allow browsers to cache the files by supplying a last modified date and an ETag. Unfortunately, this doesn't work well in all browsers. Chrome's caching, for example, is very aggressive. It will ignore the last modified date and the ETag in javascript and css files referenced in an html document. To circumvent this issue, I like to append a version number to the css and js files. In the following example, the getFile() method will look for a version number associated with a js or css file found in the requested query string ("v" parameter). The version number is simply the last modified date of the file represented as a long int ("yyyyMMddHHmmssSSS"). If the requested file version is less than the current file version, then the browser is redirected to the newer file. Other features in this example include:
Note that this example requires javaxt-core.jar. package com.example; import javaxt.http.servlet.*; public class Servlet extends HttpServlet { private javaxt.io.Directory web; private String[] welcomeFiles = new String[]{"index.html", "index.htm", "default.htm"}; //************************************************************************** //** Constructor //************************************************************************** public Servlet(){ //Set path to the web directory java.io.File jarFile = new javaxt.io.Jar(this.getClass()).getFile(); java.io.File jarDir = jarFile.getParentFile(); if (jarDir.getName().equals("dist")){ //dev web = new javaxt.io.Directory(jarDir.getParentFile() + javaxt.io.Directory.PathSeparator + "web"); } else{ //production web = new javaxt.io.Directory(jarDir.getParentFile()); } } //************************************************************************** //** processRequest //************************************************************************** /** Used to process http get and post requests. */ public void processRequest(HttpServletRequest request, HttpServletResponse response) throws ServletException, java.io.IOException { javaxt.utils.URL url = new javaxt.utils.URL(request.getURL()); String path = url.getPath(); if (path.length()>1 && path.startsWith("/")) path = path.substring(1); String service = path.toLowerCase(); if (service.contains("/")) service = service.substring(0, service.indexOf("/")); if (service.equalsIgnoreCase("WebServices")){ //Process web service request... } else{ getFile(request, response); } } //************************************************************************** //** getFile //************************************************************************** /** Used to retrieve a local file and return it to the client. The file path * is derived from the requested url. */ private void getFile(HttpServletRequest request, HttpServletResponse response) throws java.io.IOException{ //Extract file name/path from the url javaxt.utils.URL url = new javaxt.utils.URL(request.getURL()); String path = url.getPath(); if (path==null || path.length()==1) path = ""; else path = path.substring(1); //Construct a list of possible file paths java.util.ArrayList<String> files = new java.util.ArrayList<String>(); files.add(web + path); if (path.length()>0 && !path.endsWith("/")) path+="/"; for (String welcomeFile : welcomeFiles){ files.add(web + path + welcomeFile); } //Loop through all the possible file combinations for (String str : files){ //Ensure that the path doesn't have any illegal directives str = str.replace("\\", "/"); if (str.contains("..") || str.contains("/.") || str.toLowerCase().contains("/keystore")){ continue; } //Send file if it exists java.io.File file = new java.io.File(str); if (file.exists() && file.isFile() && !file.isHidden()){ String name = file.getName(); int idx = name.lastIndexOf("."); if (idx > -1){ String ext = name.substring(idx+1).toLowerCase(); if (ext.equals("js") || ext.equals("css")){ //Add version number to javascript and css files to ensure //proper caching. Otherwise, browsers like Chrome may not //return the correct file to the client. long currVersion = new javaxt.utils.Date(file.lastModified()).toLong(); long requestedVersion = 0; try{ requestedVersion = Long.parseLong(url.getParameter("v")); } catch(Exception e){} if (requestedVersion < currVersion){ url.setParameter("v", currVersion+""); response.sendRedirect(url.toString(), true); return; } } } //Send file response.write(file, javaxt.io.File.getContentType(file.getName()), true); return; } } //If we're still here, throw an error response.setStatus(404); } } |