ehcache實現頁面整體緩存和頁面局部緩存


之前寫過spring cache和ehcache的基本介紹和注解實現緩存管理,今天記錄下web項目的頁面緩存技術。

 

頁面緩存是否有必要?

     這樣說吧,幾乎所有的網站的首頁都是訪問率最高的,而首頁上的數據來源又是非常廣泛的,大多數來自不同的對象,而且有可能來自不同的db ,所以給首頁做緩存是很必要的。那么主頁的緩存策略應該怎樣設計呢?我認為應該是某個固定時間之內不變的,比如說2分鍾更新一次。那么這個緩存應該做在什么地方呢?讓我們來看一下,當前我們的的應用的結構一般是是page-filter-action-service-dao-db ,這個過程中的- 的地方都是可以做緩存的地方,根據頁面緩存的特征,應該把頁面緩存做到盡量靠近客戶的地方,就是在page 和filter 之間,這樣的優點就是第一個用戶請求之后,頁面被緩存,第二個用戶再來請求的時候,走到filter 這個請求就結束了,無需再走后面的action-service-dao-db 。帶來的好處是服務器壓力的減低和客戶段頁面響應速度的加快。了解了這些之后我們開始介紹重點。

ehcache頁面緩存的特點:緩存中的元素是被壓縮過的,如果客戶瀏覽器支持壓縮的話,filter 會直接返回壓縮過的流,這樣節省了帶寬,把解壓的工作交給了客戶瀏覽器,如果客戶的瀏覽器不支持gzip ,那么filter 會把緩存的元素拿出來解壓后再返回給客戶瀏覽器(大多數爬蟲是不支持gzip 的,所以filter 也會解壓后再返回流),這樣做的優點是節省帶寬,缺點就是增加了客戶瀏覽器的負擔

1 .SimplePageCachingFilter

    它ehcache-web模塊下頁面緩存Filter的一個簡單實現,適用於可以壓縮的Http響應(response),如HTML、XML、JSON等。它會使用通過CacheManager的靜態方法create創建的單例CacheManager,這樣如果之前已經存在CacheManager的實例了的話,這里就會直接拿來用,而不會再創建了。所以這里一般默認情況下會取類根路徑下的ehcache.xml文件來創建CacheManager,但如果我們的項目中整合了Ehcache和Spring,且在Spring配置文件中指定的Ehcache的配置文件不是默認位置的話,Spring將使用指定的配置文件優先初始化CacheManager,這樣SimplePageCachingFilter中要使用CacheManager時就不會再初始化了,而是直接使用Spring初始化的。頁面緩存使用的key是通過SimplePageCachingFilter的calculateKey()方法獲取的。其內部邏輯是獲取請求時的URI及后面的查詢字符串作為key進行返回,如“/user/index.jsp?name=abc”,這使得它的應用范圍非常廣。它不依賴於主機名和端口號,這將使得它同樣適用於有多個域或多個端口請求同樣內容的情況。如果有需要,我們可以對calculateKey方法進行重寫,從而實現我們自己的計算key的邏輯。這個是很有必要的,因為在項目中很多頁面都使用AJAX,為保證JS請求的數據不被瀏覽器緩存,每次請求可能都會是不同的數參數。如果使用 SimplePageCachingFilter,那么每次生成的key都不一樣,緩存就沒有意義了。這種情況下,我們就會覆寫 calculateKey()方法。

2 .SimpleCachingHeadersPageCachingFilter 提供HTTP緩存頭信息,這個不介紹了用的很少。

3 .SimplePageFragmentCachingFilter

    SimplePageCachingFilter適用於緩存整個頁面的情況,如果只需要緩存某一個片段,如使用jsp:include包含的部分,這個時候就需要用SimplePageFragmentCachingFilter。

第一部分是頁面整體緩存

第一步:首先配置ehcache.xml指定我們的SimplePageCachingFilter緩存  ,這里指定頁面緩存的生命周期是60秒,還有timeToIdleSeconds的時間愛你是120秒,這里要注意下不要設置太長時間

   <!-- 頁面全部緩存 -->
   <cache name="SimplePageCachingFilter"
           maxElementsInMemory="10"    
           maxElementsOnDisk="10"      
           eternal="false"
           overflowToDisk="false"
           timeToIdleSeconds="120"
           timeToLiveSeconds="60"
           memoryStoreEvictionPolicy="LFU">
</cache>

第二步 : 在web.xml中添加頁面緩存過濾器PageCachingFilter。

             注意: 如果我們在ehcache.xml中命名的頁面緩存名字為SimplePageCachingFilter時,我們再web.xml中的頁面緩存過濾器的cacheName是可以不用定義的,因為它是默認的;如果不是SimplePageCachingFilter,這是我就必須指定cacheName了。

還有一點url-pattern的指定應該是/pageCacheController/testPageCache.do,而不是/testPageCache.do這個。

    <!--ehcache 頁面緩存過濾器 -->
    <filter>
        <filter-name>PageCachingFilter</filter-name>
        <filter-class>net.sf.ehcache.constructs.web.filter.SimplePageCachingFilter</filter-class>
        <init-param>  
            <param-name>cacheName</param-name>  
            <param-value>SimplePageCachingFilter</param-value>  
       </init-param>  
    </filter>   
    <filter-mapping>
        <filter-name>PageCachingFilter</filter-name>
        <url-pattern>/pageCacheController/testPageCache.do</url-pattern>
    </filter-mapping>

第三步 : 編寫controller測試類

@Controller
@RequestMapping("pageCacheController")
public class PageCacheController {

    private final static Logger log = Logger.getLogger(PageCacheController.class);
    
    @RequestMapping("testPageCache")
    public ModelAndView testPageCache(){
        ModelMap model = new ModelMap();
        Date date = new Date();
        model.addAttribute("date", date.toLocaleString() );
        log.info("我來訪問controller了");
        return new ModelAndView("testPageCache",model);
    }
}
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8" %>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
    <title>測試</title>
    <script type="text/javascript" src="<%=request.getContextPath()%>/js/jquery-1.11.1.min.js"></script>
    
    <script type="text/javascript">

    </script>
  </head>
  
  <body>
  <h1>這是一個頁面緩存的練習</h1>
  <font style="color:green;font-weight:bold;font-size: 18px">${date}</font><br><br>
  </body>
</html>
View Code

上面這個是testPageCache.jsp頁面

第四步 : 訪問/pageCacheController/testPageCache.do觀察頁面時間並查看控制台輸出,在該緩存的生命周期內,即60秒之間刷新頁面,頁面上的時間是不會變化的,當過了緩存的生命周期在訪問,時間立馬改變。下面看看圖。

在60秒內刷新頁面觀看控制台。發現“我來訪問controller了”沒有打印出來,也就是說在緩存生命周期內我們第二次訪問時,只經過了page-filter-action-service-dao-db 中的page-filter其余的部分都沒有訪問。如果你親自做過的話你會對控制台打印的信息會產生興趣的,我這里給指出一個重要的Cache-control-> max-age=0,這個你們可以研究研究,我就不說了。

到這里頁面整體緩存的簡單例子就完成了,當然實際項目中肯定比這復雜,但是道理是一樣的。只要你明白其中的原理,那么一切OK!

第二部分是頁面局部緩存

 道理跟上面的一樣我就簡單說了

配置ehcache.xml

  <!-- 頁面局部緩存 -->
   <cache name="SimplePageFragmentCachingFilter"
           maxElementsInMemory="10"    
           maxElementsOnDisk="10"      
           eternal="false"
           overflowToDisk="false"
           timeToIdleSeconds="120"
           timeToLiveSeconds="60"
           memoryStoreEvictionPolicy="LFU">
    </cache>

 

配置web.xml,這里需要注意幾點,我們include的jsp頁面在filter中要指定<dispatcher>INCLUDE</dispatcher>,如果沒有指定任何< dispatcher >元素,默認值是REQUEST就不會攔截了。我這里有新增加了一個頁面作為include的頁面

 <!--ehcache 頁面局部緩存 -->
    <filter>
        <filter-name>PageFragmentCachingFilter</filter-name>
        <filter-class>net.sf.ehcache.constructs.web.filter.SimplePageFragmentCachingFilter</filter-class>
        <init-param>  
            <param-name>cacheName</param-name>  
            <param-value>SimplePageFragmentCachingFilter</param-value>  
       </init-param>  
    </filter>   
    <!-- This is a filter chain. They are executed in the order below.Do not change the order. -->
    <filter-mapping>
        <filter-name>PageFragmentCachingFilter</filter-name>
        <url-pattern>/page/testPageFragmentCache.jsp</url-pattern>
        <dispatcher>INCLUDE</dispatcher>
    </filter-mapping>
testPageFragmentCache.jsp頁面,為了方便我還是調用了上邊的controller方法來觀察時間。如果你是按照我的做法一步一步做的話,要測試局部緩存時,需要把頁面整體緩存的filter注釋掉,實際中不需要,只是我為了偷懶用了相同訪問地址
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8" %>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
    <title>測試</title>
  </head>  
  <body>
  <h1>這是include的jsp頁面</h1>
  <font style="color:green;font-weight:bold;font-size: 18px">${date}</font><br><br>
  </body>
</html>

下面來看效果圖

刷新頁面,沒有變化說明我們include的頁面被緩存了

來看看控制台變化

OK頁面緩存簡單的內容基本寫完了,有不合理的地方請大家指正。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM