今天在作統計報表的時候,考慮到數據比較多,因此在項目中集成ehCache減輕數據庫請求壓力。看似簡單,網上參考也比較多,可是還遇到了幾處坑,在此記錄一下。 ⊙﹏⊙bjava
隨手筆記,比較簡單,想要具體瞭解的能夠網上看看大神的博客spring
(1)、springboot集成了ehcache,配置了過時時間timeToIdleSeconds,發現就是不生效,問度娘後才知道須要在properties文件中指定緩存類型,否則spring boot 使用默認SimpleCacheConfiguration,不是用的ehcache。數據庫
(2)、測試的時候第一次請求接口返回正常數據,第二次查詢緩存的時候會報java.io.Serializable這個錯,是由於我返回的實體類沒作序列化。緩存
解決方案在下面springboot
<!--開啓 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>
<?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"/> <!--defaultCache:echcache的默認緩存策略 --> <!-- 緩存配置 diskStore:指定數據在磁盤中的存儲位置。 name:緩存名稱。 defaultCache:當藉助CacheManager.add("demoCache")建立Cache時,EhCache便會採用<defalutCache/>指定的的管理策略,如下屬性是必須的: 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:內存數量最大時是否清除。 --> <defaultCache maxElementsInMemory="10000" eternal="false" timeToIdleSeconds="120" timeToLiveSeconds="120" maxElementsOnDisk="10000000" diskExpiryThreadIntervalSeconds="120" memoryStoreEvictionPolicy="LRU"> <persistence strategy="localTempSwap"/> </defaultCache> <cache name="userCache" maxElementsInMemory="10000" eternal="false" timeToIdleSeconds="120" timeToLiveSeconds="120" maxElementsOnDisk="10000000" diskExpiryThreadIntervalSeconds="120" memoryStoreEvictionPolicy="LRU"> <persistence strategy="localTempSwap"/> </cache> </ehcache>
spring.cache.type=ehcache spring.cache.ehcache.config=classpath:META-INF/mybatis/ehcache.xml
五、以上集成工做已經完成,那如何在代碼中使用呢? 以下mybatis
/** * 查詢請求記錄數據統計 * * @param docNos * @return */ @Cacheable(key = "#startDate+'-'+#endDate+'-'+#type",value="userCache") public ResponseMessage<List<Map<String, Object>>> selectReport(String startDate, String endDate, String docTemplateCode,String type) { ResponseMessage<List<Map<String, Object>>> rsdto = new ResponseMessage<>(); List<Map<String, Object>> list=new ArrayList<>(); if(StringUtils.isBlank(startDate) || StringUtils.isBlank(endDate)) { ResponseUtil.setResult(rsdto, null, ErrorCodeEnum.PARAMERROR, false); return rsdto; } /*if(StringUtils.isBlank(docTemplateCode)) { ResponseUtil.setResult(rsdto, null, ErrorCodeEnum.PARAMERROR, false); return rsdto; }*/ if(StringUtils.isBlank(type)) { ResponseUtil.setResult(rsdto, null, ErrorCodeEnum.PARAMERROR, false); return rsdto; } Integer length=0; try { length= ReportTypeEnum.getEnum(type).getValue(); list=docRecordTunnel.selectReportByDateTime(startDate, endDate, docTemplateCode, length); ResponseUtil.setResult(rsdto, list, ErrorCodeEnum.SUCCESS,true); } catch (Exception e) { log.error("DocRecordController.selectReport查詢失敗", e); ResponseUtil.setResult(rsdto, null, ErrorCodeEnum.ERROR, false); } return rsdto; }
注: 返回的實體類須要作序列化,不然查詢緩存的時候會報錯。以下圖spring-boot
通常狀況下,咱們在Sercive層進行對緩存的操做。先介紹 Ehcache 在 Spring 中的註解:
* @Cacheable : Spring在每次執行前都會檢查Cache中是否存在相同key的緩存元素,若是存在就再也不執行該方法,而是直接從緩存中獲取結果進行返回,不然纔會執行並將返回結果存入指定的緩存中。
* @CacheEvict : 清除緩存。
* @CachePut : @CachePut也能夠聲明一個方法支持緩存功能。使用@CachePut標註的方法在執行前不會去檢查緩存中是否存在以前執行過的結果,而是每次都會執行該方法,並將執行結果以鍵值對的形式存入指定的緩存中。 測試
簡單來講,Cacheable 通常用於查詢,CacheEvict 用於新增清除緩存,CachePut 用於更新;其中,value 指的是 ehcache.xml 中的緩存策略空間;key 指的是緩存的標識,同時能夠用 # 來引用參數。上面代碼引用參數爲多個組合做爲緩存key 。spa