1.HtmlStaticFilter :
/**
* 静态页面过滤器
*/
public class HtmlStaticFilter implements Filter {
public final Logger log = Logger.getLogger(HtmlStaticFilter.class);
private static int count = 0;
private XCacheManager cache;
public XCacheManager getCache() {
return cache;
}
public void setCache(XCacheManager cache) {
this.cache = cache;
}
@Override
public void init(FilterConfig filterConfig) throws ServletException {}
@Override
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
String refresh = request.getParameter("refresh");
if (StringUtils.isNotBlank(refresh) && "true".equals(refresh)) {
chain.doFilter(request, response);
return;
}
/**
* 获取请求url作为缓存的KEY
*/
String urlKey = request.getServerName()
+ ((HttpServletRequest) request).getRequestURI();
// 不缓存非html请求. js css img 跳过
if (!urlKey.endsWith(".html") && !urlKey.endsWith("/")) {
chain.doFilter(request, response);
return;
}
log.info(++count + ":url=====>" + urlKey);
/**
* 查看缓存中是否有此文件,如果有,返回文件
*/
String content = (String) cache.get(urlKey);
log.info(cache.getClass().getName());
if (content==null) {
log.info("content=====>" + content);// 应该只出现一次
// 使用我们自定义的响应包装器来包装原始的ServletResponse
ResponseWrapper wrapper = new ResponseWrapper(
(HttpServletResponse) response);
/**
* 如果没有,继续请求,获取请求后返回的结果,放入缓存中。
*/
// 这句话非常重要,注意看到第二个参数是我们的包装器而不是response
chain.doFilter(request, wrapper);
content=wrapper.getResult();
cache.set(urlKey, content);
}
/*
* 返回结果编码为UTF-8
*/
response.setCharacterEncoding("UTF-8");
//重置响应输出的内容长度
response.setContentLength(-1);
//输出最终结果
PrintWriter out=response.getWriter();
out.write(content);
out.flush();
out.close();
}
@Override
public void destroy() { }
}
2.ResponseWrapper :
import java.io.CharArrayWriter;
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpServletResponseWrapper;
/**
* 自定义一个响应结果包装器,将在这里提供一个基于内存的输出器来存储所有
* 返回给客户端的原始HTML代码。
*/
public class ResponseWrapper extends HttpServletResponseWrapper {
private PrintWriter cachedWriter;
private CharArrayWriter bufferedWriter;
public ResponseWrapper(HttpServletResponse response) {
super(response);
// 这个是我们保存返回结果的地方
bufferedWriter = new CharArrayWriter();
// 这个是包装PrintWriter的,让所有结果通过这个PrintWriter写入到bufferedWriter中
cachedWriter = new PrintWriter(bufferedWriter);
}
@Override
public PrintWriter getWriter() throws IOException {
// TODO Auto-generated method stub
return cachedWriter;
}
public String getResult() {
return bufferedWriter.toString();
}
}
3.缓存接口 :
import net.sf.ehcache.Cache;
/**
* 缓存接口
*/
public interface XCacheManager {
Object get(String key);
/**
* @return 若已存在,返回false ; 不存在,返回true
*/
void set(String key, Object value);
Cache getCache();
}
4.缓存接口实现类 :
import java.io.Serializable;
import net.sf.ehcache.Cache;
import net.sf.ehcache.Element;
/**
* 依赖EhCache实现缓存基础
*/
public class EhCacheManagerImpl implements XCacheManager {
private Cache cache;
public Cache getCache() {
return cache;
}
public void setCache(Cache cache) {
this.cache = cache;
}
@Override
public Object get(String key) {
Element e=cache.get(key);
if(e!=null){
return e.getValue();
}
return null;
}
@Override
public void set(String key, Object value) {
Element e=new Element(key,(Serializable)value);
cache.put(e);
}
}
5.web.xml配置
<filter>
<filter-name>htmlStaticFilter</filter-name>
<filter class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
<filter-mapping>
<filter-name>htmlStaticFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
6.spring-bean.xml配置
<bean id="cacheManager"
class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean">
</bean>
<bean id="configAttributeDefinitionEhcache"
class="org.springframework.cache.ehcache.EhCacheFactoryBean">
<property name="cacheManager" ref="cacheManager"></property>
<property name="cacheName" value="configAttributeDefinitionEhcache"></property>
</bean>
<!-- 缓存过滤器配置bean -->
<bean id="xCacheManager"
class="com.square.businessmodule.service.cache.EhCacheManagerImpl">
<property name="cache" ref="configAttributeDefinitionEhcache"></property>
</bean>
<bean id="htmlStaticFilter"
class="com.square.usermodule.webapp.servlet.filter.HtmlStaticFilter">
<property name="cache" ref="xCacheManager"></property>
</bean>
7.AB测试结果:
未开启缓存,直接访问本地资源
C:\Documents and Settings\Administrator>ab -n 1000 -c 100 http://localhost:8080/?refresh=true
Server Software: Apache-Coyote/1.1
Server Hostname: localhost
Server Port: 8080
Document Path: /?refresh=true
Document Length: 45454 bytes
Concurrency Level: 100
Time taken for tests: 56.781 seconds
Complete requests: 1000
Failed requests: 0
Write errors: 0
Total transferred: 45820000 bytes
HTML transferred: 45454000 bytes
Requests per second: 17.61 [#/sec] (mean)
Time per request: 5678.125 [ms] (mean)
Time per request: 56.781 [ms] (mean, across all concurrent requests)
Transfer rate: 788.04 [Kbytes/sec] received
Connection Times (ms)
min mean[+/-sd] median max
Connect: 0 2 12.0 0 234
Processing: 500 5548 2272.4 5297 11266
Waiting: 500 5544 2271.3 5297 11266
Total: 500 5550 2271.9 5297 11266
Percentage of the requests served within a certain time (ms)
50% 5297
66% 6797
75% 7500
80% 7859
90% 8641
95% 9281
98% 9828
99% 10188
100% 11266 (longest request)一个请求最长响应时间
开启缓存测试
C:\Documents and Settings\Administrator>ab -n 1000 -c 100 http://localhost:8080/
Server Software: Apache-Coyote/1.1
Server Hostname: localhost
Server Port: 8080
Document Path: /
Document Length: 45454 bytes
Concurrency Level: 100
Time taken for tests: 1.516 seconds
Complete requests: 1000
Failed requests: 0
Write errors: 0
Total transferred: 45556000 bytes
HTML transferred: 45454000 bytes
Requests per second: 659.79 [#/sec] (mean)
Time per request: 151.563 [ms] (mean)
Time per request: 1.516 [ms] (mean, across all concurrent requests)
Transfer rate: 29353.09 [Kbytes/sec] received
Connection Times (ms)
min mean[+/-sd] median max
Connect: 0 0 1.6 0 16
Processing: 0 146 109.8 141 563
Waiting: 0 144 109.8 141 563
Total: 0 146 109.7 141 563
Percentage of the requests served within a certain time (ms)
50% 141
66% 219
75% 250
80% 266
90% 281
95% 313
98% 313
99% 328
100% 563 (longest request)
比较上述结果,在没有缓存的测试结果下,结果令人鸭梨很大- -