SSM與EhCache整合

1. pom文件導入jar包

<!--ehcache緩存框架-->
<dependency>
   <groupId>net.sf.ehcache</groupId>
   <artifactId>ehcache</artifactId>
   <version>2.10.2</version>
</dependency>

2. Spring添加配置文件整合EhCache

2.1 新建EhCache配置文件

<?xml version="1.0" encoding="UTF-8"?>
<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:noNamespaceSchemaLocation="http://ehcache.org/ehcache.xsd">

    <!-- 磁盤緩存位置 -->
    <diskStore path="java.io.tmpdir/ehcache"/>

    <!-- 默認緩存 -->
    <defaultCache
            maxEntriesLocalHeap="10000"
            eternal="false"
            timeToIdleSeconds="120"
            timeToLiveSeconds="120"
            maxEntriesLocalDisk="10000000"
            diskExpiryThreadIntervalSeconds="120"
            memoryStoreEvictionPolicy="LRU">
        <persistence strategy="localTempSwap"/>
    </defaultCache>


    <!--獲取企業微信應用的accessToken-->
    <cache name="accessTokenCache"
           maxElementsInMemory="1000"
           eternal="false"
           overflowToDisk="false"
           memoryStoreEvictionPolicy="LRU"
    />

    <!--獲取企業微信通訊錄接口憑證accessToken-->
    <cache name="weChatAccessTokenCache"
           maxElementsInMemory="1000"
           eternal="false"
           overflowToDisk="false"
           memoryStoreEvictionPolicy="LRU"
    />

    <!--企業的jsapi_ticket緩存-->
    <cache name="jsapiTicketCache"
           maxElementsInMemory="1000"
           eternal="false"
           overflowToDisk="false"
           memoryStoreEvictionPolicy="LRU"
    />
</ehcache>

2.2 新建spring-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:cache="http://www.springframework.org/schema/cache"
       xsi:schemaLocation="
     http://www.springframework.org/schema/beans
     http://www.springframework.org/schema/beans/spring-beans.xsd
     http://www.springframework.org/schema/cache
     http://www.springframework.org/schema/cache/spring-cache.xsd">

    <!-- 支持緩存註解 -->
    <cache:annotation-driven cache-manager="cacheManager" />

    <!-- 默認是cacheManager -->
    <bean id="cacheManager" name= "cacheManager" class="org.springframework.cache.ehcache.EhCacheCacheManager">
        <property name="cacheManager" ref="cacheManagerFactory"/>
    </bean>

    <!-- cache管理器配置 -->
    <bean id="cacheManagerFactory" class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean">
        <property name="configLocation" value="classpath:ehcache/ehcache.xml"/><!-- ehcache.xml的路徑 -->
    </bean>
</beans>

org.springframework.cache.ehcache.EhCacheManagerFactoryBean這個類的作用是加載Ehcache配置文件
org.springframework.cache.ehcache.EhCacheCacheManager這個類的作用是支持net.sf.ehcache.CacheManager

2.3 將spring-ehcache.xml引入spring-mvc.xml配置文件

<import resource="classpath:spring-ehcache.xml"/>

配置好就可以使用spring的緩存註解使用緩存了

3. 使用spring緩存註解

Spring對緩存的支持類似於對事務的支持。
首先使用註解標記方法,相當於定義了切點,然後使用Aop技術在這個方法的調用前、調用後獲取方法的入參和返回值,進而實現了緩存的邏輯。

3.1 @Cacheable

表明所修飾的方法是可以緩存的:當第一次調用這個方法時,它的結果會被緩存下來,在緩存的有效時間內,以後訪問這個方法都直接返回緩存結果,不再執行方法中的代碼段。
這個註解可以用condition屬性來設置條件,如果不滿足條件,就不使用緩存能力,直接執行方法。

可以使用key屬性來指定key的生成規則

@Cacheable支持如下參數

  • value:緩存位置名稱,不能爲空,如果使用EHCache,就是ehcache.xml中聲明的cache的name, 指明將值緩存到哪個Cache中
  • key:緩存的key,默認爲空,既表示使用方法的參數類型及參數值作爲key,支持SpEL,如果要引用參數值使用井號加參數名,如:#userId,
    一般來說,我們的更新操作只需要刷新緩存中某一個值,所以定義緩存的key值的方式就很重要,最好是能夠唯一,因爲這樣可以準確的清除掉特定的緩存,而不會影響到其它緩存值 ,
    本例子中使用實體加冒號再加ID組合成鍵的名稱,如”user:1”、”order:223123”等
  • condition:觸發條件,只有滿足條件的情況纔會加入緩存,默認爲空,既表示全部都加入緩存,支持SpEL
// 將緩存保存到名稱爲UserCache中,鍵爲"user:"字符串加上userId值,如 'user:1'
@Cacheable(value="UserCache", key="'user:' + #userId")    
public User findById(String userId) {    
    return (User) new User("1", "mengdee");           
}    
 
// 將緩存保存進UserCache中,並當參數userId的長度小於12時才保存進緩存,默認使用參數值及類型作爲緩存的key
// 保存緩存需要指定key,value, value的數據類型,不指定key默認和參數名一樣如:"1"
@Cacheable(value="UserCache", condition="#userId.length() < 12")    
public boolean isReserved(String userId) {    
    System.out.println("UserCache:"+userId);    
    return false;    
}

3.2 @CachePut

與@Cacheable不同,@CachePut不僅會緩存方法的結果,還會執行方法的代碼段。它支持的屬性和用法都與@Cacheable一致。可以用來更新緩存

3.3 @CacheEvict

與@Cacheable功能相反,@CacheEvict表明所修飾的方法是用來刪除失效或無用的緩存數據。

@CacheEvict 支持如下幾個參數

  • value:緩存位置名稱,不能爲空,同上
  • key:緩存的key,默認爲空,同上
  • condition:觸發條件,只有滿足條件的情況纔會清除緩存,默認爲空,支持SpEL
  • allEntries:true表示清除value中的全部緩存,默認爲false
//清除掉UserCache中某個指定key的緩存    
@CacheEvict(value="UserCache",key="'user:' + #userId")    
public void removeUser(User user) {    
    System.out.println("UserCache"+user.getUserId());    
}    
 
//清除掉UserCache中全部的緩存    
@CacheEvict(value="UserCache", allEntries=true)    
public final void setReservedUsers(String[] reservedUsers) {    
   System.out.println("UserCache deleteall");    
}

3.4 @Caching

如果需要使用同一個緩存註解(@Cacheable、@CacheEvict或@CachePut)多次修飾一個方法,就需要用到@Caching。

@Caching(evict = { @CacheEvict("primary"), @CacheEvict(cacheNames="secondary", key="#p0") })
public Book importBooks(String deposit, Date date)

3.5 @CacheConfig

與前面的緩存註解不同,這是一個類級別的註解。
如果類的所有操作都是緩存操作,你可以使用@CacheConfig來指定類,省去一些配置。

@CacheConfig("books")
public class BookRepositoryImpl implements BookRepository {
    @Cacheable
    public Book findBook(ISBN isbn) {...}
}

4. 使用@Cacheabl緩存並在緩存方法裏面設置緩存時間

Spring緩存註解使用EhCache,配置cache的緩存時間都是通過cache標籤的timeToLiveSeconds 屬性設置。如果想要在被緩存方法裏面設置緩存時間。
可以在當前類注org.springframework.cache.ehcache.EhCacheCacheManager

@Autowired
private EhCacheCacheManager ehCacheCacheManager;

org.springframework.cache.ehcache.EhCacheCacheManager這個類的作用是支持net.sf.ehcache.CacheManager。

具體代碼如下:

//1.通過org.springframework.cache.ehcache.EhCacheCacheManager獲取、//net.sf.ehcache.CacheManager

CacheManager cacheManager = ehCacheCacheManager.getCacheManager();

//2.獲取要設置緩存時間的cache類
Cache jsapiTicketCache = cacheManager.getCache("accessTokenCache");

//3.獲取cache類的配置類
CacheConfiguration cacheConfiguration = jsapiTicketCache.getCacheConfiguration();

//4.配置cache類的緩存時間
cacheConfiguration.setTimeToLiveSeconds(expiresIn);

5. 常見問題

5.1 Cacheable註解不生效原因

一個方法A調同一個類裏的另一個有緩存註解的方法B,這樣是不走緩存的

爲什麼緩存沒有被正常創建??

因爲@Cacheable 是使用AOP 代理實現的 ,通過創建內部類來代理緩存方法,這樣就會導致一個問題,類內部的方法調用類內部的緩存方法不會走代理,不會走代理,就不能正常創建緩存,所以每次都需要去調用數據庫。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章