JSP 緩存 OSCache使用介紹

一.OSCache簡介 java

OSCache是OpenSymphony這個開源項目衆多Projects中的一個。他是一個高效的J2EE緩存框架,可以很好的解決動態網站速度的問題。下面來 web

看下OSCache解決了動態網站的哪些使人鬱悶的問題。 算法

1.緩存動態內容:其實咱們的動態網頁上通常只有一部分是動態的(表頭,表尾通常是不變的),若是咱們緩存整個網頁顯然不成,由於有部分是 數據庫

隨着請求有可能變的。OSCache提供的方式是容許咱們只緩存一部分網頁。 瀏覽器

2.緩存2進制內容:產生的圖片和PDF文件在服務器加載的時候很是的耗時。OSCache解決這個問題是經過一個Servlet2.3的緩存過濾功能,而後能 緩存

夠緩存任意的URI(好比一個完整的頁面或者是一個產生的圖片/PDF文件) 服務器

3.容錯:有這種狀況或許咱們會遇到,就是當一個動態的網頁出現錯誤。即使咱們的頁面有95%都加載完畢,但就是因爲這個錯誤,整個頁面就會 session

返回錯誤的提示或頁面。OSCache容許咱們提供出現錯誤時的緩存內容,若是出現就適時的提示出來了。 app

除了上面的這些Servlet的特徵外,OSCache徹底能夠充當任何一個java程序的緩存方案。OSCache 的通常特徵以下: 框架

1.緩存任意對象:能夠不受限制的緩存JSP的一部分或是Http請求,任何的Java對象均可以被緩存。

2.全面的API:經過API能夠完徹底全的控制OSCache的任何特性。

3.持久緩存:咱們能夠把認爲重要的數據緩存到硬盤上。

4.支持集羣:集羣緩存數據能被單個的進行參數配置,不須要修改代碼。

5.緩存記錄的過時:你能夠有最大限度的控制緩存對象的過時,包括可插入式的刷新策略(若是默認性能不須要時)。

二.OSCache運行環境

若是用到OSCache Tag Library的話,須要Servlet2.3和JSP1.2的支持。若是是直接用OSCache API的話那麼就不須要Servlet容器的支持。

目前能夠正常運行的Web容器:

1.OrionServer(版本1.4.0和更高)

2.JRun(3.0或更好)

3.WebLogic(8.1或以上)

4.Websphere(5.0或以上)

5.Resin(1.2.3或以上)

6.TomCat(4.0或以上)

7.iPlanet(6.0或以上)

用到緩存過濾須要Servlet2.3支持.目前知道的能夠個工做在OrionServer,WebLogic,Tomcat上.

OSCache須要Java的版本至少是java 1.4.

三.OSCache的安裝

1.解壓oscache-2.4.1-full後發現他下面有以下文件:

2.把oscache-2.4.1.jar放到/WEB-INF/lib下.

3.要確保commons-logging.jar也在環境變量中.通常狀況下他也放在/WEB-INF/lib下.

4. 把/etc/oscache.properties放入/WEB-INF/classes下.若是用的Eclipse的話,建議新建一個 Source Folder好比叫Src_Config,而後就這個OSCache的屬性文件放在其中.經過修改這個OSCache的配置文件能夠改變文件緩存的磁盤路徑,配置持久偵聽等等.

5.把etc/META-INF/oscache.tld也放在/WEB-INF/classes下.

你的目錄結構以下:

四.OSCache應用學習

1.JSP的應用

要是想應用OSCache的標籤,咱們必須先要引入進來.方式有兩種.

其一.在web.xml中加入:

<taglib>

<taglib-uri>oscache</taglib-uri>

<taglib-location>/WEB-INF/classes/oscache.tld</taglib-location>

</taglib>

而後咱們在JSp中就能夠<%@ taglib uri="oscache" prefix="os"%>這樣來引用了.

其二,直接引用.直接在JSp中加入OSCache的標籤庫引用

<%@ taglib uri="/WEB- INF/classes/oscache.tld" prefix="os"%>.若是要進入官方的標籤庫的話也行.& lt;%@ taglib uri="http://www.opensymphony.com/oscache" prefix="cache" %& gt;這樣就不用再把oscache.tld放在/WEB-INF/classes下了.

目前OSCache有5個標籤.他們是cache, usecached, flush, addgroup, addgroups.下面咱們來分別介紹一下他們的屬性和用法.

<cache></cache>

他是OSCache中最主要的標籤了.括起來的內容將根據屬性的設置來緩存起來.第一次執行的時候,OSCache會把cache標籤中的JSp執行而且緩存起來,之後再執行的話,他會首先判斷緩存的內容是否過時,若是過時那麼會重新執行並緩存.不然就直接從緩存中讀取.斷定過時的條件以下:

