http://dev2dev.bea.com.cn/techdoc/webplat/2005041303.html
摘要
WebLogic Portal 8.1包含了大量允許開發人員最大限度地提高站點性能的功能。其中一個功能就是通過使用Render Cacheable參數實現portlet內容的緩存。雖然在幫助文檔中可以找到對該參數的基本描述,但是該參數常常引起人們的誤解。本文的目的是提供對該參數的詳細分析,并討論一下該參數的使用場合。
背景
Render Cacheable參數是portlet定義的一部分。點擊portlet定義,檢查顯示該參數以及與此密切相關的Cache Expires參數的屬性編輯器。由于Render Cacheable屬性是廣義portlet定義的一部分,而不是一個特殊的portlet實例,這就說明該緩存適用于門戶中portlet的所有實例。您不能僅為某些實例,而不為其他的實例指定緩存。
即使緩存受全局控制。但是相同portlet的不同實例可以使用不同的緩存。為了證明這一點,我們將分析這樣一種情況,即開發人員創建了一個名稱為GenericDisplayFilePortlet的portlet。該portlet可以通過個性化設置,基于傳遞到portlet的屬性顯示來自文件系統的靜態HTML文件。如果該portlet在門戶主頁上具有兩個不同的實例,每一個實例顯示一份不同的文件,則這兩個實例的緩存將不發生沖突,每一個portlet實例維護它自己的緩存。
Cache Expires參數是指緩存內容失效之前,緩存保持活動狀態的秒數。如果Cache Expires設置為–1,則任何緩存都不會發生,不管Render Cacheable是否設置為true。
緩存作用域
很多開發人員對portlet緩存產生的第一個誤解是作用于應用。這是錯誤的。portlet cache作用于會話層,這說明每一位個體用戶可以擁有portlet緩存的個體版本。
這就使portlet緩存機制完美的適合緩存個性化的內容,但是portlet緩存不適合緩存靜態內容,這些內容也會呈現給所有用戶,并且很少會失效。舉例來說,按月顯示公司新聞簡報(company newsletter)的portlet不應當使用Render Cacheable參數;而應當使用可以在應用層提供緩存的替代機制。
如果已經為新聞簡報設置了Render Cacheable參數,那么,您可以在會話作用域上為每一次獨立會話緩存其內容。這將在多個緩存中重復不必要的內容,從而降低性能。
一種簡單的替代方法是將緩存移動到一個較低的層中,并且讓portlet正在面對的JSP或者頁面流在該層上執行緩存。在這種情況中,我們可以使用包含在WebLogic中的wl:cache標簽在應用層上緩存內容。有關wl:cache 標簽的詳細文檔請參考下面內容。
另一種替代方法是在門戶緩存中緩存信息;這允許管理員通過使用WebLogic門戶包含的門戶管理員(Portal Administrator)工具,輕松地調整這些緩存。您可以通過各種方式來使用門戶緩存,包括:
- 直接使用門戶緩存API,您可以按需存儲和檢索顯示信息。請參看參考資料一節了解更多信息。
- 另一種方法是,您可以創建一個定制標簽來替代wl:cache,該標簽可以在門戶緩存中緩存信息,以實現更好的受控于門戶管理員。附錄中包含了如何實現該操作的一個簡單示例。
緩存生命周期
我們將討論的有關portlet的第二個誤解涉及到緩存的生命周期。開發人員往往認為是否始終使用緩存取決于以前是否調用過portlet,是否還沒有超過失效時間。事實上,有幾個原因可以解釋在轉換portlet的時候為什么不使用緩存。了解緩存生命周期非常重要,可以確保從緩存中獲得最大程度的優勢。
我們將執行一個非常有趣的實驗,即創建一個使用小型JSP顯示日期和時間的簡單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參數設置為true,并且將Cache Expires設置為30秒。將portlet存放在測試門戶中,然后從WebLogic Workshop運行門戶。您應當看到顯示日期和時間的門戶。現在,請按瀏覽器的刷新(Refresh)按鈕,并觀察日期和時間的變化;沒有使用portlet緩存。此時,可以原諒您會認為portlet緩存已經中斷,但是事實上,它工作正常,如下所示。
為了深入分析該示例,接下來創建一個具有簡單頁面流的新portlet,該頁面流由單個JSP頁面組成。JSP包含一個簡單的表格和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>
當點擊了Refresh(刷新)按鈕之后,該portlet簡單的初始化一次服務器postback操作。在設置該示例的時候,請確保在頁面流編輯器中鏈接刷新操作和JSP頁面。現在,將該portlet存放在緩存先前日期和時間portlet的同一門戶頁面中。
如果您現在從Workshop運行門戶,將可以看到兩種portlets:已經緩存的日期和時間portlet和剛剛創建的postback portlet。如果您刷新瀏覽器,就會出現與先前一樣的行為,即沒有使用緩存。現在,嘗試點擊postback portlet中的Refresh(刷新)按鈕,然后觀察postback執行時,緩存是否按照預期使用。
該示例的要點是證明緩存僅用于portlet生命周期的某些特定部分,尤其是,當沒有明確地證明文件時,緩存僅在portlet加載狀態中使用。不調用該部分portlet生命周期的操作將不使用緩存,因此,緩存和portlet生命周期是密切聯系的。下表綜述了各種門戶交互如何影響緩存。
交互 |
使用緩存 |
通過外部鏈接訪問門戶。 |
不 |
已經緩存的portlet初始化postback。 |
不 |
與已經緩存的portlet在同一頁面中的Portlet初始化postback。 |
是 |
在門戶中的程序塊和頁面之間導航。 |
是 |
_nfls=false參數通過URL傳遞到門戶中。 |
不 |
總而言之,為了最大限度地提高緩存的有效性,掌握與門戶交互相關的緩存生命周期處理方式非常重要。如果一種利用緩存的情況涉及到大量沒有調用緩存的交互,則應當仔細考慮portlet緩存的替代方案。
結束語
在這里總結我們對portlet緩存機制的討論。如您所見,portlet緩存機制不只是表面現象,其內涵豐富,開發人員應當仔細考慮對每一種情況的選擇,以最大限度地獲取緩存的性能優勢。
portlet cache的理想用例是專為每一位用戶訂制,并且經常失效的內容。其他用例應當考慮更加恰當的緩存替代方法,例如使用wl:cache標簽或者門戶緩存。
參考資料
- Workshop文檔
- wl:cache文檔
- Portal Cache文檔
附錄。緩存標簽
示例1. 定制標簽
這是一個簡單的示例,說明了如何使用定制標簽在門戶緩存中緩存內容。它不是一款全面的緩存解決方案,而是證明我們如何把門戶緩存作為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標簽描述符文件。
<?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. 示例緩存標簽及使用這是一個說明緩存標簽如何用在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的一位業務原理咨詢師。
原文出處http://dev2dev.bea.com/products/wlportal81/articles/portlet_caching.jsp