歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
Linux教程網 >> Linux編程 >> Linux編程 >> SpringMVC通過Redis實現緩存主頁

SpringMVC通過Redis實現緩存主頁

日期:2017/3/1 9:28:26   编辑:Linux編程

首先,緩存主頁的目的並不一定是提高性能,而是減少數據庫訪問壓力,有效推遲數據庫I/O瓶頸的到來。實現主頁緩存的方法有很多,但是鑒於項目中使用了Redis對數據庫讀寫做了緩存,因此把順便也就把主頁也緩存了吧。

實現思路

編寫一個過濾器,在過濾器中攔截對主頁的訪問請求。此時向Redis服務器查詢主頁html的緩存,如果有則直接返回給客戶端,如果沒有,則在過濾器中截獲JSP的渲染結果,放到Redis緩存中,以供下次使用。我們設定緩存過期時間為10分鐘。

實現

實現需要注意的地方有兩點:

如何在Servlet過慮器中使用Spring容器

如何截獲JSP渲染結果

  • 對於問題一,可以見我的另一篇文章:在Servlet Filter中使用Spring容器 http://www.linuxidc.com/Linux/2015-06/118881.htm
  • 對於問題二,我們可以繼承HttpServletResponseWrapper類來巧妙實現:

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分鐘。這樣下次請求時就可以直接從緩存中讀取,而不需要經過 Controller -> Service -> Dao -> Database這麼費事的流程了。

Ubuntu 14.04下Redis安裝及簡單測試 http://www.linuxidc.com/Linux/2014-05/101544.htm

Redis集群明細文檔 http://www.linuxidc.com/Linux/2013-09/90118.htm

Ubuntu 12.10下安裝Redis(圖文詳解)+ Jedis連接Redis http://www.linuxidc.com/Linux/2013-06/85816.htm

Redis系列-安裝部署維護篇 http://www.linuxidc.com/Linux/2012-12/75627.htm

CentOS 6.3安裝Redis http://www.linuxidc.com/Linux/2012-12/75314.htm

Redis安裝部署學習筆記 http://www.linuxidc.com/Linux/2014-07/104306.htm

Redis配置文件redis.conf 詳解 http://www.linuxidc.com/Linux/2013-11/92524.htm

Redis 的詳細介紹:請點這裡
Redis 的下載地址:請點這裡

Copyright © Linux教程網 All Rights Reserved