`
haofeng82
  • 浏览: 144512 次
  • 性别: Icon_minigender_1
  • 来自: 济南
社区版块
存档分类
最新评论

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

阅读更多

在使用脚本请求服务器端资源时(如图片),会出现重复下载资源的问题,这个问题只在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>
分享到:
评论

相关推荐

    浏览器缓存机制介绍与缓存策略剖析.pptx

    强缓存的缓存规则是由服务器端的 HTTP 响应报文的 HTTP 头中控制的,主要有 Expires 和 Cache-Control 两个字段,其中 Cache-Control 优先级比 Expires 高。Cache-Control 字段可以控制资源的有效期,通过 max-age ...

    服务器脚本.zip

    7. **ASP.NET**:微软的服务器端脚本框架,用于构建高性能的Web应用,支持C#和VB.NET等多种编程语言。 8. **AJAX(Asynchronous JavaScript and XML)**:虽然不是服务器脚本本身,但AJAX技术允许JavaScript在不...

    服务器端返回json数据

    7. **错误处理**:无论是服务器端还是客户端,都需要处理可能出现的错误,如网络问题、数据解析错误等。在服务器端,可能会返回一个包含错误信息的JSON结构;在客户端,需要捕获并显示这些错误。 8. **性能优化**:...

    php 长连接服务器端

    在IT行业中,PHP是一种广泛使用的服务器端脚本语言,尤其在Web开发领域有着重要的地位。本文将深入探讨“php 长连接服务器端”的概念及其在即时通讯产品开发中的应用。 首先,我们要理解什么是“长连接”。在传统的...

    页面缓存处理方案文档,解决前后端页面缓存

    以下示例展示了如何动态写入脚本,并在一定时间内缓存资源: ```html var timestamp = new Date().getTime(); var versionStamp = sessionStorage.version; if (versionStamp == null || (timestamp - ...

    WebQQ服务器端和客户端 for NowBoard

    6. **缓存技术**:为了提高用户体验,服务器端可能会使用缓存技术,比如内存缓存或分布式缓存(如Redis),来存储常用数据,减少数据库查询。 7. **负载均衡**:对于高访问量的Web应用,服务器端可能需要实现负载...

    网络传输文件,服务器端_网络传输_文件服务器_

    这个程序通常由服务器端软件如Apache、Nginx或自定义的服务端脚本(如Python、Node.js、Java等)实现。服务器端代码需要处理以下几个关键部分: 1. **监听与连接**:服务器端需启动一个监听器,等待客户端的TCP连接...

    缓存处理方法

    如代码示例所示,通过JavaScript和服务器端脚本,可以设置页面自动刷新或重定向,确保用户看到的是最新数据,同时避免了每次请求都进行完整页面渲染的开销。 2. **对象缓存**:在多用户环境中,为了防止同一用户多...

    3G航空订票服务器端

    例如,使用缓存技术可以提高数据访问速度,设置合适的会话超时策略可以防止恶意用户长时间占用资源。 总的来说,“3G航空订票服务器端”项目为初学者提供了一个全面学习服务器端开发的实践平台。通过这个项目,你...

    软件工程,客户端与服务器端交互

    在软件工程领域,客户端与服务器...以上是关于“软件工程,客户端与服务器端交互”的主要知识点,涵盖了架构设计、通信协议、安全措施、性能优化等多个方面。理解和掌握这些概念对于开发高效、安全的网络应用至关重要。

    asp磁盘缓存技术使用的代码

    ASP磁盘缓存技术是一种优化网站性能的方法,它通过将动态生成的网页内容存储到硬盘上作为静态文件,后续相同内容的请求可以直接读取这些缓存文件,避免了每次请求都执行复杂的服务器端处理,从而提高了网站响应速度...

    服务器资源监控.zip

    在“服务器资源监控”项目中,Python被用来编写监控脚本,获取服务器的CPU使用率、内存使用情况、磁盘I/O、网络流量等核心数据。这些数据可以通过内置的Python库如psutil、os、socket等轻松获取。同时,Python还可以...

    ASP缓存Gravatar头像实例演示 v1.0 -ASP源码.zip

    3. **缓存机制**:学习如何在服务器端建立一个缓存系统,存储已经获取到的Gravatar头像数据,比如可以使用Session对象、Application对象或者文件系统作为缓存存储。 4. **哈希算法**:理解MD5(Message-Digest ...

    支持Flash安全策略转发的服务器端

    总结,"支持Flash安全策略转发的服务器端"意味着我们需要编写一个能够正确处理Flash安全策略请求的服务器程序,使用C++和Visual Studio .NET 2005的Socket API来实现。这个过程包括识别请求、读取并返回crossdomain....

    dwr服务器端反推demo

    DWR(Direct Web Remoting)是一种Java库,用于在Web应用程序中实现实时通信,它允许JavaScript在客户端与服务器端之间进行直接调用,而无需传统的HTTP请求。在这个"dwrdemo"中,我们将深入探讨如何利用DWR的服务器...

    jsp播放服务器端视频

    在探讨“jsp播放服务器端视频”的主题时,我们首先需要理解JSP(JavaServer Pages)是一种基于Java技术的服务器端脚本语言,用于创建动态网页。JSP将HTML标记、Java代码片段以及预定义的动作结合在一起,使得网页...

    C++网游服务器端编程

    7. **安全性**:服务器端的安全性至关重要,包括防止DDoS攻击、SQL注入、XSS跨站脚本攻击等。使用HTTPS加密通信,以及验证客户端请求的有效性是基本的安全措施。 8. **性能优化**:C++的内存管理和性能调优是关键。...

    小偷影视缓存版 v0.1.rar

    ASP(Active Server Pages)是微软开发的一种服务器端脚本环境,它允许开发者创建动态网页。 在这个压缩包中,"yingshi"可能是主要的源代码文件夹,里面包含了实现小偷影视缓存功能的ASP文件和其他相关资源。这些...

Global site tag (gtag.js) - Google Analytics