i.緩存的內容超過了屬性time所指定的時間.

ii.不符合cron設置的時間間隔.

iii.若是scope指定的範圍刷新的話,則認爲過時了.如Session過時.

屬性以下:

key   : 緩存的Key,能夠是任何的字符,用來尋找緩存的內容用的.能夠理解成HashMap中的Key.不能把2個要緩存的東東定義成一個名字,那樣後一個會覆蓋前一個的內容.默認狀況,若是不指定Key的話,OSCache也會自動生成一個Key,規則是請求的URI+當前頁面的Query String.

scope : 緩存的範圍.有2個, application和session.默認值是application.

time   : 緩存內容的時間.以秒爲單位,默認是3600秒.到了指定的時間,就會刷新緩存內容.若是指定一個負數的話,意味着永遠不會過時.

duration : 也是用來指定緩存內容的時間,它和time屬性只能是2選1,它的特色是能夠用Simple Data Format 或者是ISO-8601進行日期格式化.

cron   : 用萬年曆的形式指定緩存內容什麼時候過時的.它應用的Unix的萬年曆形式,如("0 * * * *")

refresh : 是個Boolean值,若是是True的話,則無論前面提到的過時檢查,都刷新.默認狀況是false.

mode   : 設置這項爲」silent」將防止把括起來的內容輸出.這在你預加載緩存內容而不肯顯示給用戶看到時頗有用.

groups : 能夠提供一個以逗號分割的組名稱.如group="A, B".這將容許你以組的名義來操做他們,分組很是有用,好比你要緩存的內容正好須要另一個應用程序的一部分或數據,當依賴的發生了改變,正好聯動的可使不少的組過時,進而使與組發生關聯的緩存內容獲得更新.

language : 設置編碼方式.

refreshpolicyclass:指定自定義的類來處理緩存的內容何時過時.這個類須要從 refreshpolicyparam com.opensymphony.oscache.web.WebEntryRefreshPolicy繼承.

refreshpolicyparam : 它和上面的是聯合使用的.是給refreshpolicyclass傳任意的參數的.指定這項的話,就必須有refreshpolicyclass,不然就不起做用.

屬性就這麼多了,下面舉幾個應用的例子:

<os:cache key="<%=myKey%>" time="1800" refresh="<%=needRefresh%>">

<!--這裏是要緩存的內容-->

</os:cache>

這裏將myKey標識的緩存內容保持30分鐘,到期自動刷新.若是needRefresh爲true也會刷新(適合於更新內容的即時刷新).

<os:cache key="<%=myKey%>" cron="0 2 * * *" refresh="<%=needRefresh%>">

<!--這裏是要緩存的內容-->

</os:cache>

將myKey標識的緩存內容在天天的凌晨2時自動刷新.若是needRefresh爲true也會刷新(適合於更新內容的即時刷新).

舉到了這個例子,我不得不把cron表達式多說幾句.首先這五顆星的位置表明

分,小時,一個月中的天,月,一週中的天

分: 無疑問0~59.

小時 : 無疑問 0~23.

天(月) : 1~31

月 : 1~12,用英文全稱也能夠.如January, April

天(周): 0~6(0表明Sunday; 1表明Monday… 6表明Saturday)

舉個例子,好比咱們想讓緩存的內容在4月的晚上11:45分過時.咱們能夠這樣來寫

"45 23 * April *".

<usecached />

須要放在cache標籤中嵌套使用(通常配合try..catch使用)告訴他的上級標籤是否應用緩存的譯本. 則出現異常時將會替換包括上級標籤在內的全部內容(提示:Missing cached content). use="true|false" : 是否應用的標記. 默認爲True.通常省略.

應用例子:

<os:cache>

..內容..

    <% try {%>

    ......其它內容

    <%}catch (Exception e) {%>

    Inside catch: <os:usecached use="<%=isUsed%>"/> YES

    <% } %>

</os:cache>

則出現異常時的頁面輸出有兩種:

1>. isUsed=false

..內容..

......其它內容

Inside catch: YES

2>. isUsed=true

Missing cached content

<flush />

這個標籤是用於在運行時狀態下刷新緩存的.這個標籤很是有用,由於它能夠放在Web程序的管理部分使管理員能夠決定什麼時候刷新緩存.

屬性以下:

scope : 刷新的範圍.3個值, "application", "session" and null .null表示刷新全部.

Key : 和scope聯合使用,刷新指定範圍的指定緩存.若是不指定scope則key無效.

group : 和scope聯合使用, 刷新指定範圍的指定組中的緩存. 不指定scope無效.

Pattern :任何包含了pattren指定的字符串的緩存都被更新.它也是和scope連用.可是如今官方不同意再用這個屬性了.用group徹底能夠取代這個.便於管理.

language : 設置編碼方式

舉幾個應用的例子:

刷新整個application.

<os:flush scope="application" />

刷新session中的foobar這個緩存.

<os:flush scope="session" key="foobar" />

在application 中刷新全部currencyData 組中的緩存

<os:flush scope="application" group="currencyData" />

<addgroup />

這個標籤也是必須嵌套在cache標籤中的.把緩存的東東放入到指定的組中.這樣就能夠以組來刷新指定的內容了.

屬性只有group來指定名字的.例子以下:

把test1加入到group1和group2中

<os:cache key="test1">

    < os:addgroup group="group1" />

    ... some jsp content ...

    < os:addgroup group="group2" />

    ... some more jsp content ...

</ os:cache>

<addgroups /> (2.3及之後的版本中新加的)

同上面的功能相同,只不過能夠不用一個一個加group了.例子以下:

< os:cache key="test1">

    ... some jsp content ...

    < os:addgroups groups="group1,group2" />

    ... some jsp content ...

</ os:cache>

2.API的應用

在實際應用中除了JSP標籤庫和CacheFilter(下面介紹)外,還可使用OSCache提供的Java API .下面我來介紹一個實用的 Java類 ,使用GeneralCacheAdministrator來創建,刷新和管理緩存. GeneralCacheAdministrator 能夠被實例化,裏面有不少的實用方法.此外它還管理加載cache.properties而且根據這個屬性文件建立一個緩存實例.所以你最好使用單例模式來建立GeneralCacheAdministrator實例.

主要用到的GeneralCacheAdministrator的方法有

public Object getFromCache(String key) throws NeedsRefreshException; -- 從緩存中獲取一個key標識的對象.

public Object getFromCache(String key, int refreshPeriod) throws NeedsRefreshException ; -- 從緩存中獲取一個key標識的對象. refreshPeriod刷新週期,標識此對象在緩存中保存的時間(單位:秒)

public void putInCache(String key, Object content) -- 存儲一個由Key標識的緩存對象.

public void putInCache(String key, Object content, String[] groups)   -- 存儲一個由Key標識的屬於groups中全部成員的緩存對象.

public void flushEntry(String key) -- 更新一個Key標識的緩存對象.

public void flushGroup(String group) --更新一組屬於groupr標識的全部緩存對象.

public void flushAll() -- 更新全部緩存.

public void cancelUpdate(String key) --- 取消更新 只用於在處理捕獲的NeedsRefreshException異常並嘗試生成新緩存內容失效的時候.

public void removeEntry(String key) ---從緩中移除一個key標識的對象

public void clear() --- 清除全部緩存

官方的使用例子:

///採起補救措施的典型方案

String myKey = "myKey";

String myValue;

int myRefreshPeriod = 1000; //刷新週期1000秒

try {

//從Cache中得到 要作類型轉換

myValue = (String) admin.getFromCache(myKey, myRefreshPeriod);

} catch (NeedsRefreshException nre) {

try {

  // Cache中沒有則從庫得到數據.

  myValue = "This is the content retrieved.";

  // 存放在Cache中 鍵值myKey

  admin.putInCache(myKey, myValue);

} catch (Exception ex) {

// 嘗試恢復Cache中的內容

  myValue = (String) nre.getCacheContent();

  // 若是Cache中的內容沒有復原 則用這個終級方法

  admin.cancelUpdate(myKey); //取消對myKey的更新 即相似數據回滾

}

}

///不採起補救措施的典型方案

String myKey = "myKey";

String myValue;

int myRefreshPeriod = 1000;

try {

//從Cache中得到 要作類型轉換

myValue = (String) admin.getFromCache(myKey, myRefreshPeriod);

} catch (NeedsRefreshException nre) {

try {

  // Cache中沒有則從庫得到數據.

  myValue = "This is the content retrieved.";

  // 存放在Cache中 鍵值myKey

  admin.putInCache(myKey, myValue);

  updated = true;

} finally {

  if (!updated) {

    // 若是Cache中的內容更新出現異常 則用這個終級方法

  admin.cancelUpdate(myKey); //取消對myKey的更新 即相似數據回滾

  }

}

}

注意:

若是一個NeedsRefreshException出現 必須調用admin.putInCache或甚至admin.cancelUpdate來避免死鎖狀況發生.

3.CacheFilter的應用

