1. 程式人生 > >SpringMVC+mybatis+maven+Ehcache快取實現

SpringMVC+mybatis+maven+Ehcache快取實現

所謂快取,就是將程式或系統經常要呼叫的物件存在記憶體中,以便其使用時可以快速呼叫,不必再去建立新的重複的例項。這樣做可以減少系統開銷,提高系統效率。

快取主要可分為二大類: 

一、通過檔案快取,顧名思義檔案快取是指把資料儲存在磁碟上,不管你是以XML格式,序列化檔案DAT格式還是其它檔案格式;  

二、記憶體快取,也就是實現一個類中靜態Map,對這個Map進行常規的增刪查.

一、EhCache快取系統簡介

EhCache 是一個純 Java 的程序內快取框架,具有快速、精幹等特點,是 Hibernate 中預設的 CacheProvider。

EhCache 應用架構圖,下圖是 EhCache 在應用程式中的位置:

clip_image002

  EhCache 的主要特性有: 

複製程式碼
    1. 快速、精幹;

    2. 簡單;

    3. 多種快取策略;

    4. 快取資料有兩級:記憶體和磁碟,因此無需擔心容量問題;

    5. 快取資料會在虛擬機器重啟的過程中寫入磁碟;

    6. 可以通過 RMI、可插入 API 等方式進行分散式快取;

    7. 具有快取和快取管理器的偵聽介面;

    8. 支援多快取管理器例項,以及一個例項的多個快取區域;

    9. 提供 Hibernate 的快取實現;
複製程式碼

 二、maven新增Ehcache核心包 

在pom.xml配置檔案裡,新增

複製程式碼
  <!--ehcache 相關包 -->
   <dependency>
       <groupId>net.sf.ehcache</groupId>
       <artifactId>ehcache</artifactId>
       <version>2.7.5</version>
   </dependency>
   <dependency>
       <groupId>com.googlecode.ehcache-spring-annotations</groupId>
       <artifactId>ehcache-spring-annotations</artifactId>
       <version>1.2.0</version>
   </dependency>
複製程式碼

三、新增配置檔案

在資原始檔夾下(通常是src/main/resources/META-INF) 新增 applicationContext-ehcache.xmlehcache.xml 

   1、applicationContext-ehcache.xml內容如下:

複製程式碼
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
xmlns:aop="http://www.springframework.org/schema/aop" xmlns:c="http://www.springframework.org/schema/c"
xmlns:cache="http://www.springframework.org/schema/cache" xmlns:context="http://www.springframework.org/schema/context"
xmlns:jdbc="http://www.springframework.org/schema/jdbc" xmlns:jee="http://www.springframework.org/schema/jee"
xmlns:lang="http://www.springframework.org/schema/lang" xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:p="http://www.springframework.org/schema/p" xmlns:task="http://www.springframework.org/schema/task"
xmlns:tx="http://www.springframework.org/schema/tx" xmlns:util="http://www.springframework.org/schema/util" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd http://www.springframework.org/schema/cache http://www.springframework.org/schema/cache/spring-cache.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc.xsd http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee.xsd http://www.springframework.org/schema/lang http://www.springframework.org/schema/lang/spring-lang.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd"> <!-- 開啟spring快取 --> <cache:annotation-driven cache-manager="cacheManager" /> <bean id="cacheManagerFactory" class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean"> <property name="configLocation" value="classpath:META-INF/ehcache.xml"/> </bean> <bean id="cacheManager" class="org.springframework.cache.ehcache.EhCacheCacheManager"> <property name="cacheManager" ref="cacheManagerFactory"/> </bean> </beans>
複製程式碼

  這裡是開啟spring快取   

  2、ehcache.xml內容如下: 

複製程式碼
<?xml version="1.0" encoding="UTF-8"?>
<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="ehcache.xsd" updateCheck="true"
monitoring="autodetect" dynamicConfig="true"> <diskStore path="${java.io.tmpdir}/${system.project_name}/cache" /> <defaultCache maxElementsInMemory="10000" eternal="false" timeToIdleSeconds="120" timeToLiveSeconds="120" overflowToDisk="true"
          maxElementsOnDisk="10000000" diskPersistent="false" diskExpiryThreadIntervalSeconds="120" memoryStoreEvictionPolicy="LRU" /> <cache name="baseCache" maxElementsInMemory="200" maxElementsOnDisk="1000" eternal="false" overflowToDisk="true" diskSpoolBufferSizeMB="20"
      timeToIdleSeconds="300" timeToLiveSeconds="600" memoryStoreEvictionPolicy="LFU" /> </ehcache>
複製程式碼

  這裡是新增快取策略

  說明:

   1、java.io.tmpdir 所指地址:   

複製程式碼
 作業系統不同 這個系統屬性所表示的目錄也不同
On Windows: java.io.tmpdir:[C:\DOCUME~1\joshua\LOCALS~1\Temp\]

On Solaris: java.io.tmpdir:[/var/tmp/]

On Linux: java.io.tmpdir: [/tmp]

On Mac OS X: java.io.tmpdir: [/tmp]

    The default temporary-file directory is specified by the system property java.io.tmpdir. On UNIX systems the default value of this property is typically "/tmp" or "/var/tmp"; on Microsoft Windows systems it is typically "c:\temp". A different value may be given to this system property when the Java virtual machine is invoked, but programmatic changes to this property are not guaranteed to have any effect upon the the temporary directory used by this method.

To specify the java.io.tmpdir System property, you can invoke the JVM as follows:

java -Djava.io.tmpdir=/path/to/tmpdir

By default this value should come from the TMP environment variable on Windows systems
複製程式碼

  2、資料含義

複製程式碼
    name:Cache的唯一標識
    maxElementsInMemory:記憶體中最大快取物件數
    maxElementsOnDisk:磁碟中最大快取物件數,若是0表示無窮大
    eternal:Element是否永久有效,一但設定了,timeout將不起作用
    overflowToDisk:配置此屬性,當記憶體中Element數量達到maxElementsInMemory時,Ehcache將會Element寫到磁碟中
    timeToIdleSeconds:設定Element在失效前的允許閒置時間。僅當element不是永久有效時使用,可選屬性,預設值是0,也就是可閒置時間無窮大
    timeToLiveSeconds:設定Element在失效前允許存活時間。最大時間介於建立時間和失效時間之間。僅當element不是永久有效時使用,預設是0.,也就是element存活時間無窮大  
    diskPersistent:是否快取虛擬機器重啟期資料  
    diskExpiryThreadIntervalSeconds:磁碟失效執行緒執行時間間隔,預設是120秒
    diskSpoolBufferSizeMB:這個引數設定DiskStore(磁碟快取)的快取區大小。預設是30MB。每個Cache都應該有自己的一個緩衝區
    memoryStoreEvictionPolicy:當達到maxElementsInMemory限制時,Ehcache將會根據指定的策略去清理記憶體。預設策略是LRU(最近最少使用)。你可以設定為FIFO(先進先出)
  或是LFU(較少使用)
複製程式碼

四、DAO層做配置   

複製程式碼
    import org.springframework.cache.CacheManager;
  import org.springframework.cache.annotation.Cacheable;
    .....        
  @TriggersRemove(cacheName="baseCache",removeAll=true)
    public Entity save(Entity entity) throws CrudException {
        return entity;
    }

    @TriggersRemove(cacheName="baseCache",removeAll=true)
    public Entity update(Entity entity) throws CrudException {
        return entity;
    }

    @TriggersRemove(cacheName="baseCache",removeAll=true)
    public void del(Entity entity) throws CrudException {
            }

    @Cacheable(value="baseCache", key = "'findAll'")    
    public List<Entity> findAll() throws SearchException {
        return list;
    }
複製程式碼

@Cacheable(value="baseCache", key = "'findAll'")

這個註解就是做到快取資料,cacheName對應ehcache.xml 中配置


 @TriggersRemove(cacheName="baseCache",removeAll=true)

這個註解的作用就是當資料發生變化的時候清除快取,做到資料同步

  擴充套件:@Cacheable可以指定三個屬性,value、key和condition

  1、@Cacheable("cache1")@Cacheable({"cache1""cache2"})//Cache是發生在cache1cache2上的

    value屬性是必須指定的,其表示當前方法的返回值是會被快取在哪個Cache上的,對應Cache的名稱。其可以是一個Cache也可以是多個Cache,當需要指定多個Cache時其是一個數組。

  2@Cacheable(value="users", key="#user.id")@Cacheable(value="users", key="#p0")

    key屬性是用來指定Spring快取方法的返回結果時對應的key的。該屬性支援SpringEL表示式。當我們沒有指定該屬性時,Spring將使用預設策略生成key。我們這裡先來看看自定義策略,自定義策略是指我們可以通過Spring的EL表示式來指定我們的key。這裡的EL表示式可以使用方法引數及它們對應的屬性

  3、@Cacheable(value={"users"}, key="#user.id", condition="#user.id%2==0")

    有的時候我們可能並不希望快取一個方法所有的返回結果。通過condition屬性可以實現這一功能。condition屬性預設為空,表示將快取所有的呼叫情形。其值是通過SpringEL表示式來指定的,當為true時表示進行快取處理;當為false時表示不進行快取處理,即每次呼叫該方法時該方法都會執行一次。以上下示例表示只有當user的id為偶數時才會進行快取。

  4、@CachePut("users")

    在支援Spring Cache的環境下,對於使用@Cacheable標註的方法,Spring在每次執行前都會檢查Cache中是否存在相同key的快取元素,如果存在就不再執行該方法,而是直接從快取中獲取結果進行返回,否則才會執行並將返回結果存入指定的快取中。@CachePut也可以宣告一個方法支援快取功能。與@Cacheable不同的是使用@CachePut標註的方法在執行前不會去檢查快取中是否存在之前執行過的結果,而是每次都會執行該方法,並將執行結果以鍵值對的形式存入指定的快取中。

       @CachePut也可以標註在類上和方法上。使用@CachePut時我們可以指定的屬性跟@Cacheable是一樣的。

  5、@CacheEvict(value="users", allEntries=true)

  allEntries是boolean型別,表示是否需要清除快取中的所有元素。預設為false,表示不需要。當指定了allEntries為true時,Spring Cache將忽略指定的key。有的時候我們需要Cache一下清除所有的元素,這比一個一個清除元素更有效率。

  6、@CacheEvict(value="users", beforeInvocation=true)

    清除操作預設是在對應方法成功執行之後觸發的,即方法如果因為丟擲異常而未能成功返回時也不會觸發清除操作。使用beforeInvocation可以改變觸發清除操作的時間,當我們指定該屬性值為true時,Spring會在呼叫該方法之前清除快取中的指定元素。

  7、@Caching(cacheable = @Cacheable("users"), evict = { @CacheEvict("cache2"),

         @CacheEvict(value = "cache3", allEntries = true) })

     public User find(Integer id) {

        return null;

     }

   @Caching註解可以讓我們在一個方法或者類上同時指定多個Spring Cache相關的註解。其擁有三個屬性:cacheable、put和evict,分別用於指定@Cacheable、@CachePut和@CacheEvict   

  如何知道有沒生效:檢視sql執行日誌

參考: