SpringMVC中EhCache實現快取資料
EhCache 是一個純Java的程序內快取框架,具有快速、精幹等特點,是Hibernate中預設CacheProvider。Ehcache是一種廣泛使用的開源Java分散式快取。主要面向通用快取,Java EE和輕量級容器。它具有記憶體和磁碟儲存,快取載入器,快取擴充套件,快取異常處理程式,一個gzip快取servlet過濾器,支援REST和SOAP api等特點。ehcache直接在jvm虛擬機器中快取,速度快,效率高;但是快取共享麻煩,叢集分散式應用不方便。
EhCache快取資料實現步驟:
②引入xml配置檔案
ehcache.xml:
maxElementsInMemory:快取中允許建立的最大物件數 eternal:快取中物件是否為永久的,如果是,超時設定將被忽略,物件從不過期。 timeToIdleSeconds:快取資料的鈍化時間,也就是在一個元素消亡之前,兩次訪問時間的最大時間間隔值,這隻能在元素不是永久駐留時有效,如果該值是 0 就意味著元素可以停頓無窮長的時間。 timeToLiveSeconds:快取資料的生存時間,也就是一個元素從構建到消亡的最大時間間隔值,這隻能在元素不是永久駐留時有效,如果該值是0就意味著元素可以停頓無窮長的時間。 overflowToDisk:記憶體不足時,是否啟用磁碟快取。 memoryStoreEvictionPolicy:快取滿了之後的淘汰演算法。LRU和FIFO演算法這裡就不做介紹。LFU演算法直接淘汰使用比較少的物件,在記憶體保留的都是一些經常訪問的物件。對於大部分網站專案,該演算法比較適用。 如果應用需要配置多個不同命名並採用不同引數的Cache,可以相應修改配置檔案,增加需要的Cache配置即可。
<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="config/ehcache.xsd"> <!-- 磁碟儲存的路徑 --> <diskStore path="C:/ehcache" /> <!-- 一個快取 --> <cache name="articleCache" maxElementsInMemory="1" eternal="true" timeToIdleSeconds="0" timeToLiveSeconds="0" overflowToDisk="true" maxElementsOnDisk="1000000" diskPersistent="false" diskExpiryThreadIntervalSeconds="120" memoryStoreEvictionPolicy="LRU" /> </ehcache>
③快取操作 :
CacheManager cm = CacheManager.create();//建立CacheManager快取管理物件 Cache cache = cm.getCache("demoCache");// 通過cm可以生成指定名稱的Cache物件 cm.removeCache("demoCache");//移除指定名稱的Cache物件 //有了Cache物件之後就可以開始操作Cache物件了 Element element = new Element("key", "value");//往Cache物件中新增元素 cache.put(element);// 將資料儲存到cache中 cache.get("key");//從cache中取回元素 cache.remove("key");//從Cache中移除一個元素 //==============注意:對於快取的物件都是必須可序列化的。==============
這裡拿個我目前階段正在做的專案來舉例項吧:
spring配置檔案中建立CacheManager快取管理物件
<bean class="net.sf.ehcache.CacheManager" factory-method="create"></bean>
抽取EhcacheUtil工具類:
/**
* 實現快取資料的存取
*/
public class EhcacheUtil {
/**
* 從快取中獲取資料
* @param cm:快取管理物件
* @param cachename:ehcache.xml配置檔案中的name值
* @param key:在快取中儲存的資料對應存放值
* @return
*/
public static Element getElement(CacheManager cm,String cachename,String key){
Cache cache = cm.getCache(cachename);//通過cm可以生成指定名稱(cachename)的Cache物件
//對於以後查詢的種類會更多因此這個引數需要採用傳值 ex:articleCache,userCache,imageCache
Element element = cache.get(key);//從cache(key)中取回元素
return element;
}
/**
* 儲存資料到快取中
* @param cm:快取管理物件
* @param cachename:ehcache.xml配置檔案中的name值
* @param key:在快取中儲存的資料對應存放值
* @param value:在快取中儲存的資料
*/
public static void setElement(CacheManager cm,String cachename,String key,Object value){
Cache cache = cm.getCache(cachename);
Element element = new Element(key, value);
cache.put(element);//往cache(key)中新增元素
}
}
service中實現快取: 這裡看看方法queryCache中是怎麼快取資料,以及獲取快取中的資料即可,具體的還要根據自己的專案要求來~~
/**
* 文章業務邏輯處理:
* 增刪改查 + 實現快取
*/
@Service
public class ArticlesServiceImpl implements IArticlesService {
@Autowired
private ArticlesDaoImpl dao;
@Autowired
private CacheManager cm;//@Autowired注入spring配置檔案中建立CacheManager
private Boolean iscache=false; //iscache標識-->快取中區分增刪改 true:表示快取已經改變,就會重新整理之後查詢內容,false:在快取中查詢內容
@Override
public void addArticle(Articles article, ServletContext context) throws Exception {
String newName = createHtml(article, context);
article.setHtmlurl("/temp/"+newName);//設定htmlurl的值
dao.addArticle(article);
iscache=true;
}
@Override
public PageList<Articles> queryAll(Boolean flag, Conditions condition) throws Exception {
// return dao.queryAll(flag,condition);
PageList<Articles> pageList = queryCache(flag, condition,iscache);
iscache=false;
return pageList;
}
//快取中 當資料增刪改的時候-->執行重新查詢 否則就從快取中查詢內容 -->因此要注意一些邏輯 不要導致在快取中查詢不符合的內容
private PageList<Articles> queryCache(Boolean flag, Conditions condition, Boolean iscache) throws Exception {
//解決分頁問題
/**
* 快取中是儲存了多個element,element依據key來獲取
* 前臺儲存:beforelist1 -->末尾的數字1表示分頁查詢時的頁數
* 後臺儲存:afterlist1
*/
String key="";
if (flag) { //後臺
key="afterlist"+condition.getCurrentPage();
}else{ //前臺
key="beforelist"+condition.getCurrentPage();
}
System.out.println("前臺before,後臺after --> "+key);
Element element = EhcacheUtil.getElement(cm, "articleCache", key);//這裡的key的作用是不同的快取 get:從key快取中取資料
PageList<Articles> pageList = null;
if (element == null||iscache) {
/**
* 只要更新資料,以前的所有快取先清空 注意:這裡應該還要判斷文章型別type+title選擇的變化 如果變化 也應該清空快取 !!
*/
if(iscache){
// cm.removeCache("articleCache"); //只有增加、刪除、修改,才需要移除快取
cm.getCache("articleCache").removeAll();//移除articleCache中資料 這行程式碼很重要, 用上一行的程式碼會出錯-->空指標
}
pageList = dao.queryAll(flag, condition);
EhcacheUtil.setElement(cm, "articleCache", key, pageList);
} else {
pageList = (PageList<Articles>) element.getObjectValue();
}
return pageList;
}
}