Home  >  Article  >  Web Front-end  >  Use the Ehcache caching framework to cache pages_html/css_WEB-ITnose

Use the Ehcache caching framework to cache pages_html/css_WEB-ITnose

WBOY
WBOYOriginal
2016-06-24 11:47:301481browse

        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文件代码:

<?xml version="1.0" encoding="UTF-8"?><ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"	xsi:noNamespaceSchemaLocation="ehcache.xsd" updateCheck="true"	monitoring="autodetect" dynamicConfig="true">	<!-- 		diskStore :指定数据存储位置,可指定磁盘中的文件夹位置 		-->	<diskStore path="java.io.tmpdir/ehcache" />	<!--		defaultCache: 默认的管理策略		diskPersistent: 是否在磁盘上持久化。指重启jvm后,数据是否有效。默认为false。 		diskExpiryThreadIntervalSeconds: 对象检测线程运行时间间隔。标识对象状态的线程多长时间运行一次。		-->	<defaultCache 		maxEntriesLocalHeap="10000"		maxEntriesLocalDisk="10000000"		eternal="false"		timeToIdleSeconds="120"		timeToLiveSeconds="120"		overflowToDisk="true"		diskSpoolBufferSizeMB="30"		diskPersistent="false"		diskExpiryThreadIntervalSeconds="120"		memoryStoreEvictionPolicy="LRU" />	<!--配置自定义缓存: 		name: Cache的名称,具有唯一性,Ehcache会把该cache放到HashMap里。		maxEntriesLocalHeap:堆内存中最大缓存对象数,0没有限制		maxEntriesLocalDisk:磁盘中的最大对象数,默认为0不限制		eternal:设定缓存中elements是否永久有效,如果为true,timeouts设置将被忽略,element将永不过期;如果为false,则需要根据timeToIdleSeconds和timeToLiveSeconds相关配置进行判断。 		overflowToDisk:内存中数据超过设定的内存限制,造成内存不足时, 是否启用磁盘缓存以将数据缓存到磁盘上。。 		diskSpoolBufferSizeMB:设置DiskStore(磁盘缓存)的缓存区大小。默认是30MB。每个cache使用各自的DiskStore。		timeToIdleSeconds:缓存数据的钝化时间,也就是在一个元素消亡之前,两次访问时间的最大时间间隔值,这只能在元素不是永久驻留时有效(即将eternal设为false时), 如果该值是 0 就意味着元素可以停顿无穷长的时间。 		timeToLiveSeconds:缓存数据的生存时间,也就是一个元素从构建到消亡的最大时间间隔值, 这只能在元素不是永久驻留时有效(即将eternal设为false时),如果该值是0就意味着元素可以停顿无穷长的时间。 		memoryStoreEvictionPolicy:内存中数据超过设定的内存限制,造成内存不足时,该Cache启用的内存回收策略,默认值为LRU,可选FIFO、LFU。		Ehcache三大内存回收策略:		FIFO:First In First Out (先进先出)。		LFU: Less Frequently Used (最少被使用的)??所缓存的元素有一个hit属性,hit值最小的将会被“优先”清出缓存。		LRU:Least Recently Used(最近最少使用)??缓存的元素有一个时间戳,当缓存容量满了而又需要腾出地方来缓存新的元素时,那么现有缓存元素中时间戳离当前时间最远的元素将被“优先”清出缓存。		 -->	<cache 		name="PageEhCacheFilter"		maxEntriesLocalHeap="10000"		maxEntriesLocalDisk="1000"		eternal="false"		overflowToDisk="true"		diskSpoolBufferSizeMB="20"		timeToIdleSeconds="5"		timeToLiveSeconds="10"		memoryStoreEvictionPolicy="LFU" /></ehcache>

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

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

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

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

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

<?xml version="1.0" encoding="UTF-8"?><web-app xmlns="http://java.sun.com/xml/ns/javaee"     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"     xsi:schemaLocation="http://java.sun.com/xml/ns/javaee     http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd "     version="2.5">	<!-- 配置缓存并gzip压缩页面数据的核心过滤器 -->	<filter>		<filter-name>PageEhCacheFilter</filter-name>		<filter-class>com.ghj.packageoffilter.PageEhCacheFilter</filter-class>		<!-- 需要缓存的页面url -->		<init-param>			<param-name>patterns</param-name>			<param-value>/index.jsp</param-value>		</init-param>				<!-- 配置该过滤器所使用的Dhcache,值得注意的是:也可以不配置cacheName属性,但这时“ehcache.xml”文件中第44行代码的name属性必须为SimplePageCachingFilter,因为PageEhCacheFilter类继承的SimplePageCachingFilter类中设定了cacheName的值为“SimplePageCachingFilter”;如果在这里指定了cacheName属性,那么“ehcache.xml”文件中第44行代码的name属性的属性值必须和所配置的一致-->		<init-param>			<param-name>cacheName</param-name>			<param-value>PageEhCacheFilter</param-value>		</init-param>	</filter>	<filter-mapping>		<filter-name>PageEhCacheFilter</filter-name>		<url-pattern>*.action</url-pattern>	</filter-mapping>	<filter-mapping>		<filter-name>PageEhCacheFilter</filter-name>		<url-pattern>*.jsp</url-pattern>	</filter-mapping></web-app>

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

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" import="java.util.Date,java.text.SimpleDateFormat"%><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"><html>	<head>		<title>首页</title>	</head>		<body>		<div style="text-align:center;margin-top:360px;">			<font style="color:green;font-weight:bold;font-size: 18px"><%=new SimpleDateFormat("yyyy-MM-dd hh:MM:ss").format(new Date())%></font><br><br>			<font style="color:red;font-weight:bold;font-size: 27px">每次刷新页面,如果时间是变动的,则说明该页面没有被缓存或缓存已经过期,否则则说明该页面已经被缓存。</font>		</div>	</body></html>

        【0分下载该示例】

Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn