1. 程式人生 > >SpringMVC中EhCache實現快取資料

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;
    }

}