天天看點

Spring Cache緩存架構使用

作者:頑石九變

說明

Spring Cache是Spring架構的緩存抽象,內建了各種主流緩存實作(ConcurrentMap、redis、ehcache、Caffeine等)

Spring預設使用ConcurrentMap作為緩存;如果工程中引入了redis配置,則會使用redis作為緩存

Spring通過CacheManager判斷具體使用哪個緩存,每個緩存都有一個具體的CacheManager(比如:EhCacheCacheManager,RedisCacheManager,CaffeineCacheManager),如果沒有配置任何的CacheManager,則會使用ConcurrentMap作為緩存

常用注解說明

Spring Cache緩存架構使用

SpEL表達式說明

注解中key的寫法是SpEL表達式,

Spring Cache提供了一些供我們使用的SpEL上下文資料,下表直接摘自Spring官方文檔:

Spring Cache緩存架構使用

說明:

1、當我們要使用root對象的屬性作為key時我們也可以将“#root”省略,因為Spring預設使用的就是root對象的屬性。如:

@Cacheable(key = "targetClass + methodName +#p0")
           

2、使用方法參數時我們可以直接使用“#參數名”或者“#p參數index”。如:

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

SpEL提供了多種運算符

Spring Cache緩存架構使用

在工程中使用

1、引入依賴

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-cache</artifactId>
</dependency>
           

2、在工程中配置

在啟動類中增加注解 @EnableCaching 開啟緩存功能

在application.properties中添加可選自定義配置

Spring Cache緩存架構使用

詳細配置項可參考(org.springframework.boot.autoconfigure.cache.CacheProperties)

3、在代碼中使用

1)儲存時,緩存傳回值

@CachePut(value="dict",key="targetClass +'AppDictType'+ #entity.dictTypeCd")
@Transactional(readOnly = false)
public AppDictType save(AppDictType entity) {
    return dictTypeDao.save(entity);
}
           

2)查詢時,先讀取緩存,如果緩存不存在,則執行方法查詢,然後更新緩存

@Cacheable(value="dict",key="targetClass +'AppDictType'+ #dictTypeCd")
public AppDictType findByDictTypeCd(String dictTypeCd) {
    return dictTypeDao.findByDictTypeCd(dictTypeCd);
}
           

3)删除時,清空緩存

@Transactional(readOnly = false)
@CacheEvict(value="dict",key="targetClass +'AppDictType'+ #dictTypeCd")
public void deleteByDictTypeCd(String dictTypeCd) {
    dictTypeDao.deleteByDictTypeCd(dictTypeCd);
}
           

4)測試用例

@Test
public void testCache() {
    String dictTypeCd = "test01";
    AppDictType entity = new AppDictType();
    entity.setDictTypeCd(dictTypeCd);
    entity.setDictTypeName("測試01");
    // 新增記錄,并放入緩存
    entity = dictService.save(entity);
    // 查詢緩存
    AppDictType dict = dictService.findByDictTypeCd(dictTypeCd);
    logger.info("dict1:{}", JsonUtil.obj2Json(dict));
    // 修改資料
    entity.setDictTypeName("測試0011");
    entity = dictService.save(entity);
    // 查詢緩存,資料發生變化
    AppDictType dict2 = dictService.findByDictTypeCd(dictTypeCd);
    logger.info("dict2:{}", JsonUtil.obj2Json(dict3));
    // 删除記錄,并清除緩存
    dictService.deleteByDictTypeCd(dictTypeCd);
    // 查詢記錄為空
    AppDictType dict3 = dictService.findByDictTypeCd(dictTypeCd);
    logger.info("dict3:{}", JsonUtil.obj2Json(dict4));
}
           

4、使用redis緩存

1)引入redis依賴

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
           

2)在application.properties 配置redis連結參數

spring.redis.host=192.168.1.144
spring.redis.port=6379
           

5、使用ehcache緩存

