关于使用脚本请求服务器端资源无法缓存的问题


在使用脚本请求服务器端资源时(如图片),会出现重复下载资源的问题,这个问题只在IE中出现过,经查找,发现一个解决方式:加一个过滤器,代码如下:、

import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Enumeration;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import java.util.regex.Pattern;
import java.util.regex.PatternSyntaxException;

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;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

/**
 * Filter fixes the IE image cache bug described at folowing locations.
 * http://mir.aculo.us/articles/2005/08/28/internet-explorer-and-ajax-image-caching-woes
 * http://www.netmechanic.com/news/vol6/javascript_no1.htm
 * http://www.bazon.net/mishoo/articles.epl?art_id=958
 * http://ahinea.com/en/tech/ie-dhtml-image-caching.html
 * 
 * @author zluspai
 */
public class IEImageCacheBugFixFilter implements Filter {

	private static final Log LOG = LogFactory.getLog(IEImageCacheBugFixFilter.class);
	// if the slowness is simulated by this filter
	private static final boolean SIMULATE_SLOWNESS = false;

	// date format for header
	private static final SimpleDateFormat DATEFORMAT = new SimpleDateFormat("EEE, d MMM yyyy 00:00:00 z", Locale.US);;

	// regexp Pattern objects precompiled
	private List patterns = new ArrayList();

	/**
	 * {@inheritDoc}
	 */
	public void init(FilterConfig config) throws ServletException {
		String patternParam = config.getInitParameter("patterns");
		// parse patterns
		if (patternParam != null) {
			String[] patternArr = patternParam.split(",");
			for (int i = 0; i < patternArr.length; i++) {
				String pattern = patternArr[i];
				try {
					Pattern p = Pattern.compile(pattern);
					this.patterns.add(p);
				} catch (PatternSyntaxException syntaxex) {
					LOG.warn("Exception when parsing pattern:" + pattern, syntaxex);
				}
			}
		}
	}

	/**
	 * Check if the path matches with the regexp patterns.
	 * 
	 * @param path The path string
	 * @return If matched
	 */
	private boolean isMatch(String path) {
		for (Iterator iPatterns = patterns.iterator(); iPatterns.hasNext();) {
			Pattern pattern = (Pattern) iPatterns.next();
			if (pattern.matcher(path).matches()) {
				if (LOG.isDebugEnabled()) {
					LOG.debug("matched: " + pattern.pattern() + " ,path:" + path);
				}
				return true;
			}
		}
		return false;
	}

	/**
	 * {@inheritDoc}
	 */
	public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {

		if (request instanceof HttpServletRequest) {
			HttpServletRequest httpRequest = (HttpServletRequest) request;
			HttpServletResponse httpResponse = (HttpServletResponse) response;
			String path = httpRequest.getRequestURI();

			// check patterns
			if (isMatch(path)) {
				if (LOG.isDebugEnabled()) {
					LOG.debug(getHeaderInfo(httpRequest));
				}

				// check if the browser asks if-modified
				if (httpRequest.getHeader("if-modified-since") != null) {
					// tell the browser that resource not changed, so it can use
					// the cached version!
					httpResponse.setStatus(304);
					LOG.debug("returning 304 for path:" + path);
					return;
				}

				// uncomment this to simulate slow response
				if (SIMULATE_SLOWNESS) {
					delay(path);
				}
				// turn on caching for everything served:
				addCacheHeader(httpResponse, path);
			}
		}
		// forward in chain
		chain.doFilter(request, response);
	}

	/**
	 * Add cache header to the response.
	 * 
	 * @param httpResponse The response
	 * @param path The current path
	 */
	private void addCacheHeader(HttpServletResponse httpResponse, String path) {
		httpResponse.setHeader("Cache-control", "max-age=10000000");
		Calendar c = Calendar.getInstance();
		String date = DATEFORMAT.format(c.getTime());
		httpResponse.setHeader("Last-Modified", date);
		// expires is one more year:
		c.add(Calendar.YEAR, 1);
		date = DATEFORMAT.format(c.getTime());
		httpResponse.setHeader("Expires", date);
		// unique tag needed
		httpResponse.setHeader("ETag", path);
	}

	/**
	 * Log header info arrived in request.
	 * 
	 * @param httpRequest The HttpRequest object.
	 * @return String containig all header info.
	 */
	private String getHeaderInfo(HttpServletRequest httpRequest) {
		StringBuffer info = new StringBuffer();
		Enumeration headernames = httpRequest.getHeaderNames();
		while (headernames.hasMoreElements()) {
			String name = (String) headernames.nextElement();
			info.append(name + "=" + httpRequest.getHeader(name)).append("\n");
		}
		return info.toString();
	}

	/**
	 * Implemented Filter method.
	 */
	public void destroy() {
	}

	/**
	 * Delay a bit before serving the response.
	 * 
	 * @param path The current request url path
	 */
	private void delay(String path) {
		// long delay:
		try {
			LOG.info("Waiting before serving of:" + path);
			Thread.sleep(2000);
		} catch (InterruptedException e) {
			LOG.debug("ignored exception", e);
		}
	}

}

To use this filter you will need to map it in the web.xml, for example:

<!-- fixes IE caching problem for Ajax requests -->
<!-- several directories can be cached: dojo, customdoj, images, scripts -->
<filter>
   <filter-name>IEImageCacheBugFixFilter</filter-name>
   <filter-class>IEImageCacheBugFixFilter</filter-class>
   <init-param>
      <param-name>patterns</param-name>
      <param-value>.*\.(g|G)(i|I)(f|F),.*\.(j|J)(p|P)(g|G),.*/dojo/.*,.*/images/.*,.*/scripts/.*,</param-value>
   </init-param>
   </filter>
<filter-mapping>
   <filter-name>IEImageCacheBugFixFilter</filter-name>
   <url-pattern>/*</url-pattern>
</filter-mapping>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值