OScache能夠是你很輕易的緩存網站中所有頁面,甚至是那些2進制文件.從2.4版本開始你能夠在運行期設置和覆蓋CacheFilter的初始化參數.注意,只有返回狀態爲200的頁面纔會緩存. (HttpServletResponse.SC_OK).

配置CacheFilter,在Web.xml中加入以下:

<filter>

<filter-name>CacheFilter</filter-name>

<filter-class>com.opensymphony.oscache.web.filter.CacheFilter</filter-class>

<init-param>

  <param-name>time</param-name>

  <param-value>600</param-value>

</init-param>

<init-param>

  <param-name>scope</param-name>

  <param-value>session</param-value>

</init-param>

</filter>

<filter-mapping>

<filter-name>CacheFilter</filter-name>

<url-pattern>*.jsp</url-pattern>

</filter-mapping>

這個例子將在session範圍緩存全部JSp10分鐘.默認狀況scope爲application,時間爲1小時.

若是ICacheKeyProvider不設置的話,這個CacheFilter將使用(URI+QueryString)做爲緩存Key.

你可使用下列的初始化參數來設置CacheFilter:

Parameter: time

設置緩存時間,默認是1個小時.能夠設置爲-1(不肯定).這樣他就不會過時了.除非你明確刷新它(前面說到的refresh =」true」).或者是更改這個刷新的策略.

Parameter: scope

同cache的scope. 也是有application(default)和session

Parameter: cron (NEW! Since 2.3)

同cache的scope.設置過時

Parameter: fragment (NEW! Since 2.2)

做用不太清除,用默認便可.

Parameter: nocache (NEW! Since 2.2)

定義那些頁面不須要緩存.」off」---緩存全部;」sessionIdInURL」---若是session中包括這URL的則不緩存這個頁面

Parameter: lastModified (NEW! Since 2.2)

定義是否把Header發送到Response中.

」off」----不發送,即使它設置在過濾鏈中.

「on」----若是在過濾鏈中則發送.

「inital」(default)----最後更改的信息將基於當前時間被設置

Parameter: max-age (NEW! Since 2.3.1)

設置在瀏覽器中緩存的最大時間.在設置的期間,再也不向服務器請求,而是從本身的緩存中查找頁面.默認是60秒.

Parameter: expires (NEW! Since 2.2)

定義過時header發送到Response中的時間.

「off」----不發送.

「on」(default)---若是在過濾鏈中則發送.而且time這個過時信息將基於時間參數和頁面內容的建立時間初始化.

Parameter: ICacheKeyProvider (NEW! Since 2.2)

指定實現ICacheKeyProvider接口的類.

Parameter: ICacheGroupsProvider (NEW! Since 2.2)

指定實現ICacheGroupsProvider接口的類

Parameter: EntryRefreshPolicy (New! Since 2.3)

指定實現EntryRefreshPolicy接口的類.

Parameter: disableCacheOnMethods (New! Since 2.4)

指定請求方式不進行緩存.默認Null,對全部的請求方式都緩存.例如:

<init-param>

  <param-name>disableCacheOnMethods</param-name>

  <param-value>POST,PUT,DELETE</param-value>

</init-param>

Parameter: oscache-properties-file (New! Since 2.4)

經過指定OSCache的屬性文件,開發者就能運行多個CacheFilter

4.OSCache的屬性文件.(oscache.properties)

cache.memory

值爲true或false.默認爲true.若是設置爲false那麼緩存到數據庫或硬盤中.彷佛有點傻,因此咱們通常不改此項.

cache.capacity

緩存元素的個數.默認是沒有限制的.

cache.algorithm

緩存的算法.注意要是指定算法的話,必須把上面的緩存個數指定.這裏支持三種算法.

com.opensymphony.oscache.base.algorithm.LRUCache – 最後最近使用

com.opensymphony.oscache.base.algorithm.FIFOCache – 先進先出

com.opensymphony.oscache.base.algorithm.UnlimitedCache – 無限緩存

cache.blocking

是否同步化。true 或者 false。通常設爲true,避免讀取髒數據。

cache.unlimited.disk

指定硬盤緩存是否要做限制。默認值爲false。false的情況下,disk cache capacity 將和cache.capacity的值相同。

cache.persistence.class

指定類是被持久化的類。class必須實現PersistenceListener接口。 做爲硬盤持久,能夠實現 com.opensymphony.oscache.plugins.diskpersistence.HashDiskPersistenceListener 接口。 它把class的toString()輸出的hash值做爲文件的名稱。若是你要把文件名易讀(本身設定),DiskPersistenceListener 的父類也 能使用,但其可能有非法字符或者過長的名字。 注意:HashDiskPersistenceListener 和 DiskPersistenceListener 須要設定硬盤路徑:cache.path

cache.path

指定硬盤緩存的路徑。目錄若是不存在將被創建。同時注意oscache應該要有權限寫文件系統。 cache.path=c://myapp//cache or *ix: cache.path=/opt/myapp/cache

cache.persistence.overflow.only (NEW! Since 2.1)

指定是否只有在內存不足的狀況下才使用硬盤緩存。 默認值false。但推薦是true若是內存cache被容許的話。這個屬性完全的改變了cache的行爲,使得persisted cache 和memory徹底不一樣。

cache.event.listeners

用逗號分離的class名列表。每一個class必須實現如下接口之一,或者幾個 CacheEntryEventListener:接收 cache add/update/flush and remove事件 CacheMapAccessEventListener :接收cache 訪問事件。這個可讓你跟蹤cache怎麼工做。 默認是不配置任何class的。固然你可使用一下的 class: com.opensymphony.oscache.plugins.clustersupport.BroadcastingCacheEventListener -分佈式的(此處被屏蔽)。能夠廣播到局域網內的其餘cache實例。 com.opensymphony.oscache.extra.CacheEntryEventListenerImpl -一個簡單的(此處被屏蔽)。在cache的生命週期中記錄count of 全部entry的事件。 com.opensymphony.oscache.extra.CacheMapAccessEventListenerImpl -記錄 count of cache map events(cache hits,misses and state hits).

cache.key

設置ServletCacheAdministrator使用的Key.在代碼中若是須要用到的話,能夠經過com.opensymphony.oscache.web.ServletCacheAdministrator.DEFAULT_CACHE_KEY獲得.

cache.use.host.domain.in.key

若是你的服務器是被配置到多臺主機上的話,你或許想加上一個主機的名字在它生成的緩存Key上.true的話會加上.默認值是false.

附加的屬性: cache.cluster.multicast.ip, cache.cluster.properties

5.小結:

OSCache的使用主要有4種:

POJO 緩存

HTTP Response 緩存

JSP Tag Library 緩存

O/R Data Access 緩存

1)、POJO 緩存

這種方式的緩存直接調用OSCache的API進行,主要用於處理頁面內容會根據參數動態改變,能夠將參數設置爲key值來保存數據:

首先,聲明成員變量:

// OSCache Adminitrator instance

private static GeneralCacheAdministrator cacheAdmin = null;

其次,進行初始化:

public RingArtistAction() {

cacheAdmin = new GeneralCacheAdministrator();

}

將POJO進行緩存:

// Cache data key and refresh period

String key = sex + ":" + place;

int refreshPeriod = Constants.getIntegerValue(Constants.OSCACHE_REFRESH_PERIOD).intValue();

try {

  // Get from the cache

artists = (Map) cacheAdmin.getFromCache(key, refreshPeriod);

} catch (NeedsRefreshException nre) {

  try {

    // Get the value (probably from the database)

int count = getArtistCount(sex, place, errors);

artists = getArtistData(sex, place, count, errors);

    // Store in the cache

cacheAdmin.putInCache(key, artists);

  } catch (Exception ex) {

    // We have the current content if we want fail-over.

artists = (Map) nre.getCacheContent();

    // It is essential that cancelUpdate is called if the

    // cached content is not rebuilt

cacheAdmin.cancelUpdate(key);

ex.printStackTrace();

  }

}

2)、HTTP Response 緩存

這種方式的緩存用來處理整個頁面的內容固定,不會根據參數動態改變:

首先在web.xml中配置CacheFilter:

<filter>

<filter-name>CacheFilter</filter-name>

<filter-class>com.opensymphony.oscache.web.filter.CacheFilter</filter-class>

<init-param>

<param-name>time</param-name>

<param-value>86400</param-value>

</init-param>

<init-param>

<param-name>scope</param-name>

<param-value>application</param-value>

</init-param>

</filter>

將全部須要緩存的頁面加入filter-mapping:

<filter-mapping>

<filter-name>Set Character Encoding</filter-name>

<url-pattern>/*</url-pattern>

</filter-mapping>

注意,只有返回狀態爲200(HttpServletResponse.SC_OK)的內容纔會被緩存

3)、JSP Tag 緩存

JSP Tag緩存主要用於緩存JSP頁面的局部內容:

<cache:cache key="especialcategory" cron="* 5 * * *">

<jsp:include page="/ringcategory.do" flush="true" >

<jsp:param name="ringType" value="1"/>

</jsp:include>

</cache:cache>

4)、O/R Data Access 緩存

請閱讀參考資料的內容獲取詳情。

相關文章
相關標籤/搜索