廢話不多說,就說一句:在 JFinal 中內建 EhCache,可以提高系統的并發通路速度。
可能有人會問 JFinal 是什麼,EhCache 是什麼,簡單解釋一下。
JFinal 是一個基于Java 語言的極速 Web 開發架構,用起來非常爽,誰用誰知道。EhCache 是一個純 Java 的程序内緩存架構,具有快速、精幹的特點,用起來非常爽,誰用誰知道。
JFinal 本身已經內建了 EhCache 這個緩存插件,但預設是沒有啟用的。那怎麼啟用呢?
請随我來。
01、在 pom.xml 中加入 EhCache 依賴
<dependency>
<groupId>net.sf.ehcache</groupId>
<artifactId>ehcache-core</artifactId>
<version>2.6.11</version>
</dependency>
02、在 JFinalConfig 中配置 EhCachePlugin
public class DemoConfig extends JFinalConfig {
public void configPlugin(Plugins me) {
me.add(new EhCachePlugin());
}
}
基于 JFinal 的 Web 項目需要建立一個繼承自 JFinalConfig 類的子類,該類用于對整個 Web 項目進行配置。
03、添加 ehcache.xml
在項目的 src 目錄 / resources 目錄下添加 ehcache.xml 檔案,該檔案的初始内容如下所示。
<?xml version="1.0" encoding="UTF-8"?>
<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="ehcache.xsd"
updateCheck="false" monitoring="autodetect"
dynamicConfig="true">
<diskStore path="java.io.tmpdir"/>
<defaultCache
maxEntriesLocalHeap="10000"
eternal="false"
timeToIdleSeconds="120"
timeToLiveSeconds="120"
diskSpoolBufferSizeMB="30"
maxEntriesLocalDisk="10000000"
diskExpiryThreadIntervalSeconds="120"
memoryStoreEvictionPolicy="LRU"
statistics="false">
<persistence strategy="localTempSwap"/>
</defaultCache>
</ehcache>
簡單解釋一下常用的配置項,否則大家在配置的時候容易猶豫不決。
1)maxEntriesLocalHeap:記憶體中最大緩存對象數
2)eternal:true 表示對象永不過期,此時會忽略 timeToIdleSeconds 和 timeToLiveSeconds 屬性,預設為 false
3)timeToIdleSeconds:對象最近一次被通路後的閑置時間,如果閑置的時間超過了 timeToIdleSeconds 屬性值,這個對象就會過期,EhCache 将把它從緩存中清空;即緩存被建立後,最後一次通路時間到緩存失效的時候之間的間隔,機關為秒(s)
4)timeToLiveSeconds:對象被存放到緩存中後存活時間,如果存活時間超過了 timeToLiveSeconds 屬性值,這個對象就會過期,EhCache 将把它從緩存中清除;即緩存被建立後,能夠存活的最長時間,機關為秒(s)
假如我們現在增加以下配置:
<cache name="keywordsCache"
maxEntriesLocalHeap="500"
eternal="false"
overflowToDisk="true"
diskPersistent="true"
timeToIdleSeconds="300"
timeToLiveSeconds="600">
</cache>
結合之前的預設緩存配置,再來對比介紹下,大家就完全掌握了。
1)name 為該緩存的名字,後續使用緩存的時候要用到。
2)overflowToDisk:true 表示記憶體中緩存的對象數目達到了 maxEntriesLocalHeap 界限後,會把溢出的對象寫到硬碟緩存中。此時的對象必須實作要實作 Serializable 接口(為什麼?歡迎檢視我以前的文章 Java Serializable:明明就一個空的接口嘛)。
3)diskPersistent:是否緩存虛拟機重新開機時的資料
再來了解一下 timeToIdleSeconds 和 timeToLiveSeconds 這兩個配置項。
timeToIdleSeconds="300"
timeToLiveSeconds="600"
以上表示,一個資料被添加進緩存後,該資料能夠在緩存中存活的最長時間為 600 秒()timeToLiveSeconds);在這 600 秒内,假設不止一次去緩存中取該資料,那麼相鄰 2 次擷取資料的時間間隔如果小于 300 秒(timeToIdleSeconds),則能成功擷取到資料;但如果最近一次擷取到下一次擷取的時間間隔超過了 300 秒,那麼,将得到 null,因為此時該資料已經被移出緩存了。
04、使用 CacheKit 操作緩存
CacheKit 類是 JFinal 提供的緩存操作工具類,使用起來非常簡便。
Map<String, Keywords> map = CacheKit.get("keywordsCache", "keywordMap");
if (map == null) {
map = new HashMap<>();
List<Keywords> keywordList = dao.findAll();
for (Keywords item : keywordList) {
map.put(item.getKeyword(), item);
}
CacheKit.put("keywordsCache", "keywordMap", map);
}
CacheKit 中有兩個最重要的方法:
1)
get(String cacheName, Object key)
,從 cache 中取資料。
2)
put(String cacheName, Object key, Object value)
,将資料放入 cache 中。
參數 cacheName 與 ehcache.xml 中的
<cache name="keywordsCache" …>
name 屬性值對應,這個很好了解。
參數 key 是指取值用到的 key;參數 value 是被緩存的資料,這個其實也好了解。比如在上面的代碼中,我們使用了
keywordsCache
這個配置項,在裡面放了一個 HashMap,key 為
keywordMap
,value 就是 map 這個對象。
JFinal 内部提供了很多使用 Ehcache 的工具方法,比如:
List<Keywords> keywordList = dao.findByCache("keywordsCache", "keywordList", "select * from keywords");
這段代碼的作用就是,當我們要從資料庫中查詢 Keywords 的時候,先從 Ehcache 緩存中取,如果緩存失效的話,再從資料庫中取。
我是怎麼知道的呢?當然不是靠猜的,我們來看一下源碼。
public List<M> findByCache(String cacheName, Object key, String sql, Object... paras) {
Config config = _getConfig();
ICache cache = config.getCache();
List<M> result = cache.get(cacheName, key);
if (result == null) {
result = find(config, sql, paras);
cache.put(cacheName, key, result);
}
return result;
}
05、最後
當資料的查詢頻率很高,遠大于修改的頻率,就要使用緩存了,這可以在很大程度上提高系統的性能。那現在我就提一個問題了,假如現在要修改一下資料,是先更新 DB,還是先更新緩存呢?
謝謝大家的閱讀,原創不易,喜歡就點個贊,這将是我最強的寫作動力。如果你覺得文章對你有所幫助,也蠻有趣的,就關注一下我的公衆号,謝謝。