`

如何缓存DWR生成的JS文件

阅读更多

DWR provides a convenient mechanism to execute server side java classes from javascript running in the browser. We use it extensively while developing Dekoh applications. Recently I noticed that when we use DWR, there are many requests to java-script files from the browser. It appeared that some DWR scripts are not being cached by the browser. I fired up  firefox live http headers   and noticed that inded some scripts were being downloaded with every page. We use DWR version 1.1.4. The headers for the repeat downloads looked like:

GET /dekohportal/dwr/interface/locationchooser.js HTTP/1.1
Host: localhost
User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.1) Gecko/20061010 Firefox/2.0
Accept: text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5
Accept-Language: en,as;q=0.5
Accept-Encoding: gzip,deflate
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
Keep-Alive: 300
Connection: keep-alive
Cache-Control: max-age=0  

HTTP/1.x 200 OK
Server: Pramati Server/5.0SP3 [Servlet/2.4 JSP/2.0]
Date: Tue, 24 Jul 2007 05:29:20 GMT
Transfer-Encoding: chunked
Connection: Keep-Alive

Notice that in the response headers, there is no Last-Modified header. This is the reason why the browser is reloading the script on every page load. This script is a DWR interface script. When you expose java methods using DWR (through a create tag in the dwr-*.xml), DWR creates an interface javascript. This file implements javascript methods which invoke the remote java methods (using DWREngine._execute). The interface script does not change unless the methods exposed in the dwr-*.xml are changed and the application is restarted. Hence the script should have been cacheable. These scripts are generated by DefaultInterfaceProcessor in DWR. To enable caching, we need to change the InterfaceProcessor to add the Last-Modified header in the response and read the If-Modified-Since header in the request. DWR provides a nice mechanism to plugin custom implementation of processors. So instead of chaging the DefaultInterfaceProcessor (which is shipped with DWR), I subclassed the default implementation to support these new headers and plugged it in to our runtime. The code for custom interface processor looks like:

import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;import uk.ltd.getahead.dwr.impl.DefaultInterfaceProcessor;
import uk.ltd.getahead.dwr.impl.HtmlConstants;  

/**
 * This class is the InterfaceProcessor for DWRHandler which
 * will add the functionality to add las modified header and
 * check if modified since header.
 * @author <a href="mailto:venkat@pramati.com" mce_href="mailto:venkat@pramati.com">Venkat Gunnu</a>
 * @since Jul 19, 2007
 */  

public class HttpCachingInterfaceProcessor
        extends DefaultInterfaceProcessor  

{
	//Store the application startup time. This will be the time we will set
	//as the Last-Modified time for all the interface scripts
	private final long lastUpdatedTime = (System.currentTimeMillis() / 1000) * 1000;  

	public void handle(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException
	{
		long ifModifiedSince = req.getDateHeader(HtmlConstants.HEADER_IF_MODIFIED);
		if (ifModifiedSince < lastUpdatedTime) {
			//If the browser does not have the script in the cache or the cached copy is stale
			//set the Last-Modified date header and send the new script file
			//Note: If the browser does not have the script in its cache ifModifiedSince will be -1  

			resp.setDateHeader(HtmlConstants.HEADER_LAST_MODIFIED, lastUpdatedTime);
			super.handle(req, resp);
		} else {
			//If the browser has current version of the file, dont send the script. Just say it has not changed
			resp.setStatus(HttpServletResponse.SC_NOT_MODIFIED);
		}
	}
}

To plugin this new Interface Processor, we need to add init parameter for DWRServlet in web.xml. The snippet from web.xml would look like:

<servlet><servlet-name>dwr-invoker</servlet-name>
<servlet-class>uk.ltd.getahead.dwr.DWRServlet</servlet-class>
<init-param>
<param-name>interface</param-name>
<param-value>util.dwr.HttpCachingInterfaceProcessor</param-value>
</init-param>
...
</servlet>

After adding the custom inerface processor following are the headers for the dwr interface request.

GET /dekohportal/dwr/interface/locationchooser.js HTTP/1.1
Host: localhost
User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.1) Gecko/20061010 Firefox/2.0
Accept: text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5
Accept-Language: en,as;q=0.5
Accept-Encoding: gzip,deflate
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
Keep-Alive: 300
Connection: keep-aliveHTTP/1.x 200 OK
Server: Pramati Server/5.0SP3 [Servlet/2.4 JSP/2.0]
Date: Tue, 24 Jul 2007 05:49:43 GMT  

Last-Modified: Tue, 24 Jul 2007 05:49:33 GMT


Transfer-Encoding: chunked
Connection: Keep-Alive

Notice that now for the first request, DWR is sending the Last-Modfied header. When we make the second request, the browser sends an “If-Modified-Since” header and DWR now sends a 304 NOT_MODIFIED response.

GET /dekohportal/dwr/interface/locationchooser.js HTTP/1.1
Host: localhost
User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.1) Gecko/20061010 Firefox/2.0
Accept: text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5
Accept-Language: en,as;q=0.5
Accept-Encoding: gzip,deflate
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
Keep-Alive: 300
Connection: keep-alive
If-Modified-Since: Tue, 24 Jul 2007 05:49:33 GMT

  

HTTP/1.x 304 NOT_MODIFIED


Server: Pramati Server/5.0SP3 [Servlet/2.4 JSP/2.0]
Date: Tue, 24 Jul 2007 05:50:42 GMT
Content-Length: 0


Connection: Keep-Alive

Thus, by plugging in a custom interface processor, we can enable caching of interface java-scripts in DWR.

 

原文:http://blogs.dekoh.com/dev/2007/07/24/caching-dwr-interface-java-script-files/

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics