CacheManagementFilter

来源:互联网 发布:阿里云服务器租赁合同 编辑:程序博客网 时间:2024/06/06 01:36

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;
 }

}