歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
您现在的位置: Linux教程網 >> UnixLinux >  >> Linux編程 >> Linux編程

SpringMVC通過Redis實現緩存主頁

首先,緩存主頁的目的並不一定是提高性能,而是減少數據庫訪問壓力,有效推遲數據庫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