一、Spring Boot ehcache 相關依賴
<!-- spring boot cache -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-cache</artifactId>
</dependency>
<!-- ehcache -->
<dependency>
<groupId>net.sf.ehcache</groupId>
<artifactId>ehcache</artifactId>
</dependency>
application.properties
ehcache相關配置
#整合spring
spring.cache.type=ehcache
#讀取ehcache.xml配置
spring.cache.ehcache.config=classpath:ehcache.xml
#打印日誌com.ljj換成項目的包名
logging.level.com.ljj=debug
ehcache.xml
在資源目錄下添加ehcache.xml文件
<!-- ehcache配置 -->
<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="http://ehcache.org/ehcache.xsd"
updateCheck="false">
<!-- 緩存路徑,用戶目錄下的base_ehcache目錄 -->
<diskStore path="user.home/base_ehcache"/>
<defaultCache
maxElementsInMemory="20000"
eternal="false"
timeToIdleSeconds="120"
timeToLiveSeconds="120"
overflowToDisk="true"
maxElementsOnDisk="10000000"
diskPersistent="false"
diskExpiryThreadIntervalSeconds="120"
memoryStoreEvictionPolicy="LRU"/>
<!--
緩存文件名:user,同樣的可以配置多個緩存
maxElementsInMemory:內存中最多存儲
eternal:外部存儲
overflowToDisk:超出緩存到磁盤
diskPersistent:磁盤持久化
timeToLiveSeconds:緩存時間
diskExpiryThreadIntervalSeconds:磁盤過期時間
-->
<cache name="userCache"
maxElementsInMemory="20000"
eternal="true"
overflowToDisk="true"
diskPersistent="false"
timeToLiveSeconds="0"
diskExpiryThreadIntervalSeconds="120"/>
</ehcache>
二、整合spring
spring boot ehcache的前期準備已經結束,現在開始整合spring使用。
重點在以下4個註解:
- @EnableCaching
- @Cacheable
- @CachePut
- @CacheEvict
1.@EnableCaching
在spring boot項目啓動類或配置類上添加使用緩存註解
2.@Cacheable
一般在服務層的查詢方法上使用。查詢的時候會先在緩存上查詢key是否存在,不存在則將結果保存到緩存。
@Cacheable(value = "userCache", key = "'userId:'+#id", condition = "#id < 10")
public User get(Long id) {
log.info("查詢用戶的【id】 = {}", id);
//假設從數據庫讀取了用戶數據
//User user = userDao.getUser(id);
return user;
}
@Cacheable表明所修飾的方法是可以緩存的。當第一次調用這個方法時,它的結果會被緩存下來,在緩存的有效時間內,以後訪問這個方法都直接返回緩存結果,不再執行方法中的代碼段。
@Cacheable的參數
- value:緩存位置名稱,不能爲空。如果使用EHCache,就是ehcache.xml中聲明的cache節點的name屬性值,指明將值緩存到哪個Cache中。
- key:緩存的key,默認爲空,既表示使用方法的參數類型及參數值作爲key。支持SpEL,如果要引用參數值使用井號加參數名(如:#id)。
- condition:觸發條件,只有滿足條件的情況纔會加入緩存,默認爲空,既表示全部都加入緩存,支持SpEL
一般來說,我們的更新操作只需要刷新緩存中的某一個值,所以定義緩存的key值的方式就很重要。key最好是能夠唯一,這樣我們就可以準確的清除掉特定的緩存,而不會影響到其它緩存。例子中就使用了實體加冒號再加ID組合成key的名稱(‘userId:’ + #id )。
tip:如果參數爲對象的情況,如:User。那麼我們可以通過#user.id來獲取對象的屬性。
3.@CachePut
一般在保存或更新方法上使用。此註解用於更新緩存的結果。
@CachePut(value = "userCache", key = "'user:'+#user.id")
public User saveOrUpdate(User user) {
//假設更新了數據庫的用戶數據
//userDao.saveOrUpdate(user)
log.info("保存或用戶【user】 = {}", user);
return user;
}
與@Cacheable不同,@CachePut不僅會緩存方法的結果,還會執行方法的代碼段。它支持的屬性和用法都與@Cacheable一致。一個緩存後就不執行代碼了,一個還要執行。
4.@CacheEvict
與@Cacheable功能相反,@CacheEvict表明所修飾的方法是用來刪除失效或無用的緩存數據。
@CacheEvict(value = "userCache", key = "'user:'+#id")
public void delete(Long id) {
//假設從數據庫刪除了用戶數據
//userDao.delete(id);
log.info("刪除用戶的【id】 = {}", id);
}
@CacheEvict參數
與@Cacheable參數不同的地方有2處。
- condition:觸發條件,只有滿足條件的情況纔會清除緩存,默認爲空,支持SpEL
- allEntries:true表示清除value中的全部緩存,默認爲false
測試
@Autowired
private UserService userService;
@Test
void saveAndGet() {
userService.saveOrUpdate(User.builder().id(4L).realName("user4").build());
log.debug("獲取id爲4的用戶:{}", userService.get(4L));
}
因爲使用了lombok工具,這裏說明一下過程。userService裏有上面3個註解的方法。調用saveOrUpdate(User)保存一個User實體持久化到本地,然後通過get(id)獲取這個User。在調用get(id)方法的時候並沒有觸發方法體裏的打印方法,因爲調用的時候先去緩存裏查詢了。