http://dev2dev.bea.com.cn/techdoc/webplat/2005041303.html
摘要
WebLogic Portal 8.1包含了大量允許開發(fā)人員最大限度地提高站點(diǎn)性能的功能。其中一個(gè)功能就是通過使用Render Cacheable參數(shù)實(shí)現(xiàn)portlet內(nèi)容的緩存。雖然在幫助文檔中可以找到對該參數(shù)的基本描述,但是該參數(shù)常常引起人們的誤解。本文的目的是提供對該參數(shù)的詳細(xì)分析,并討論一下該參數(shù)的使用場合。
背景
Render Cacheable參數(shù)是portlet定義的一部分。點(diǎn)擊portlet定義,檢查顯示該參數(shù)以及與此密切相關(guān)的Cache Expires參數(shù)的屬性編輯器。由于Render Cacheable屬性是廣義portlet定義的一部分,而不是一個(gè)特殊的portlet實(shí)例,這就說明該緩存適用于門戶中portlet的所有實(shí)例。您不能僅為某些實(shí)例,而不為其他的實(shí)例指定緩存。
即使緩存受全局控制。但是相同portlet的不同實(shí)例可以使用不同的緩存。為了證明這一點(diǎn),我們將分析這樣一種情況,即開發(fā)人員創(chuàng)建了一個(gè)名稱為GenericDisplayFilePortlet的portlet。該portlet可以通過個(gè)性化設(shè)置,基于傳遞到portlet的屬性顯示來自文件系統(tǒng)的靜態(tài)HTML文件。如果該portlet在門戶主頁上具有兩個(gè)不同的實(shí)例,每一個(gè)實(shí)例顯示一份不同的文件,則這兩個(gè)實(shí)例的緩存將不發(fā)生沖突,每一個(gè)portlet實(shí)例維護(hù)它自己的緩存。
Cache Expires參數(shù)是指緩存內(nèi)容失效之前,緩存保持活動(dòng)狀態(tài)的秒數(shù)。如果Cache Expires設(shè)置為–1,則任何緩存都不會(huì)發(fā)生,不管Render Cacheable是否設(shè)置為true。
緩存作用域
很多開發(fā)人員對portlet緩存產(chǎn)生的第一個(gè)誤解是作用于應(yīng)用。這是錯(cuò)誤的。portlet cache作用于會(huì)話層,這說明每一位個(gè)體用戶可以擁有portlet緩存的個(gè)體版本。
這就使portlet緩存機(jī)制完美的適合緩存?zhèn)€性化的內(nèi)容,但是portlet緩存不適合緩存靜態(tài)內(nèi)容,這些內(nèi)容也會(huì)呈現(xiàn)給所有用戶,并且很少會(huì)失效。舉例來說,按月顯示公司新聞簡報(bào)(company newsletter)的portlet不應(yīng)當(dāng)使用Render Cacheable參數(shù);而應(yīng)當(dāng)使用可以在應(yīng)用層提供緩存的替代機(jī)制。
如果已經(jīng)為新聞簡報(bào)設(shè)置了Render Cacheable參數(shù),那么,您可以在會(huì)話作用域上為每一次獨(dú)立會(huì)話緩存其內(nèi)容。這將在多個(gè)緩存中重復(fù)不必要的內(nèi)容,從而降低性能。
一種簡單的替代方法是將緩存移動(dòng)到一個(gè)較低的層中,并且讓portlet正在面對的JSP或者頁面流在該層上執(zhí)行緩存。在這種情況中,我們可以使用包含在WebLogic中的wl:cache標(biāo)簽在應(yīng)用層上緩存內(nèi)容。有關(guān)wl:cache 標(biāo)簽的詳細(xì)文檔請參考下面內(nèi)容。
另一種替代方法是在門戶緩存中緩存信息;這允許管理員通過使用WebLogic門戶包含的門戶管理員(Portal Administrator)工具,輕松地調(diào)整這些緩存。您可以通過各種方式來使用門戶緩存,包括:
- 直接使用門戶緩存API,您可以按需存儲(chǔ)和檢索顯示信息。請參看參考資料一節(jié)了解更多信息。
- 另一種方法是,您可以創(chuàng)建一個(gè)定制標(biāo)簽來替代wl:cache,該標(biāo)簽可以在門戶緩存中緩存信息,以實(shí)現(xiàn)更好的受控于門戶管理員。附錄中包含了如何實(shí)現(xiàn)該操作的一個(gè)簡單示例。
緩存生命周期
我們將討論的有關(guān)portlet的第二個(gè)誤解涉及到緩存的生命周期。開發(fā)人員往往認(rèn)為是否始終使用緩存取決于以前是否調(diào)用過portlet,是否還沒有超過失效時(shí)間。事實(shí)上,有幾個(gè)原因可以解釋在轉(zhuǎn)換portlet的時(shí)候?yàn)槭裁床皇褂镁彺妗A私饩彺嫔芷诜浅V匾梢源_保從緩存中獲得最大程度的優(yōu)勢。
我們將執(zhí)行一個(gè)非常有趣的實(shí)驗(yàn),即創(chuàng)建一個(gè)使用小型JSP顯示日期和時(shí)間的簡單portlet,如下所示:
<%@ page language="java" contentType="text/html;charset=UTF-8"%>
<%@ taglib uri="netui-tags-databinding.tld" prefix="netui-data"%>
<%@ taglib uri="netui-tags-html.tld" prefix="netui"%>
<%@ taglib uri="netui-tags-template.tld" prefix="netui-template"%>
<p>
Date and time is:<%=new Date(System.currentTimeMillis())%>
</p>
將portlet的Render Cacheable參數(shù)設(shè)置為true,并且將Cache Expires設(shè)置為30秒。將portlet存放在測試門戶中,然后從WebLogic Workshop運(yùn)行門戶。您應(yīng)當(dāng)看到顯示日期和時(shí)間的門戶。現(xiàn)在,請按瀏覽器的刷新(Refresh)按鈕,并觀察日期和時(shí)間的變化;沒有使用portlet緩存。此時(shí),可以原諒您會(huì)認(rèn)為portlet緩存已經(jīng)中斷,但是事實(shí)上,它工作正常,如下所示。
為了深入分析該示例,接下來創(chuàng)建一個(gè)具有簡單頁面流的新portlet,該頁面流由單個(gè)JSP頁面組成。JSP包含一個(gè)簡單的表格和Submit(提交)按鈕,如下所示:
<%@ page language="java" contentType="text/html;charset=UTF-8"%>
<%@ taglib uri="netui-tags-databinding.tld" prefix="netui-data"%>
<%@ taglib uri="netui-tags-html.tld" prefix="netui"%>
<%@ taglib uri="netui-tags-template.tld" prefix="netui-template"%>
<p>Postback example</p>
<netui:form action="refresh">
<netui:button>Refresh</netui:button>
</netui:form>
當(dāng)點(diǎn)擊了Refresh(刷新)按鈕之后,該portlet簡單的初始化一次服務(wù)器postback操作。在設(shè)置該示例的時(shí)候,請確保在頁面流編輯器中鏈接刷新操作和JSP頁面。現(xiàn)在,將該portlet存放在緩存先前日期和時(shí)間portlet的同一門戶頁面中。
如果您現(xiàn)在從Workshop運(yùn)行門戶,將可以看到兩種portlets:已經(jīng)緩存的日期和時(shí)間portlet和剛剛創(chuàng)建的postback portlet。如果您刷新瀏覽器,就會(huì)出現(xiàn)與先前一樣的行為,即沒有使用緩存。現(xiàn)在,嘗試點(diǎn)擊postback portlet中的Refresh(刷新)按鈕,然后觀察postback執(zhí)行時(shí),緩存是否按照預(yù)期使用。
該示例的要點(diǎn)是證明緩存僅用于portlet生命周期的某些特定部分,尤其是,當(dāng)沒有明確地證明文件時(shí),緩存僅在portlet加載狀態(tài)中使用。不調(diào)用該部分portlet生命周期的操作將不使用緩存,因此,緩存和portlet生命周期是密切聯(lián)系的。下表綜述了各種門戶交互如何影響緩存。
交互 | 使用緩存 |
---|---|
通過外部鏈接訪問門戶。 | 不 |
已經(jīng)緩存的portlet初始化postback。 | 不 |
與已經(jīng)緩存的portlet在同一頁面中的Portlet初始化postback。 | 是 |
在門戶中的程序塊和頁面之間導(dǎo)航。 | 是 |
_nfls=false參數(shù)通過URL傳遞到門戶中。 | 不 |
總而言之,為了最大限度地提高緩存的有效性,掌握與門戶交互相關(guān)的緩存生命周期處理方式非常重要。如果一種利用緩存的情況涉及到大量沒有調(diào)用緩存的交互,則應(yīng)當(dāng)仔細(xì)考慮portlet緩存的替代方案。
結(jié)束語
在這里總結(jié)我們對portlet緩存機(jī)制的討論。如您所見,portlet緩存機(jī)制不只是表面現(xiàn)象,其內(nèi)涵豐富,開發(fā)人員應(yīng)當(dāng)仔細(xì)考慮對每一種情況的選擇,以最大限度地獲取緩存的性能優(yōu)勢。
portlet cache的理想用例是專為每一位用戶訂制,并且經(jīng)常失效的內(nèi)容。其他用例應(yīng)當(dāng)考慮更加恰當(dāng)?shù)木彺嫣娲椒ǎ缡褂脀l:cache標(biāo)簽或者門戶緩存。
參考資料
- Workshop文檔
- wl:cache文檔
- Portal Cache文檔
附錄。緩存標(biāo)簽
示例1. 定制標(biāo)簽
這是一個(gè)簡單的示例,說明了如何使用定制標(biāo)簽在門戶緩存中緩存內(nèi)容。它不是一款全面的緩存解決方案,而是證明我們?nèi)绾伟验T戶緩存作為Render Cacheable的一種替代來緩存信息。
package com.bea.ps.portal.tags.cache; import com.bea.p13n.cache.Cache; import com.bea.p13n.cache.CacheFactory; import java.io.IOException; import javax.servlet.jsp.JspException; import javax.servlet.jsp.tagext.BodyTagSupport; /** * Caches content in body of tag in a portal cache called * 'tagContentCache'. While not as full featured as wl:cache, * caching content in the portal cache does have an advantage of * allowing administrators to tune and control the cache from the * portal administration tool. */ public class CacheContentTag extends BodyTagSupport { private static final String CACHE_NAME = "tagContentCache"; private String name; /** * Name to use to uniquely identify content within the cache */ public String getName() { return name; } public void setName(String value) { name = value; } public int doStartTag() throws JspException { Cache cache = CacheFactory.getCache(CACHE_NAME); //If the request parameter _cache_refresh is set to true, //we invalidate the cache for this entry. This is identical //to the way wl:cache behaves. if ("true".equals(pageContext.getRequest().getParameter("_cache_refresh"))) { cache.remove(name); } if (cache.get(name)!=null) return BodyTagSupport.SKIP_BODY; else return BodyTagSupport.EVAL_BODY_BUFFERED; } public int doEndTag() throws JspException { Cache cache = CacheFactory.getCache(CACHE_NAME); String content = (String)cache.get(name); //If content is null then it has not been previously cached if (content==null) { //Get content of tag body content = getBodyContent().getString(); //Put content in portal cache cache.put(name,content); } try { //Out put content to page pageContext.getOut().print(content); } catch (IOException e) { throw new JspException(e); } return BodyTagSupport.EVAL_PAGE; } public void release() { super.release(); name = null; } }示例2. TLD文件
這是一份伴隨的JSP標(biāo)簽描述符文件。
<?xml version="1.0" encoding="ISO-8859-1"?> <!DOCTYPE taglib PUBLIC "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.2//EN" "http://java.sun.com/dtd/web-jsptaglibrary_1_2.dtd"> <taglib> <tlib-version>1.0</tlib-version> <jsp-version>1.2</jsp-version> <short-name>example</short-name> <display-name>Cache Tag</display-name> <description> A tag for caching content in a portal cache </description> <tag> <name>cache</name> <tag-class>com.bea.ps.portal.tags.cache.CacheContentTag</tag-class> <body-content>jsp</body-content> <display-name>Cache</display-name> <description>Caches content in the portal cache tagContentCache</description> <attribute> <name>name</name> <required>true</required> <rtexprvalue>true</rtexprvalue> <description>The name to use to uniquely identify the content</description> </attribute> </tag> </taglib>示例3. 示例緩存標(biāo)簽及使用
這是一個(gè)說明緩存標(biāo)簽如何用在JSP中的示例。
<%@ taglib uri="/WEB-INF/tld/example.tld" prefix="example" %> <example:cache name="newsletter"> <jsp:include page="newsletter.html"> </example:cache>Gerald Nunn是BEA Systems Professional Services的一位業(yè)務(wù)原理咨詢師。
原文出處
http://dev2dev.bea.com/products/wlportal81/articles/portlet_caching.jsp