1)引入ehcache依賴

<dependency>
    <groupId>net.sf.ehcache</groupId>
    <artifactId>ehcache</artifactId>
</dependency>
           

2)在application.properties 配置redis連結參數

#可以強制指定,也可以不指定,系統會自動偵測
#spring.cache.type=ehcache
spring.cache.ehcache.config=classpath:ehcache.xml
           

3)增加ehcache.xml

<?xml version="1.0" encoding="UTF-8"?>
<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../config/ehcache.xsd">
     <!--當ehcache把資料寫到硬碟上時,将寫到這個目錄下,java.io.tmpdir:為預設臨時檔案路徑-->  
    <diskStore path="java.io.tmpdir"/>
  <!--defaultCache:echcache的預設緩存政策  -->
    <defaultCache
            maxElementsInMemory="10000"
            eternal="false"
            timeToIdleSeconds="120"
            timeToLiveSeconds="120"
            maxElementsOnDisk="10000000"
            diskExpiryThreadIntervalSeconds="120"
            memoryStoreEvictionPolicy="LRU">
        <persistence strategy="localTempSwap"/>
    </defaultCache>
   <!--指定名稱的緩存配置-->
    <cache name="fileConfig"
            maxElementsInMemory="10000"
            eternal="false"
            timeToIdleSeconds="120"
            timeToLiveSeconds="120"
            maxElementsOnDisk="10000000"
            diskExpiryThreadIntervalSeconds="120"
            memoryStoreEvictionPolicy="LRU">
        <persistence strategy="localTempSwap"/>
    </cache>
        <!-- 
        緩存配置說明:
        name:緩存名稱。
        maxElementsInMemory:緩存最大對象個數。
        eternal:對象是否永久有效,一但設定了,timeout将不起作用。
        timeToIdleSeconds:設定對象在失效前的允許閑置時間(機關:秒)。僅當eternal=false對象不是永久有效時使用,可選屬性,預設值是0,也就是可閑置時間無窮大。
        timeToLiveSeconds:設定對象在失效前允許存活時間(機關:秒)。最大時間介于建立時間和失效時間之間。僅當eternal=false對象不是永久有效時使用,預設是0.,也就是對象存活時間無窮大。
        overflowToDisk:當記憶體中對象數量達到maxElementsInMemory時,Ehcache将會對象寫到磁盤中。
        diskSpoolBufferSizeMB:這個參數設定DiskStore(磁盤緩存)的緩存區大小。預設是30MB。每個Cache都應該有自己的一個緩沖區。
        maxElementsOnDisk:硬碟最大緩存個數。
        diskPersistent:是否緩存虛拟機重新開機期資料 Whether the disk store persists between restarts of the Virtual Machine. The default value is false.
        diskExpiryThreadIntervalSeconds:磁盤失效線程運作時間間隔,預設是120秒。
        memoryStoreEvictionPolicy:當達到maxElementsInMemory限制時,Ehcache将會根據指定的政策去清理記憶體。預設政策是LRU(最近最少使用)。你可以設定為FIFO(先進先出)或是LFU(較少使用)。
        clearOnFlush:記憶體數量最大時是否清除。
        -->
</ehcache>
           

4)在方法中指定cacheName

@Cacheable("fileConfig")
public SysFileConfig findByAppCode(String appCode) {
    SysFileConfig config = fileConfigDao.selectOne(new QueryWrapper<SysFileConfig>().eq("app_code", appCode));
    return config;
}
           

5、關閉spring cache緩存

如果已經開啟了@EnableCaching緩存,在某些環境下又不想使用緩存,又不想修改原有代碼。

可通過如下配置關閉緩存:

spring.cache.type=none
           

參考

  • https://www.cnblogs.com/yueshutong/p/9381540.html
  • https://docs.spring.io/spring-boot/docs/2.2.0.RELEASE/reference/htmlsingle/#boot-features-caching