1. 程式人生 > >如果有人問你 JFinal 如何整合 EhCache,把這篇文章甩給他

如果有人問你 JFinal 如何整合 EhCache,把這篇文章甩給他

廢話不多說,就說一句:在 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,還是先更新快取呢?

謝謝大家的閱讀,原創不易,喜歡就點個贊,這將是我最強的寫作動力。如果你覺得文章對你有所幫助,也蠻有趣的,就關注一下我的公眾號,謝謝。

&n