SpringMVC通过Redis实现缓存主页

这里说的缓存只是为了提供一些动态的界面没办法作静态化的界面来减少数据库的访问压力,如果能够做静态化的话的还是采用nginx来做界面的静态化,这样可以承受高并发的访问能力。
好了,废话少说直接看实现代码吧,
实现机制主要是通过过滤器拦截方案,有两个地方要注意的
1,Servlet过虑器中使用Spring容器
2,截获JSP渲染结果保存redis中
首先看第一个Servlet过虑器中使用Spring容器
定义一个filter, 实现ApplicationContextAware接口
public class CacheFilter implements Filter, ApplicationContextAware {
private static ApplicationContext ctx; // 必须声明为static
@Override
public void init(FilterConfig config) throws ServletException {
}

@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
filterChain.doFilter(servletRequest, servletResponse);
}
@Override
public void destroy() {

}
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
CacheFilter.ctx = applicationContext; // 保存spring容器到static变量中
}

配置spring的bean

<bean class="com.zhang.example.servlet.CacheFilter" id="cacheFilter"></bean>

web.xml中的声明

<filter>
<filter-name>Cache Filter</filter-name>
<filter-class>com.zhang.example.servlet.CacheFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>Cache Filter</filter-name>
<servlet-name>/</servlet-name>
</filter-mapping>

这时,我们就可以在doFilter()方法中直接通过ApplicationContext检索需要的bean了
StringRedisTemplate redis = (StringRedisTemplate)ctx.getBean("redisTemplate");

二,截获JSP渲染结果
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() {
return cachedWriter;
}

/**
* 获取原始的HTML页面内容。
*
* @return
*/
public String getResult() {
return bufferedWriter.toString();
}
}

public class CacheFilter implements Filter, ApplicationContextAware {
private static final Logger log = LoggerFactory.getLogger(CacheFilter.class);

private static ApplicationContext ctx;
@Override
public void init(FilterConfig config) throws ServletException {
}

@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
HttpServletResponse resp = (HttpServletResponse) servletResponse;
HttpServletRequest req = (HttpServletRequest) servletRequest;
// 如果不是访问主页,放行
if (false == req.getRequestURI().equals("/")) {
filterChain.doFilter(servletRequest, resp);
return;
}
// 访问的是主页
// 从缓存中得到主页html
String html = getHtmlFromCache();
if (null == html) {
// 缓存中没有 截取生成的html并放入缓存
log.info("缓存不存在,生成缓存");
ResponseWrapper wrapper = new ResponseWrapper(resp);
filterChain.doFilter(servletRequest, wrapper);
// 放入缓存
html = wrapper.getResult();
putIntoCache(html);
}
// 返回响应
resp.setContentType("text/html; charset=utf-8");
resp.getWriter().print(html);
}
@Override
public void destroy() {
}

@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.ctx = applicationContext;
}

private String getHtmlFromCache() {
StringRedisTemplate redis = (StringRedisTemplate)ctx.getBean("redisTemplate");
return redis.opsForValue().get("home");
}

private void putIntoCache(String html) {
StringRedisTemplate redis = (StringRedisTemplate)ctx.getBean("redisTemplate");
redis.opsForValue().set("home", html, TimeUnit.MINUTES.toSeconds(10)); // 10分钟
}
}
按照这个逻辑,当客户的GET请求为/时,CacheFilter会首先向Redis发起请求获取主页的html代码,如果成功,则直接返回给客户端,失败,则通过刚刚写好的ResponseWrapper截获主页JSP的渲染结果,放入Redis,并设置过期时间为10分钟。这样下次请求时就可以直接从缓存中读取
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值