IT博客汇
  • 首页
  • 精华
  • 技术
  • 设计
  • 资讯
  • 扯淡
  • 权利声明
  • 登录 注册

    [原]借助Ehcache缓存框架实现对页面的缓存

    wangshuxuncom发表于 2015-03-25 14:58:09
    love 0

    Ehcache是一个纯Java进程内缓存框架,该内存框架可以实现对页面或对象等数据的缓存——可以将数据缓存到内存和磁盘;与Memacached一样,该框架也支持集群/分布式缓存。本片博客用于研究如何借助Ehcache缓存框架实现对页面的缓存。页面缓存主要用Filter过滤器对客户端的http请求进行过滤,如果该请求存在于缓存中,那么页面将从缓存对象中获取gzip压缩后的数据(其响应速度是没有压缩缓存时速度的3-5倍)。页面缓存的过滤器有CachingFilter,可以通过继承该CachingFilter实现自定义页面缓存过滤器(Ehcache自身封装的SimplePageCachingFilter类就是通过继承CachingFilter类实现的页面缓存过滤器)。下面与大家分享一个示例:

    工程结构:


    代码1——PageEhCacheFilter.java文件代码:

    package com.ghj.packageoffilter;
     
    import java.util.Enumeration;
    
    import javax.servlet.FilterChain;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    
    import net.sf.ehcache.constructs.blocking.LockTimeoutException;
    import net.sf.ehcache.constructs.web.AlreadyCommittedException;
    import net.sf.ehcache.constructs.web.AlreadyGzippedException;
    import net.sf.ehcache.constructs.web.filter.FilterNonReentrantException;
    import net.sf.ehcache.constructs.web.filter.SimplePageCachingFilter;
    
    import org.apache.commons.lang.StringUtils;
    import org.apache.log4j.Logger;
    
    /**
     * 页面缓存过滤器
     * 
     * @author 高焕杰
     */
    public class PageEhCacheFilter extends SimplePageCachingFilter {
    
        private final static Logger logger = Logger.getLogger(PageEhCacheFilter.class);
    
        private static String[] cacheURLArray;
    
        @Override
        protected void doFilter(final HttpServletRequest request, final HttpServletResponse response, final FilterChain chain) throws AlreadyGzippedException, AlreadyCommittedException, FilterNonReentrantException, LockTimeoutException, Exception {
            if (cacheURLArray == null) {
            	String patterns = filterConfig.getInitParameter("patterns");
            	cacheURLArray = StringUtils.split(patterns, ",");
            }
            
            String requestURL = request.getRequestURL().toString();
            boolean containCacheURLFlag = false;
            if (cacheURLArray != null && cacheURLArray.length > 0) {
                for (String cacheURL : cacheURLArray) {
                    if (requestURL.contains(cacheURL.trim())) {//判断当前请求是否是要缓存的url
                    	containCacheURLFlag = true;
                        break;
                    }
                }
            }
    
            if (containCacheURLFlag) {//当前请求是要缓存的url
                String queryString = request.getQueryString();
                if (StringUtils.isNotEmpty(queryString)) {//当前请求含有采用问号传过来的参数
                	queryString = "?" + queryString;
                	logger.info("当前请求被缓存:" + requestURL + queryString);
                }else{
                	logger.info("当前请求被缓存:" + requestURL);
                }
                super.doFilter(request, response, chain);
            } else {//当前请求不是要缓存的url
                chain.doFilter(request, response);
            }
        }
    
        /**
         * 重写acceptsGzipEncoding方法,使该过滤器兼容对客户使用IE6和IE7时发过来请求时的gzip压缩
         * 使用Gzip压缩时,需注意两个问题:
    	 * 1、Filter进行Gzip压缩时,采用系统默认编码方式,对于使用GBK编码的中文网页来说,需要将操作系统的语言设置为“zh_CN.GBK”,否则会出现乱码问题。
    	 * 2、默认情况下CachingFilter类(SimplePageCachingFilter类的父类)会根据浏览器发送的请求头部所包含的Accept-Encoding参数值来判断是否进行Gzip压缩。虽然浏览器IE6和IE7支持Gzip压缩,但是在发送请求的时候却不带该参数,因此可以通过继承CachingFilter类,重写acceptsGzipEncoding方法来实现。
         *
         * @author 高焕杰
         */
        @Override
        protected boolean acceptsGzipEncoding(HttpServletRequest request) {
            boolean ie6 = headerContains(request, "User-Agent", "MSIE 6.0");
            boolean ie7 = headerContains(request, "User-Agent", "MSIE 7.0");
            return acceptsEncoding(request, "gzip") || ie6 || ie7;
        }
    
        private boolean headerContains(final HttpServletRequest request, final String header, final String value) {
            logRequestHeaders(request);
            final Enumeration accepted = request.getHeaders(header);
            while (accepted.hasMoreElements()) {
                final String headerValue = (String) accepted.nextElement();
                if (headerValue.indexOf(value) != -1) {
                    return true;
                }
            }
            return false;
        }
    }

    代码2——ehcache.xml文件代码:

    
    
    
    	
    	
    
    	
    	
    
    	
    	
    

    代码3——ehcache.xsd文件代码:

    该文件取自该压缩文件中——【0分下载该压缩文件】

    代码4——log4j.properties文件代码:

    log4j.rootLogger=DEBUG,Console,DailyRollingFile
    
    log4j.appender.Console=org.apache.log4j.ConsoleAppender
    log4j.appender.Console.layout=org.apache.log4j.PatternLayout
    log4j.appender.Console.layout.ConversionPattern= [%-5p]-[%d{yyyy-MM-dd HH:mm:ss}] -%l -%m%n
    
    log4j.appender.DailyRollingFile=org.apache.log4j.DailyRollingFileAppender
    log4j.appender.DailyRollingFile.Encoding=UTF-8
    log4j.appender.DailyRollingFile.File=C\:\\framework.log
    log4j.appender.DailyRollingFile.DatePattern=yyyy-MM-dd'.log'
    log4j.appender.DailyRollingFile.layout=org.apache.log4j.PatternLayout
    log4j.appender.DailyRollingFile.layout.ConversionPattern=%d [%t] %-5p %-40.40c %X{traceId}-%m%n

    代码5——web.xml文件代码:

    
    
    
    	
    	
    		PageEhCacheFilter
    		com.ghj.packageoffilter.PageEhCacheFilter
    		
    		
    			patterns
    			/index.jsp
    		
    		
    		
    		
    			cacheName
    			PageEhCacheFilter
    		
    	
    
    	
    		PageEhCacheFilter
    		*.action
    	
    	
    		PageEhCacheFilter
    		*.jsp
    	
    

    代码6——index.jsp文件代码:

    <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" import="java.util.Date,java.text.SimpleDateFormat"%>
    
    
    	
    		首页
    	
    	
    	
    		
    <%=new SimpleDateFormat("yyyy-MM-dd hh:MM:ss").format(new Date())%>

    每次刷新页面,如果时间是变动的,则说明该页面没有被缓存或缓存已经过期,否则则说明该页面已经被缓存。

    【0分下载该示例】

    作者:wangshuxuncom 发表于2015/3/25 14:58:09 原文链接
    阅读:222 评论:0 查看评论


沪ICP备19023445号-2号
友情链接