package com.beetle.framework.web.cache;
import java.io.*;
import java.util.*;
import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.jsp.*;
import com.opensymphony.oscache.base.*;
import com.opensymphony.oscache.web.*;
public class CacheManagementFilter extends HttpServlet implements Filter {
private ServletCacheAdministrator servletCacheAdministrator = null;
private Map cachePaths = null;
// 继承自Filter类,处理request/response
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain filterChain) throws ServletException, IOException {
if (this.cachePaths.isEmpty()) {
filterChain.doFilter(request, response);
return;
}
HttpServletRequest httpRequest = (HttpServletRequest) request;
String path = getPath(httpRequest.getServletPath().trim()); // 得到请求字符的最后文件名路径
if (this.cachePaths.containsKey(path)) {
doCache(request, response, filterChain, path);
} else {
filterChain.doFilter(request, response);
}
}
private void doCache(ServletRequest request, ServletResponse response,
FilterChain filterChain, String urlpath) throws ServletException,
IOException {
CacheObject cacheObject = (CacheObject) cachePaths.get(urlpath);
int cacheScope = scopeString2scopeInt(cacheObject.getScope());
int time = cacheObject.getTime(); // 时间的单位是秒
HttpServletRequest httpRequest = (HttpServletRequest) request;
// 下面是利用OScache进行缓存处理
String key = servletCacheAdministrator.generateEntryKey(null, httpRequest, cacheScope);
Cache cache = servletCacheAdministrator.getCache(httpRequest, cacheScope);
try {
// 响应用户请求的内容(该内容被放在缓存中),包含页面显示内容和一些响应头信息: Content-Type、Last-Modified、Content-Encoding
ResponseContent respContent = (ResponseContent) cache.getFromCache(
key, time);
long clientLastModified = httpRequest.getDateHeader("If-Modified-Since");
//If-Modified-Since是由客户端往服务器发送的头信息,如果为空返回-1
//客户端会通过 If-Modified-Since 头将先前服务器端发过来的 Last-Modified 最后修改时间戳发送回去,
//这是为了让服务器端进行验证,通过这个时间戳判断客户端的页面是否是最新的,如果不是最新的,则返回新的内容,
//如果是最新的,则返回 304 告诉客户端其本地 cache 的页面是最新的,于是客户端就可以直接从本地加载页面了
if ((clientLastModified != -1)
&& (clientLastModified >= respContent.getLastModified())) {
((HttpServletResponse) response)
.setStatus(HttpServletResponse.SC_NOT_MODIFIED);
return;
}
// 写缓存数据到ServletResponse
respContent.cache2response(response);
} catch (NeedsRefreshException nre) {
cache.cancelUpdate(key);
nre.printStackTrace();
}
}
public void init(FilterConfig filterConfig) throws ServletException {
servletCacheAdministrator = ServletCacheAdministrator.getInstance(filterConfig
.getServletContext());
cachePaths = ConfigHelper.getCachePaths(filterConfig.getServletContext()
.getResourceAsStream("/config/CacheManagent.xml"));
}
private String getPath(String path) {
int i = path.lastIndexOf('/');
if (i == -1) {
return path;
} else {
return path.substring(i + 1);
}
}
private int scopeString2scopeInt(String scopeString) {
int cacheScope = PageContext.APPLICATION_SCOPE;
if (scopeString.equals("session")) {
cacheScope = PageContext.SESSION_SCOPE;
} else if (scopeString.equals("application")) {
cacheScope = PageContext.APPLICATION_SCOPE;
} else if (scopeString.equals("request")) {
cacheScope = PageContext.REQUEST_SCOPE;
} else if (scopeString.equals("page")) {
cacheScope = PageContext.PAGE_SCOPE;
}
return cacheScope;
}
}