是否經常在爲數據查詢較慢而發愁,當你須要查詢數據巨量較大而更改較少的數據時,不妨使用緩存技術,他會帶給你更加效率的查詢。今天,和你們分享一下利用Spring管理Encache來實現數據的緩存。java
Ehcache是一個純Java的進程內緩存框架,它支持read-only和read/write緩存,內存和磁盤緩存。使用過hibernate的童鞋應該都清楚,hibernate的二級緩存就能夠採用ehcache來實現。這裏就不過多講解ehcache的原理,它的底層實際是一個Map,以key-value的形式保存緩存數據,下面對ehcache.xml作一下介紹。spring
在上面的配置文件中,配置了兩個cache,一個是默認的缺省的緩存策略,一個是自定義的methodCache,其中各個屬性的做用分別以下:數據庫
diskStore中的path:設置緩存文件的建立位置,好比:user.home(用戶主目錄),user.dir (用戶當前工做目錄),java.io.tmpdir(系統默認臨時文件路徑),以及自定義的存儲位置(如:D:\cache\onlinestudy);編程
name: Cache的惟一標識;緩存
maxElementsInMemory: 內存中最大緩存對象數;服務器
maxElementsOnDisk: 磁盤中最大緩存對象數, 如果0表示無窮大;app
eternal: Element是否永久有效, 一但設置了, timeout 將不起做用;框架
overflowToDisk: 當內存中 Element 數量達到 maxElementsInMemory 時, Ehcache 是否將 Element 寫到磁盤中;ide
timeToLiveSeconds:設置Element 在失效前容許存活時間. 最大時間介於建立時間和失效時間之間.僅當 Element 不是永久有效時使用, 默認爲 0 : 表示存活時間無窮大;性能
diskPersistent:是否緩存虛擬機重啓期數據;
diskExpiryThreadIntervalSeconds: 磁盤失效線程運行時間間隔, 默認是120秒;
diskSpoolBufferSizeMB:這個參數設置DiskStore(磁盤緩存) 的緩存區大小, 默認30MB;
memoryStoreEvictionPolicy:當達到maxElementsInMemory限制時, Ehcache將會根據指定的策略去清理內存.默認策略是LRU(最近最少使用). 能夠設置爲 FIFO(先進先出) 或 LFU(較少使用)。
對應上面參數的具體設置,就須要根據項目的實際狀況而定,綜合考慮程序的響應時間、內存佔用空間等效率因素。
在程序的容許範圍內使用查詢緩存,能在必定程度上提升程序的性能,提升訪問速度,下降服務器的壓力。哪些地方咱們須要使用查詢緩存呢,一些常常被訪問且變更性小的數據建議使用查詢緩存,好比:系統的菜單,常常被訪問的統計數據等。
經過上面的準備,就能夠實現查詢緩存了。查詢緩存分爲兩部分,一是緩存的寫入/更新,二是緩存的讀取。緩存經過ehcache來實現,而對他的操做就經過Spring AOP來控制。
好比給OPM項目(spring3+struts2+spring JdbcTemplate)增長查詢緩存的功能,具體步驟以下:
1.須要給項目增長ehcache相關的jar包和ehcache.xml配置文件,這裏咱們就採用上面給出的ehcache.xml中的methodCache做爲此次的查詢緩存;
2.用spring管理ehcache,在applicationContext.xml中增長以下配置。
3.切面編程(AOP)的聲明,本次使用AOP註解的方式來實現,所以須要在applicationContext.xml中聲明,而且還須要指定spring自動掃描註冊的包類配置項以下。
4. 編寫aspect類,該QueryCache類中主要有兩個功能方法,一個用於查詢緩存,一個用於清除緩存,代碼以下。
上面的第一個advice方法queryCache就是對com.travelsky.ccboy.dao包及其子包中類的以query或find開頭的方法進行環繞通知,首先程序在調用目標查詢方法以前,先去cache中查找是否有對應的查詢結果,若是有則直接放回結果,若是沒有就去調用目標方法,而後將查詢的結果保存到緩存中,再返回結果,就避免了每次都去數據庫中查找,則樣就提升了查詢的速度。
這裏有一個關鍵的問題就是怎麼來構造cache的key,這裏使用了目標方法的完整類路徑+方法名+查詢參數值做爲key,這就保證了對同一個方法使用不一樣的參數查詢能夠有不一樣的緩存;還須要注意的問題有:(1)若是目標查詢方法的參數是一個引用對象,好比queryPersonPO,則咱們須要重寫QueryPersonPO類的equals方法,以保證建立key的有效性;(2)因爲ehcache的緩存使用了內存/磁盤緩存,因此咱們須要對被緩存的對象類(也就是目標查詢方法返回的對象)進行序列化,以保證能正確的緩存和讀取;(3)在方法的上面考慮使用了synchronized,目的是避免多人在同一時刻訪問時重複的查詢數據庫,確保一次查詢成功,多人共享數據的目的。
緩存的清除出了經過配置的ehcache.xml中的規則管理以外,上面還提供了一個清除緩存的clean方法,使用了After return advice,原理是隻要調用了以update或delete開頭的方法,這就把這個類的緩存都清除,下次調用查詢方法時再進行緩存。
下面是測試運行結果。
從上圖能夠看出,兩個線程同時使用相同的參數訪問了同一個方法兩次,而實際訪問數據庫只有一次,當第一次訪問成功後,後面訪問的時間就大大減小了。