轉(zhuǎn)自:http://blog.csdn.net/furthersun/archive/2008/09/19/2952329.aspx
1、摘要
本文檔介紹了如何在 Portlet 應(yīng)用中使用 OSCache 進(jìn)行頁面內(nèi)容緩存和對(duì)象緩存,分析了 OSCache
的實(shí)現(xiàn)原理,并提出了一個(gè)用來緩存對(duì)象和頁面的簡(jiǎn)單易用的方案。本文檔不涉及 OSCache 的安裝與配置的內(nèi)容,相關(guān)內(nèi)容請(qǐng)參考 OSCache
的 在線文檔 。
2、 OSCache 簡(jiǎn)介
OSCache標(biāo)記庫由OpenSymphony設(shè)計(jì),它是一種開創(chuàng)性的緩存方案,它提供了在現(xiàn)有JSP頁面之內(nèi)實(shí)現(xiàn)內(nèi)存緩存的功能。OSCache是個(gè)一個(gè)被廣泛采用的高性能的J2EE緩存框架,OSCache還能應(yīng)用于任何Java應(yīng)用程序的普通的緩存解決方案。
OSCache有以下特點(diǎn):
l 緩存任何對(duì)象:你可以不受限制的緩存部分jsp頁面或HTTP請(qǐng)求,任何java對(duì)象都可以緩存。
l 擁有全面的API:OSCache API允許你通過編程的方式來控制所有的OSCache特性。
l 永久緩存:緩存能被配置寫入硬盤,因此允許在應(yīng)用服務(wù)器的多次生命周期間緩存創(chuàng)建開銷昂貴的數(shù)據(jù)。
l 支持集群:集群緩存數(shù)據(jù)能被單個(gè)的進(jìn)行參數(shù)配置,不需要修改代碼。
l 緩存過期:你可以有最大限度的控制緩存對(duì)象的過期,包括可插入式的刷新策略(如果默認(rèn)性能不能滿足需要時(shí))。
3、OSCache 緩存原理簡(jiǎn)介
Cache Factory
Cache Proxy
Cache Map
Memory
Disk
Listeners
Cache Entry
圖 3-1 OSCache 架構(gòu)概覽
Cache Factory :該實(shí)體負(fù)責(zé)獲得 Cache Proxy ,兼有一些對(duì) Cache Proxy 的管理功能。對(duì)應(yīng)到現(xiàn)在的
OSCache 實(shí)現(xiàn)中的類是: GeneralCacheAdministrator 和 ServletCacheAdministrator 。
Cache Proxy :該實(shí)體是 Cache Map 的代理,它主要負(fù)責(zé)從 Cache Map 中取得 /
存儲(chǔ)指定的緩存對(duì)象,如果緩存對(duì)象過期,那么就將緩存刷新,并向指定的監(jiān)聽者發(fā)送存 / 取事件。對(duì)應(yīng)到現(xiàn)在的 OSCache 實(shí)現(xiàn)中的類是:
Cache 和 ServletCache 。
Cache Map :該實(shí)體存儲(chǔ)了所有的緩存實(shí)體,是一個(gè) OSCache 專有的 Map
實(shí)現(xiàn),它能根據(jù)指定的算法清除緩存,以及將緩存持久化到磁盤中。對(duì)應(yīng)到現(xiàn)在的 OSCache 實(shí)現(xiàn)中的類是: FIFOCache ,
LRUCache 和 UnlimitedCache 。
Listeners : OSCache 存 / 取事件的監(jiān)聽者實(shí)體。對(duì)應(yīng)到現(xiàn)在的 OSCache 實(shí)現(xiàn)中的類是: CacheEntryEventListener 和 CacheMapAccessEventListener 。
Cache Entry :表示緩存對(duì)象的包裝實(shí)體,它包裝了緩存對(duì)象和刷新策略。對(duì)應(yīng)到現(xiàn)在的 OSCache 實(shí)現(xiàn)中的類是: CacheEntry 。
3.1 應(yīng)用場(chǎng)景
一個(gè)典型的“緩存對(duì)象”場(chǎng)景是:
應(yīng)用調(diào)用 Cache Factory 獲得 Cache Proxy ,然后應(yīng)用將要緩存的對(duì)象以及刷新策略通過 Cache Proxy 存儲(chǔ)到 Cache Map 中,并通知各個(gè) Listener 。
一個(gè)典型的“取得緩存對(duì)象”的場(chǎng)景是:
應(yīng)用調(diào)用 Cache Factory 獲得 Cache Proxy ,然后給 Cache Proxy 的相應(yīng)方法傳入要獲得的緩存對(duì)象的
key , Cache Proxy
會(huì)根據(jù)指定的刷新策略判斷緩存是否過期,如果緩存沒有過期,則返回緩存對(duì)象,如果緩存過期,則刷新緩存,并向應(yīng)用層拋出需要刷新的異常(
NeedsRefreshException ),應(yīng)用如果收到此異常,將重新計(jì)算內(nèi)容并將內(nèi)容緩存。
4、Web 應(yīng)用中的緩存方案
4.1 假定
OSCache 現(xiàn)有的緩存刷新策略(超過指定時(shí)間后自動(dòng)過期,超過指定日期后自動(dòng)過期,按照克龍表達(dá)式的設(shè)定自動(dòng)過期)不能滿足需求。現(xiàn)有應(yīng)用要求:當(dāng)數(shù)據(jù)源的部分內(nèi)容更新后,能夠使相關(guān)緩存過期,展現(xiàn)頁面從數(shù)據(jù)源取得更新的內(nèi)容顯示。
4.2、方案應(yīng)用場(chǎng)景
該方案為下列場(chǎng)景提供了支持:
1. 緩存整個(gè) Response ,能夠定制刷新指定的 Response 。
2. 緩存 JSP 頁面內(nèi)容,能夠定制刷新指定的緩存內(nèi)容。
3. 緩存對(duì)象,能夠定制刷新指定的緩存對(duì)象。
4.3、 配置
4.3.1 配置 ***CacheFilter
在 Web 應(yīng)用的 web.xml 中添加下面的內(nèi)容:
< filter>
< filter-name>CacheFilter</filter-name>
< filter-class>
com.***.portal.oscache.***CacheFilter
</ filter-class>
< init-param>
< param-name>time</param-name>
< param-value>-1</param-value>
</ init-param>
< init-param>
< param-name>scope</param-name>
定制這個(gè) fileter 緩存的 response 的組
< param-value>application</param-value>
</ init-param>
<init-param>
<param-name>groups</param-name>
<param-value> landy </param-value>
</init-param>
</ filter>
< filter-mapping>
< filter-name>CacheFilter</filter-name>
< url-pattern>/ landy </ url-pattern>
</ filter-mapping>
注意:
為了在部分?jǐn)?shù)據(jù)更新時(shí)只刷新部分 Response , ***CacheFilter 比 OSCache 提供的 CacheFitler
增加了一個(gè)可配置的參數(shù):“ groups ”,部署者可以通過這個(gè)參數(shù)配置這個(gè) filter 所映射的 URLS 的組(通常同一個(gè)組的 URL
會(huì)從同時(shí)更新的數(shù)據(jù)源取數(shù)據(jù)),這樣當(dāng)數(shù)據(jù)源某部分更新之后,我們就可以刷新從這部分?jǐn)?shù)據(jù)源取數(shù)據(jù)的 URLs
。該配置項(xiàng)支持配置多個(gè)組,以逗號(hào)作為分隔符,如:“ group1,group2 ”。
其他的配置項(xiàng)說明請(qǐng)參考 OSCache 在線文檔的 CacheFilter 配置部分 。
4.4、緩存整個(gè) Response
OSCache 提供的 CacheFilter 能夠緩存 Response ,但不能供應(yīng)用選擇性的刷新某些 Response ,而 ***CacheFilter 就能支持這一特性。
4.4.1 使用方法
您可以按照以下的方式刷新某一組( Filter 初始化參數(shù)中 groups 參數(shù)配置的內(nèi)容)的 Responses:
ServletCacheAdministrator admin = null;
Filter 初始化參數(shù)中 scope 參數(shù)配置的內(nèi)容
admin = ServletCacheAdministrator.getInstance(config
.getServletContext());
Filter 初始化參數(shù)中 groups 參數(shù)配置的內(nèi)容
Cache cache = admin.getCache(httpRequest, cacheScope);
cache. flushGroup(group);
4.4.2 約束
這種方案僅適用于普通的 web 應(yīng)用,不適用于 Portlets 應(yīng)用,因?yàn)樵?Portlets
應(yīng)用中,每個(gè) Portlet 都是頁面上一個(gè)可插拔的組件,如果被緩存的 Response 代表的頁面中某個(gè) Portlet
被刪除了,那么這個(gè)頁面產(chǎn)生的 Response 就會(huì)不一樣,而這時(shí)應(yīng)用卻無法刷新緩存的 Response 。
4.5、 緩存 JSP 頁面內(nèi)容
可以在 JSP 頁面中將要緩存的內(nèi)容置于 <cache></cache> 標(biāo)簽之間,當(dāng)更新數(shù)據(jù)源的事件產(chǎn)生時(shí),在處理事件的方法中加入如下代碼即可:
***OSCacheUtil.getInstance().flushGroup("group1");
4.5.1 樣例
我要緩存一個(gè)從數(shù)據(jù)源的 A 表取數(shù)據(jù)的 JSP 內(nèi)容段,如下表所示:
<oscache:cache key="foobar" scope="application" time="-1" groups="group1" >
//business code
Select * from table A and Display
</oscache:cache>
數(shù)據(jù)源更新了,在處理數(shù)據(jù)更新事件的代碼中,我加入下表的代碼:
***OSCacheUtil.getInstance().flushGroup("group1");
這樣就可以刷新緩存的 group1 組的數(shù)據(jù)了。
4.5.2 約束
本方案在滿足了 4.1 描述的需求的條件下,僅支持選擇性的刷新存儲(chǔ)在 application 域(
cache 標(biāo)簽中 scope 屬性配置為 application )的緩存。為什么不支持選擇性的刷新 session
域的緩存呢?是因?yàn)閿?shù)據(jù)更新的事件產(chǎn)生是隨機(jī)的,當(dāng)數(shù)據(jù)更新事件發(fā)生時(shí),我們無法得到 web 服務(wù)器中的每個(gè) session
,所以不能支持選擇性的刷新 session 域的緩存。
4.6、緩存對(duì)象
可以在 web 應(yīng)用的業(yè)務(wù)處理邏輯中將要緩存的對(duì)象采用如下的方式將對(duì)象緩存到 application 域中:
***OSCacheUtil.getInstance().putInCache(key, content, new String[]{“group1”});
當(dāng)更新數(shù)據(jù)源的事件產(chǎn)生時(shí),在處理事件的方法中加入如下代碼即可:
***OSCacheUtil.getInstance().flushGroup("group1");
4.6.1 約束
同 4.5.2 一致。
5、Demo
5.1 方案框架
包括 ***CacheFilter 和 ***OSCacheUtil 。
5.2 測(cè)試用例(基于 portlet )
用例 src :
用例 ear :