图片见:http://hi.baidu.com/stenlylee/blog/item/3dfb7dd998d3d1ec38012f64.html
實際的 Web Application 中,緩存 (cache) 是不可或缺的事。 JBoss Seam 當然也提供了多種緩存服務。在這系列的文中我會講講最高層,最易應用和最易理解的 PojoCache 以及 Page Fragment Cache 。
在使用緩存之前,我們首先建立一個 Hello World 程式作為藍本 (源碼 svn)。
<page view-id="/index.xhtml" action="#{complexWork.work}" />
這會讓 seam 在顯示 index.xhtml 前先執行 complexWork.work method。
@Stateful 代表這是個 SFSB。@Name 指定了它在 seam 中的名字,我們以後可以用 complexWork 在 seam 中稱呼它。work() 是我們的主要業務邏輯 ,它會等待一秒以模擬一些繁重的工作,再把 message 設定為 “Hello, World”。@Out annotation 會讓 seam 知道我們想在頁面上看到 message。
沒有甚麼值得一談的,只是把 message 顯示出來:
留意 console ,每次 refresh 網頁 SFSB 也在重新工作:
接著我們要為 SFSB 加入緩存 。
PojoCache 是 seam 內置的 Java 物件緩存組件。PojoCache 支援 JTA transaction manager,isolation level,replication,overflowing, eviction policy 等功能,要完整設定並不簡單。但要讓它可以供 seam 應用則不難,首先要在 resources 下加入設定檔 treecache.xml 。(源碼 svn)
這個設定檔中值得留意的是 Eviction Policy 。 Eviction Policy 是指 PojoCache 移除 cache 中的規則。現在 PojoCache 只支援 LRU (Least Recently Used) policy。現在的設定下,在 “/message” region 中最多可存放 100 個物件,每個物件最多可以保留 10 秒。詳細的設定可以參考 JBoss TreeCache Manual 中的LRU eviction policy。
接著在需要 PojoCache 的 component 中指定 Injection :
留意改動後的 work() 方法,使用 pojoCache 就如一般的 Map 一樣簡單。
使用 PojoCache 後再到 index.seam,會發現只有第一次啟動網頁時需要較長時間。
在之後十秒內再 refresh 網頁幾乎不用任何等待,這是由於我們設定了緩存有 10 秒的壽命。
在此我們己經成功設定 seam 使用 PojoCache 了!下面將會討論使用 Page Fragment Cache 以及手動移除 Cache 的方法。
直接在 component 中使用 PojoCache 讓我們可以在物件的層次控制緩存,雖然這可以很強大和靈活,但如果每個物件都要特別地作緩存,那業務的源碼就會充滿著緩存代碼,難以維護。這時候我們可以用 Page Fragment Cache。
(源碼 svn)
打開 view 的檔案 view/index.xhtml,加入 seam 的 <s:cache> tag。Seam 的 Page Fragment Cache 同樣是用 PojoCache 去實現,s:cache tag 中的 region 和 key 跟 PojoCache 中用法完全一樣。
同時在 SFSB 的 interface 和 implementation 加入方法 getMoreMessage():
public String getMoreMessage(){ log.info("retrieve moreMessage()"); return "Hello, again! (this message is component cached)"; }
運行的效果如下:
留意 console 的輸出:
在第一次之顯示之後,gerMoreMessage() 方法就沒有再被呼叫過,這是由於整個被 s:cache 包圍的組件也被緩存了。
要留意 PojoCache 並不像 Hibernate 的 second level cache,更改了的物件並不會自動把有關的 PojoCache 和 page fragment 自動 invalidate 掉。除了指定 Eviction Policy外,一些對更新敏感的資料需要用手動的方法移除。PojoCache 容許我們手動用 Region 和 Key 指定移除特定的緩存。
(源碼 svn)
public String flush(){ log.info("flush cache"); try { pojoCache.remove("/message", "complexTask"); pojoCache.remove("/message", "complexTask2"); } catch (CacheException ex) { log.warn("Unexpected error while remove cache... #0 #1, error=#2", "complexTask", "complexTask2", ex.getMessage()); } return "/index.xhtml"; }
使用 flush() 方法後指定的兩個緩存就會被移除。
加入移除緩存按鍵的主頁:
使用 flush() 後的 console ,是我們其待的結果:在 flush 後原本的 cache 不見了。
這一篇中我們試驗了Seam 的以下功能:
有一些東西我是沒有討論的,例如這裡只有講最簡單的本地緩存,Transaction Manager 和不同 Isolation Level 在應用中的影響等等…這些應用就得等高人指教了。
在 Seam 中使用 PojoCache 並不困難,基本的 Seam 己包括所有需要的組件。然而,實際應用前我們必需要先設定它,這卻是異常神秘和讓人困惑的。在 Seam 的文件中有關緩存的課題我們只能找到這一句:JBossCache 有許多嚇人和讓人困惑的設定,我們不會在此討論。詳情請參考 JBossCache 的文件。然而就算你讀完JBoss Cache User Guide也不可能讓你設定好 seam 中的 PojoCache,因為JBoss Cache 中的例子根本不能用在 seam 中。
在網路和 JBoss 的網站上可以找到大量過時的資料,究竟 JBossCache,TreeCache 和 PojoCache有何分別?究竟怎樣才能讓我的 Hello World Seam Application 可以使用到最簡單的緩存?最後我由討論區上一篇孤獨的文章,加上 seam 的 blog example ,Seam 的源碼以及 TreeCache 的文檔中才慢慢找出個頭緒來… 回頭己是花了兩天。
希望這篇記錄有助以後需要最簡單 Seam 緩存的人。