Spring怎麼整合EhCache?還可以這樣……

Spring整合Ehcache測試項目

4.12


4.2.5.RELEASE
1.8.8
2.8.2
1.2.17
1.6.6




junit
junit
${junit.version}
test



org.springframework
spring-test
${spring.version}

test


org.springframework
spring-context-support
${spring.version}


org.springframework
spring-jdbc
${spring.version}


org.springframework
spring-webmvc
${spring.version}



org.springframework
spring-aspects
${spring.version}



org.aspectj
aspectjrt
${aspectj.version}


org.aspectj
aspectjweaver
${aspectj.version}



net.sf.ehcache
ehcache
${ehcache.version}



log4j
log4j
${log4j.version}


org.slf4j
slf4j-api
${slf4j.version}


org.slf4j
slf4j-log4j12
${slf4j.version}



2、添加ehcache配置文件ehcache.xml

默認情況下Ehcache會自動加載classpath根目錄下名為ehcache.xml文件,也可以將該文件放到其他地方在使用時指定文件的位置。


xsi:noNamespaceSchemaLocation="http://ehcache.org/ehcache.xsd">



maxElementsInMemory="10000"
eternal="false"
overflowToDisk="true"
timeToIdleSeconds="10"
timeToLiveSeconds="20"
diskPersistent="false"
diskExpiryThreadIntervalSeconds="120" />

maxElementsInMemory="1000"
eternal="false"
timeToIdleSeconds="10"
timeToLiveSeconds="20"
overflowToDisk="true" />

maxElementsInMemory="10000"
maxElementsOnDisk="100000"
eternal="false"
timeToIdleSeconds="1800"

timeToLiveSeconds="1800"
overflowToDisk="true"
diskPersistent="false" />

maxElementsInMemory="10000"
maxElementsOnDisk="100000"
eternal="false"
timeToIdleSeconds="3600"
timeToLiveSeconds="3600"
overflowToDisk="true"
diskPersistent="false" />

maxElementsInMemory="10000"
maxElementsOnDisk="100000"
eternal="false"
timeToIdleSeconds="86400"
timeToLiveSeconds="86400"
overflowToDisk="true"
diskPersistent="false" />

cache元素屬性說明:

name:緩存名稱

maxElementsInMemory:內存中最大緩存對象數

maxElementsOnDisk:硬盤中最大緩存對象數,若是0表示無窮大

eternal:true表示對象永不過期,此時會忽略timeToIdleSeconds和timeToLiveSeconds屬性,默認為false

overflowToDisk:true表示當內存緩存的對象數目達到了maxElementsInMemory界限後,會把溢出的對象寫到硬盤緩存中。注意:如果緩存的對象要寫入到硬盤中的話,則該對象必須實現了Serializable接口才行。

diskSpoolBufferSizeMB:磁盤緩存區大小,默認為30MB。每個Cache都應該有自己的一個緩存區。

diskPersistent:是否緩存虛擬機重啟期數據,是否持久化磁盤緩存,當這個屬性的值為true時,系統在初始化時會在磁盤中查找文件名 為cache名稱,後綴名為index的文件,這個文件中存放了已經持久化在磁盤中的cache的index,找到後會把cache加載到內存,要想把 cache真正持久化到磁盤,寫程序時注意執行net.sf.ehcache.Cache.put(Element element)後要調用flush()方法。

diskExpiryThreadIntervalSeconds:磁盤失效線程運行時間間隔,默認為120秒。

timeToIdleSeconds: 設定允許對象處於空閒狀態的最長時間,以秒為單位。當對象自從最近一次被訪問後,如果處於空閒狀態的時間超過了timeToIdleSeconds屬性 值,這個對象就會過期,EHCache將把它從緩存中清空。只有當eternal屬性為false,該屬性才有效。如果該屬性值為0,則表示對象可以無限 期地處於空閒狀態。

timeToLiveSeconds:設定對象允許存在於緩存中的最長時間,以秒為單位。當對象自從被存放到緩存中後,如果處於緩存中的時間超過了 timeToLiveSeconds屬性值,這個對象就會過期,EHCache將把它從緩存中清除。只有當eternal屬性為false,該屬性才有 效。如果該屬性值為0,則表示對象可以無限期地存在於緩存中。timeToLiveSeconds必須大於timeToIdleSeconds屬性,才有意義。

memoryStoreEvictionPolicy:當達到maxElementsInMemory限制時,Ehcache將會根據指定的策略去清理內存。可選策略有:LRU(最近最少使用,默認策略)、FIFO(先進先出)、LFU(最少訪問次數)。

3、添加spring配置文件application.xml


xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
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/context http://www.springframework.org/schema/beans/spring-context.xsd
http://www.springframework.org/schema/cache http://www.springframework.org/schema/cache/spring-cache.xsd">











4、創建EhcacheService接口

package top.jimc.ehcache.service;
import top.jimc.ehcache.po.User;
/**
* @author Jimc.
* @since 2018/9/21.
*/
public interface EhcacheService {
String getTimestamp(String param);
String getDataFromDB(String key);
void removeDataAtDB(String key);
String refreshData(String key);
User findUserById(String userId);
void removeUserById(String userId);
void removeAllUser();
}

5、創建EhcacheServiceImpl實現類

package top.jimc.ehcache.service.impl;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.CachePut;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import top.jimc.ehcache.po.User;
import top.jimc.ehcache.service.EhcacheService;
/**
* @author Jimc.
* @since 2018/9/21.
*/
@Service
public class EhcacheServiceImpl implements EhcacheService {
@Cacheable(value = "cacheTest", key = "#param")
public String getTimestamp(String param) {
return String.valueOf(System.currentTimeMillis());
}
@Cacheable(value = "cacheTest", key = "#key")
public String getDataFromDB(String key) {
System.out.println("模擬從數據庫中獲取數據...");
return key + ":" + String.valueOf(Math.round(Math.random()*1000000));
}
@CacheEvict(value = "cacheTest", key = "#key")
public void removeDataAtDB(String key) {
System.out.println("模擬從數據庫中刪除數據...");

}
@CachePut(value = "cacheTest", key = "#key")
public String refreshData(String key) {
System.out.println("模擬從數據庫中加載數據...");
return key + "::" + String.valueOf(Math.round(Math.random()*1000000));
}
@Cacheable(value = "cacheTest", key = "'user:' + #userId")
public User findUserById(String userId) {
System.out.println("模擬從數據庫中查詢數據");
return new User(userId, "Tom");
}
/**
* 清除cacheTest中指定key的緩存
*/
@CacheEvict(value = "cacheTest", key = "'user:' + #userId")
public void removeUserById(String userId) {
System.out.println("cacheTest remove:" + userId);
}
/**
* 清除cacheTest中全部緩存
*/
@CacheEvict(value = "cacheTest", allEntries = true)
public void removeAllUser() {
System.out.println("cacheTest remove all");
}
}

6、創建spring單元測試基類BaseJunit4Test

import org.junit.runner.RunWith;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
/**
* 測試基類
* @author Jimc.
* @since 2018/9/21.
*/
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {"classpath:applicationContext.xml"})
public class BaseJunit4Test {
}

7、創建測試類EhcacheServiceTest

import org.junit.Test;
import org.springframework.beans.factory.annotation.Autowired;
import top.jimc.ehcache.service.EhcacheService;
/**
* @author Jimc.
* @since 2018/9/21.
*/
public class EhcacheServiceTest extends BaseJunit4Test {
@Autowired
private EhcacheService ehcacheService;
@Test
public void testTimestamp() throws InterruptedException {
System.out.println("第一次調用:" + ehcacheService.getTimestamp("param"));
Thread.sleep(4000);
System.out.println("再過4秒之後調用:" + ehcacheService.getTimestamp("param"));
Thread.sleep(11000);
System.out.println("再過11秒之後調用:" + ehcacheService.getTimestamp("param"));
}
@Test
public void testDataCache() {
String key = "LiSi";
String value = ehcacheService.getDataFromDB(key);// 模擬從數據庫中獲取數據
System.out.println(value);
value = ehcacheService.getDataFromDB(key);// 從緩存中獲取數據,所以不執行該方法體
System.out.println(value);
ehcacheService.removeDataAtDB(key);// 從數據庫中刪除數據
value = ehcacheService.getDataFromDB(key); // 再次從數據庫中獲取數據(緩存數據刪除了,所以要重新獲取,執行方法體)
System.out.println(value);
}
@Test
public void testDataPut() {
String key = "WangWu";
String value = ehcacheService.refreshData(key);// 模擬從數據庫中加載數據
System.out.println(value);

value = ehcacheService.getDataFromDB(key);// 從緩存中獲取數據,所以不執行該方法體
System.out.println(value);
value = ehcacheService.refreshData(key);// 再次模擬從數據庫中加載數據,此時會執行方法體
System.out.println(value);
value = ehcacheService.getDataFromDB(key);// 從緩存中獲取數據,所以不執行該方法體
System.out.println(value);
}
@Test
public void testFindById(){
System.out.println(ehcacheService.findUserById("1"));// 先模擬從數據庫中查詢數據
System.out.println(ehcacheService.findUserById("1"));// 從緩存中取數據,不會執行方法體
}
@Test
public void testRemoveUserById(){
System.out.println(ehcacheService.findUserById("1"));// 先添加到緩存
ehcacheService.removeUserById("1");// 再刪除
System.out.println(ehcacheService.findUserById("1")); // 再查詢,如果不存在會執行方法體
}
@Test
public void testRemoveAllUser(){
// 先模擬從數據庫中查詢數據
System.out.println(ehcacheService.findUserById("1"));
System.out.println(ehcacheService.findUserById("2"));
ehcacheService.removeAllUser();// 清除cacheTest中全部緩存
// 重新模擬從數據庫中查詢數據,此時執行了方法體,證明緩存中的數據已被清除
System.out.println(ehcacheService.findUserById("1"));
System.out.println(ehcacheService.findUserById("2"));
}
}

8、執行結果

testTimestamp()執行結果:
第一次調用:1537515009017
再過4秒之後調用:1537515009017
再過11秒之後調用:1537515024027
testDataCache()執行結果:
模擬從數據庫中獲取數據...
LiSi:477475
LiSi:477475
模擬從數據庫中刪除數據...
模擬從數據庫中獲取數據...
LiSi:308969
testDataPut()執行結果:
模擬從數據庫中加載數據...
WangWu::77005
WangWu::77005
模擬從數據庫中加載數據...
WangWu::539514
WangWu::539514
testFindById()執行結果:
模擬從數據庫中查詢數據
top.jimc.ehcache.po.User@6736fa8d
top.jimc.ehcache.po.User@6736fa8d
testRemoveUserById()執行結果:
模擬從數據庫中查詢數據
top.jimc.ehcache.po.User@6736fa8d
cacheTest remove:1
模擬從數據庫中查詢數據
top.jimc.ehcache.po.User@50313382
testRemoveAllUser()執行結果:
模擬從數據庫中查詢數據
top.jimc.ehcache.po.User@6736fa8d
模擬從數據庫中查詢數據
top.jimc.ehcache.po.User@52815fa3

cacheTest remove all
模擬從數據庫中查詢數據
top.jimc.ehcache.po.User@1cb346ea
模擬從數據庫中查詢數據
top.jimc.ehcache.po.User@4c012563

9、註解基本使用詳解

Spring對緩存的支持類似於對事務的支持。

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

(1)@Cacheable

表明所修飾的方法是可以緩存的:當第一次調用這個方法時,它的結果會被緩存下來,在緩存的有效時間內,以後訪問這個方法都直接返回緩存結果,不再執行方法中的代碼段。

這個註解可以用condition屬性來設置條件,如果不滿足條件,就不使用緩存能力,直接執行方法。

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

參數:

  • alue:緩存位置名稱,不能為空,如果使用EHCache,就是ehcache.xml中聲明的cache的name, 指明將值緩存到哪個Cache中
  • key:緩存的key,默認為空,既表示使用方法的參數類型及參數值作為key,支持SpEL,如果要引用參數值使用井號加參數名,如:#userId,一般來說,我們的更新操作只需要刷新緩存中某一個值,所以定義緩存的key值的方式就很重要,最好是能夠唯一,因為這樣可以準確的清除掉特定的緩存,而不會影響到其它緩存值 , 本例子中使用實體加冒號再加ID組合成鍵的名稱,如”user:1”、”order:223123”等
  • condition:觸發條件,只有滿足條件的情況才會加入緩存,默認為空,既表示全部都加入緩存,支持SpEL

(2)@CachePut

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

(3)@CacheEvict

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

參數:

  • value:緩存位置名稱,不能為空,同上
  • key:緩存的key,默認為空,同上
  • condition:觸發條件,只有滿足條件的情況才會清除緩存,默認為空,支持SpEL
  • allEntries:true表示清除value中的全部緩存,默認為false

加Java架構師進階交流群獲取Java工程化、高性能及分佈式、高性能、深入淺出。高架構。性能調優、Spring,MyBatis,Netty源碼分析和大數據等多個知識點高級進階乾貨的直播免費學習權限 都是大牛帶飛 讓你少走很多的彎路的 群.號是 338549832 對了 小白勿進 最好是有開發經驗

注:加群要求

1、具有工作經驗的,面對目前流行的技術不知從何下手,需要突破技術瓶頸的可以加。

2、在公司待久了,過得很安逸,但跳槽時面試碰壁。需要在短時間內進修、跳槽拿高薪的可以加。

3、如果沒有工作經驗,但基礎非常紮實,對java工作機制,常用設計思想,常用java開發框架掌握熟練的,可以加。

4、覺得自己很牛B,一般需求都能搞定。但是所學的知識點沒有系統化,很難在技術領域繼續突破的可以加。

5.阿里Java高級大牛直播講解知識點,分享知識,多年工作經驗的梳理和總結,帶著大家全面、科學地建立自己的技術體系和技術認知!


分享到:


相關文章: