JSR 286 Portlet 的新特性: Portlet 2.0 新特性介紹

關於本文

本文假定讀者熟知 JSR 168 Portlet,並對 J2EE 基本常識有一定了解。本文主要以理論的方式向讀者介紹 JSR 286 Portlet 的以下新增特性:

  • 資源服務
  • 事件
  • 共享呈現參數
  • Portlet 過濾器
  • Portlet 窗口




回頁首


Portlet 和 JSR 168

Portlet 是部署在容器內用來生成動態內容的 Web 組件,與 servlet 類似,portlet 的整個生命週期從 init 到 destroy 的過程都在 portlet 容器中進行。Java Portlet Specification 對 portlet API、 標準化用戶數據、參數設置、portlet 請求以及響應、部署、打包以及安全等方面都做了詳細的規定,以此來實現 portlet 之間以及 portlet 與 portlet 容器之間的交互和協作。 Java Portlet Specification 1.0, 即 Java Specification Request(JSR)168 發佈於 2003 年 10 月。





回頁首


JSR 286 及其新特性

JSR 168 目前在業界受到廣泛支持,而且它由開放源碼支持。標準和產品的第一個版本存在一定的缺陷,僅支持最基本的用例,在功能上有一些限制。而且 Java Portlet Specification V1.0 也存在這種情況,因此,經過三年之後,大多數支持 Java Portlet Specification V1.0 的門戶產品都提供一些附加擴展,以支持更高級的用例,這些附加的擴展造成了各個門戶產品的標準不統一,彼此間的交互協作成了不可避免的問題。爲了更好地規範 portlet 開發,以適應業界發展,並提供適應於最高級別用例的標準解決方案,從而爲這些高級功能提供互操作性,在 2005 年 11 月開始了 Java Portlet Specification V2.0(稱爲 JSR 286)的開發,Java Portlet Specification V2.0 目前已經進入 Final draft 的等待審批階段,並計劃在 2008 年 3 月正式發佈。JSR 286 最終草案兼容了 JSR 168,並完善了 JSR 168 的部分功能,並提供了諸多 JSR 168 所沒有的新特性,例如資源服務、事件、portlet 過濾器、共享呈現參數及 portlet 窗口等。與 V1.0 類似,V2.0 也將基於 J2EE 1.4,因此可讓 Portlet 使用 J2EE 1.4 增強(如 JSP 2.0)。下面是該新規範的一些主要功能及特性:

  1. 資源服務:一種新的通過 portlet 呈現資源的方式。
  2. 事件:通過發送事件和接收事件來實現 portlet 之間的通信。
  3. Portlet 過濾器:與 servlet 過濾器類似,根據 Portlet 請求和響應動態的呈現內容的變換。存在以下四種類型的 portlet 過濾器:
    • Action 過濾器
    • Render 過濾器
    • Resource 過濾器
    • Event 過濾器
  4. 共享呈現參數:除了 portlet 私有的呈現參數之外,新增了可以在 portlet 之間共享的呈現參數。
  5. Portlet 窗口:提供 portlet 窗口 ID 供 portlet 使用。

下面我們將對 JSR 286 所提供的這些新功能及其使用逐一做詳細介紹。





回頁首


資源服務

在 JSR 168 中,Portlet 服務於資源的方法只有兩種:直接鏈接到資源,或者通過 Portlet 服務於資源。兩種方法分別適用於不同目的的需要,各有優缺點。

直接鏈接對於所有 Portlet 狀態都相同的靜態資源非常有效,但對於其他用例效果卻不太好,因爲需要考慮來自 Portlet 上下文的信息。這樣的示例包括基於 Portlet 模式、窗口狀態、當前呈現參數或 Portlet 首選項呈現不同資源。

以一個 JSP 文件 test.jsp 爲例,如果要訪問該資源,可以直接通過超鏈接訪問該文件,如清單 1 所示:


清單 1. 直接訪問資源文件
                
<a href="<c:url value="/test.jsp" />">test.jsp</a>

或者通過 Servlet 轉向,如清單 2 和清單 3 所示:


清單 2. 直接訪問 Servlet
                
<a href="<c:url value="/testServlet" />">testServlet</a>


清單 3. Servlet 對資源文件的訪問控制
                
public void service(ServletRequest request, ServletResponse response) 
    throws ServletException,IOException {
    ...
    在此添加訪問控制等業務邏輯代碼
    ...
    RequestDispatcher rd = request.getRequestDispatcher("/WEB-INF/jsp/test.jsp"); 
    rd.forward(request, response); //或者爲 rd.include(request, response); 
}

從清單 1、2、3 可以看到,直接鏈接到資源這種方式,無法訪問到相關 Portlet 的信息,包括 Portlet 模式、窗口狀態、當前呈現參數或 Portlet 首選項等。而通過 Portlet 呈現資源的優勢是可以通過門戶訪問資源,因此可以通過控制門戶訪問而對資源提供保護。但是,這也帶來了額外的門戶請求開銷,加重了門戶服務器的負載。

爲了更好的解決這兩種方法的侷限性,JSR 286 採用了一種新的資源服務方式 —— Portlet 資源服務。即 JSR 286 引入了一個新的具有 serveResource方法的可選生命週期接口 ResourceServingPortlet ,該接口可以由 ResourceURL 觸發,Portlet 可以通過 PortletResponse.createResourceURL 方法創建它。資源 URL 包含當前 Portlet 的瞬時狀態(Portlet 模式、窗口狀態和呈現參數),但不能爲此狀態設置新值。資源 URL 可以有在資源 URL 上設置的其他資源參數。

通過調用 ResourceServingPortlet 接口的 serveResource() 方法, Portlet 不僅可以通過控制門戶訪問而對資源進行保護,並且 Portlet 容器不會呈現任何除 serveResource() 方法返回的內容之外的附加輸出。這樣,用戶由於可以直接通過操作響應對象而被賦予了更多的控制權限,並且沒有額外門戶請求的開銷,減輕了門戶服務的負載。而 Portal 服務器此時只是充當了一個代理服務器的作用。

JSR 286 資源服務的使用方法:

  1. Portlet 類需實現 javax.portlet.Portlet  javax.portlet.ResourceServingPortlet 接口並實現 serveResource() 方法, 如 清單 4 所示: 

    清單 4. Portlet 對資源文件的訪問控制
                            
    public class TestPortlet implements Portlet, ResourceServingPortlet 
    {
        ......
        public void serveResource(ResourceRequest resourceRequest,
            ResourceResponse resourceResponse) throws PortletException,
            IOException {
            ...
            在此添加訪問控制等業務邏輯代碼
            ...
            PortletRequestDispatcher portletRequestDispatcher = portletConfig
                .getPortletContext().getRequestDispatcher(
                "/WEB-INF/jsp/TestPortletResource.jsp");
            portletRequestDispatcher.include(resourceRequest, resourceResponse);
        }
        ......
    }
    
  2. 使用 JSP 標籤通過 PortletResponse.createResourceURL 方法創建 RecourceURL: 

    清單 5. 創建資源訪問 URL
                            
    <a href="<portlet:resourceURL/>">Click me to request Resource URL</a>
    
  3. 所保護的訪問資源,在此例中即爲 TestPortletResource.jsp 。

接下來,我們就可以充分體驗 JSR 286 資源服務新特性所帶來的簡單便捷以及高性能了。

對照該介紹,讀者可參照本系列第 2 部分對資源服務特性的實例開發加深對該部分相關內容的理解。





回頁首


事件

JSR 286 定義的事件模型是一種鬆耦合的代理事件模型。在此模型中,Portlet 定義可以接收以及在 Portlet 部署描述符中公佈的事件。在運行時,門戶管理員(或業務用戶)可以將不同的 Portlet 連接在一起。

Portlet 事件服務並不是一個可信任消息服務(例如 JMS)的替代。很多情況下 Portlet 事件並不能總是保證能夠傳送到目的地。因此 Portlet 必須能夠在部分或即使所有事件都不能正確接收的情況下仍然能夠工作。

另外,有的時候 Portlet 爲了響應某一個事件,也會向另外的 Portlet 發佈新的事件,這樣就形成了事件的衍生代。這在一定程度上可能造成事件的死鎖,JSR 286 本身沒有對衍生代做出限制,但是很多 Portlet 容器會定義事件的最大衍生代以防止死鎖的發生。讀者在開發相關應用時請注意其本身的限制。

事件聲明

對於一個事件的聲明包括三個部分,分別是事件的定義聲明、事件的發佈載體聲明也就是發佈該事件的 Portlet 聲明、事件接收載體的 Portlet 聲明。

  • 事件定義聲明:我們需要在 portlet.xml 中使用 <event-definition> 元素對事件進行聲明,並且該元素與 <portlet> 元素並列作爲 <portlent-app> 的子元素。 

    清單 6. event-definition 聲明
                            
    <portlet-app id="myPortletApp" version="2.0">
    	<portlet>
    	...
    	</portlet> 
    	<event-definition> . . .</event-definition>
    	...
    </portlet-app>
    

    對於一個事件的聲明有兩點需要注意:事件的名稱和值的類型。對於事件名稱,JSR 286 既可以爲事件定義默認的命名空間,其作用域爲所有未聲明 QName 的事件;也可以爲事件單獨定義自己的 QName。對於 QName 和命名空間的理解,請讀者參考 XML 規範的相關文檔,本文不做詳細介紹。對於事件值的類型,既可以是簡單的 Java 對象,例如 Integer,String 等,也可以是預先定義的 Java 複雜對象,但是前提是該對象必須實現 Serializable 接口。其中 <event-definition> 的具體格式如 清單 7 和 清單 8 所示:



    清單 7. 默認命名空間下事件定義聲明
                            
    <default-namespace>http://cn.ibm.com/</default-namespace>
    ......
    <event-definition>
        <name>event-with-simple-value</name>
        <value-type>java.lang.String</value-type>
    </event-definition>
    
    <event-definition>
        <name>event-with-complex-value</name>
        <value-type>com.ibm.jsr286.TestEventBean</value-type>
    </event-definition>
    



    清單 8. 自定義 QName 下事件定義聲明
                            
    <event-definition>   
        <qname xmlns:key="http://www.ibm.com">event-with-simple-value</qname>
        <value-type>java.lang.Integer</value-type>
    </event-definition>
    
    <event-definition>   
        <qname xmlns:key="http://www.ibm.com">event-with-qname</qname>
        <value-type>com.ibm.jsr286..TestEventBean</value-type>
    </event-definition>
    
  • 事件發佈載體聲明:事件的發佈載體聲明需要在 portlet.xml 的 <portlet> 元素中用 <supported-publishing-event> 關鍵字。對應事件聲明格式,事件發佈載體 Portlet 聲明亦有默認命名空間和自定義命名空間以及簡單對象和複雜對象的情況,見示例: 

    清單 9. 默認命名空間下事件發佈聲明
                            
    <supported-publishing-event>
        <name>event-with-simple-value</name>	
    </supported-publishing-event>
    
    <supported-publishing-event>
        <name>event-with-complex-value</name>	
    </supported-publishing-event>
    



    清單 10. 自定義 QName 下事件發佈聲明
                            
    <supported-publishing-event>
        <qname xmlns:key="http://www.ibm.com">event-with-simple-value</qname>
    </supported-publishing-event>   
    
    <supported-publishing-event>
        <qname xmlns:key="http://www.ibm.com">event-with-complex-value</qname>
    </supported-publishing-event>   
    
  • 事件接收載體聲明與事件發佈載體聲明類似,事件的接收載體聲明需要在 portlet.xml 的 <portlet> 元素中用 <supported-processing-event> 關鍵字。見示例清單 11 和 清單 12: 

    清單 11. 默認命名空間下事件接收載體聲明
                            
    <supported-processing-event>
        <name>event-with-simple-value</name>	
    </supported-processing-event>
    
    <supported-processing-event>
        <name>event-with-complex-value</name>	
    </supported-processing-event>
    



    清單 12: 自定義 QName 下事件接收載體聲明
                            
    <supported-processing-event> 
        <qname xmlns:key="http://www.ibm.com">event-with-simple-value</qname>
    </supported-processing-event>
    
    <supported-processing-event> 
        <qname xmlns:key="http://www.ibm.com">event-with-complex-value</qname>
    </supported-processing-event>
    

事件發佈接收與處理

  • 事件發佈:我們可以在希望發佈事件的 Portlet 的 processAction() 方法裏,通過調用 ActionResponse 的 setEvent() 進行事件發佈,setEvent() 方法的輸入參數爲事件的名稱和對應的值,這些參數必須與我們前面在 portlet.xml 中的事件聲明一致。 

    清單 13. 事件發佈
                            
    public class TestSenderPortlet implements Portlet
    {
        ......
        public void processAction(ActionRequest request,
            ActionResponse response) throws PortletException,
            IOException {
            ......
            response.setEvent(eventName, eventObject);
            ......
        }
        ......
    }
    
  • 事件接收:事件的接收 Portlet 必須實現 javax.Portlet.EventPortlet 接口,事件的接收處理則在該接口包含 processEvent() 方法中進行,JSR 286 定義該方法提供了兩個輸入參數: EventRequest  EventResponse,我們可以通過調用 EventRequest 實例的 getEvent() 方法來獲得當前事件,該方法返回一個事件對象的實例,該實例封裝了事件的唯一標識和對應的值。 

    清單 14: 事件接收
                            
    public class TestReceiverPortlet implements Portlet,EventPortlet
    {
        ......
        public void processEvent(EventRequest request,
            EventResponse response) throws PortletException,
            IOException {
            ......
            Event event = request.getEvent();
            ......
        }
        ......
    }
    
  • 事件處理:獲得事件對象後,我們也可以通過 getQNames() 方法或者 getName() 獲得事件的名稱。兩種獲得事件方法的區別是 getQNames() 可以得到事件的全稱標識,而 getName() 只是取得本地標識名。而取得事件的值則可以通過事件的 getValue() 方法獲得。 

    清單 15: 事件處理
                            
    ......
    public void processEvent(EventRequest request,
        EventResponse response) throws PortletException,
        IOException {
        ......
        Event event = request.getEvent();
        String name = event.getName();// 或者 String qname = event.getQNames();
        String value = event.getValue();
        ......
    }
    ......
    

GenericPortlet API 的變化

在 JSR 168 Portlet 的開發中,開發者通常繼承抽象類 javax.portlet.GenericPortlet 來實現自己的 Portlet 邏輯代碼。 同 JSR 168 相比, JSR 286 的 GenericPortlet 增加了 javax.portlet.EventPortlet  javax.portlet.ResourceServingPortlet 接口的實現,從而增加了事件處理和資源服務的功能。讀者可以從 類圖 1 和 類圖 2 看出 JSR 286 GenericPortlet API 的變化。


圖 1. JSR 168 GenericPortlet 類圖
JSR 168 GenericPortlet 類圖 

圖 2. JSR 286 GenericPortlet 類圖
JSR 286 GenericPortlet 類圖 




回頁首


共享呈現參數

我們先來看一看共享呈現參數的官方介紹:共享呈現用於在 Portlet 之間共享呈現參數,從而創建一個頁面上下文。共享呈現參數在 portlet.xml 文件中聲明。如果這些參數不是空值,Portlet 將自動接收它們。與非共享呈現參數相比,如果應該更改值,Portlet 僅需要設置共享呈現參數。

共享呈現參數,顧名思義,就是指 Portlet 之間共享參數,每一個 Portlet 對該參數的修改都能夠直接被另外支持該參數 Portlet 所獲得。共享呈現參數與 JSR 168 中已經有私有呈現參數的區別就在於,私有呈現參數只爲 Portlet 內部使用,而共享呈現參數則爲多個 Portlet之間通信協作而設置。共享呈現參數與事件相比的優勢就在於避免了事件處理過程調用的繁瑣。

我們舉一個簡單的事例來說明共享呈現參數的優點。假如我們開發了一個關於天氣的 Portlet, 這個 Portlet 可以根據選擇的城市來顯示該城市的天氣情況。我們爲這個 Portlet 定製了郵政編碼這個共有呈現參數來表示用戶選擇的城市。這樣,如果我們再開發一個也有這個共享呈現參數的 Portlet,例如顯示該城市地圖或者旅遊信息的 Portlet。在這種情況下,當我們修改天氣 Portlet 所選擇的城市的話,地圖以及旅遊信息的 Portlet 也會自動做出相應變化。從而實現了不同 Portlet 之間的協作。

共享呈現參數的聲明

對共享呈現參數的使用聲明包括兩個部分,對共享呈現參數定義的聲明和支持共享呈現參數的 Portlet 聲明。

  1. 共享呈現參數定義聲明:對於共享呈現參數定義的聲明必須在 portlet.xml 部署文件中使用 <public-render-parameter> 關鍵字,該元素與 <portlet> 元素並列爲 <portlet-app> 的分支。 

    清單 16. 共享呈現參數定義聲明
                            
    <portlet-app ...>
        <portlet>
            <portlet-name>Portlet A</portlet-name>
        ...
        </portlet>
        ...
        <public-render-parameter>
            <identifier>public-render-param1</identifier>
        </public-render-parameter>
        <public-render-parameter>
            <identifier>public-render-param2</identifier>
        </public-render-parameter>
    </portlet-app>
    
  2. 支持共享呈現參數 Portlet 聲明:對於支持共享呈現參數的 Portlet 的聲明需要在 portlet.xml 中 <portlet> 元素中使用 <supported-public-render-parameter> 關鍵字。 

    清單 17. 共享呈現參數 Portlet 定義聲明
                            
    <portlet>
        <portlet-name>Portlet B</portle-name>
        ......
        <supported-public-render-parameter>
            <identifier>public-render-param1</identifier>
        </supported-public-render-parameter>
    </portlet>    
    
    <portlet>
        <portlet-name>Portlet C</portle-name>
        ......
        <supported-public-render-parameter>
            <identifier>public-render-param2</identifier>
        </supported-public-render-parameter>
    </portlet>
    

共享呈現參數的使用

與非共享呈現參數的使用方法相同,共享呈現參數可以通過 ActionResponse 的 setRenderParameter("標識","值") 方法設定,並通過 RenderRequest 的 getParameter("標識") 來獲得。見 清單 18 和 清單 19


清單 18. Portlet A 設定共享呈現參數
                
...
public void processAction(ActionRequest actionRequest,
        ActionResponse actionResponse) throws PortletException, IOException {
    String publicRenderParamValue1 = actionRequest.getParameter("public-render-param1");
    actionResponse.setRenderParameter("public-render-param1", publicRenderParamValue1);
}
...


清單 19. Portlet B 獲取共享呈現參數
                
...
public void render(RenderRequest renderRequest,
        renderResponse renderResponse) throws PortletException, IOException {
    ...
    String publicRenderParamValue1 = renderRequest.getParameter("public-render-param1");
    ...
}
......





回頁首


Portlet 過濾器

Portlet 過濾器是 JSR 286 提供的有一個非常重要的新特性。事實上,在 JSR 286 之前,就已經有很多廠商(包括 IBM)自定義擴展了 JSR 168,提供了過濾器功能。由此可見,Portlet 過濾器的重要性。爲了避免各種廠商不同 Portlet 過濾器的不兼容性,JCP(Java Community Process)對 JSR 286 定義了標準的過濾器實現。

什麼是 Portlet 過濾器?

與 Servlet 相似,Portlet 過濾器可以使用戶可以改變一個 request 和修改一個 response。Filter 不是一個 Portlet,它不能產生一個 response,它能夠在一個 request 到達 Portlet 之前預處理 request,也可以在離開 Portlet 時處理 response。換句話說,過濾器其實是一個“Portlet chaining”(Portlet 鏈)。它能夠實現的功能包括:

  1. 在 Portlet 被調用之前截獲;
  2. 在 Portlet 被調用之前檢查 servlet request;
  3. 根據需要修改 request 頭和 request 數據;
  4. 根據需要修改 response 頭和 response 數據;
  5. 在 Portlet 被調用之後截獲;

 

Portlet 過濾器與 Servlet 過濾器

事實上,從宏觀功能的角度看來,Portlet 過濾器和 Servlet 過濾器是很相似的。這是因爲二者都可以聲明性地嵌入,從而截獲並修改請求和響應。但是理解它們之間存在着很大的不同是非常重要的。在一定程度上,它們之間的差異是與 Servlet 和Portlet 之間的差異相聯繫的:Servlet 過濾器是一個門戶級過濾器,它可以修改由一些小的部分(來自頁面上所有 Portlet 的響應)集合而成的整個門戶頁面;而 Portlet 過濾器只能用於那些小的部分。Servlet 過濾器(如果已經安裝的話)是接收和修改客戶端請求的第一個組件,同時也是修改對客戶端的響應的最後一個組件(請參見圖 3)。


圖 3. 帶有 Servlet 過濾器和 Portlet 過濾器的客戶端請求事件序列
Portlet and Servlet workflow 

如圖 3 所示,Servlet 請求(步驟 1)在分派給一個或多個 Portlet 請求(步驟 3)之前首先通過一個 Servlet 過濾器鏈進行處理(步驟 2)。在結果集聚到一起(步驟 6 和 7)之前,Portlet 請求進一步轉發到 Portlet 過濾器鏈進行處理(步驟 4)。接着,將集聚的結果發送回 Servlet 過濾器進行處理,之後,將集聚的結果最終顯示給用戶(步驟 9)。

另外一點需要注意的是,Servlet 過濾器比 Portlet 過濾器的優先級別要高,容器將首先進行 Servlet 過濾,其次是 Portlet 過濾。一個過濾器鏈包含一個或多個過濾器。在一個過濾器完成處理之後,新的請求和響應將傳送到鏈上的下一個過濾器;鏈上的最後一個過濾器調用目標資源(Servlet 或 Portlet)。

Portlet 過濾器的工作原理

Portlet 過濾器可以放置在 V2.0 規範提供的任何生命週期方法調用的前面或者後面(processAction、processEvent、render、serveResource),而且還支持這些生命週期方法使用包裝的請求和響應。與 Servlet 過濾器類似,Portlet 過濾器需要在 portlet.xml 部署描述符中進行定義,不同的是,servlet只有一個service()的請求處理方法,因此servlet只有一種類型的過濾器。而portlet卻有四種請求處理方法,於是有四種類型的過濾器,包括:

  1. Action 過濾器
  2. Render 過濾器
  3. Resource 過濾器
  4. Event 過濾器

 

下面我們來介紹四種過濾器的工作原理。

JSR 286 爲 Portlet 過濾器提供了接口類 PortletFilter,該接口提供了兩個方法。

  1. void init(FilterConfig config)
    容器調用一次這個方法來準備用於服務的過濾器。對象 filterConfig 使得過濾器能夠訪問配置參數以及對門戶上下文的引用。
  2. void destroy()
    這個方法是在將過濾器從服務移除之後調用的。這個方法使得過濾器能夠清除任何存放的資源。
JSR 286 爲四種過濾器分別定義了一個接口類,這四個接口類都繼承 PortletFilter 類,並分別添加了各自 doFilter() 方法。關於這幾個類之間的關係,請見下圖:

 


圖 4. Portlet 過濾器繼承圖
Portlet Filter繼承圖 

四種過濾器分別對 Portlet 的四個方法進行攔截。用戶自定義的過濾器必須實現相應的過濾器接口,通過其 doFilter() 方法來實現相應的動作。其對應關係見表 1:


表 1. 過濾器與攔截方法關係圖
過濾器攔截方法
Action 過濾器 processAction(ActionRequest request, ActionResponse response)
Render 過濾器 render(RenderRequest request, RenderResponse response)
Resource 過濾器 serveResource(ResourceRequest request, ResourceResponse response)
Event 過濾器 processEvent(EventRequest request, EventResponse response)

Portlet 過濾器的部署聲明

下面我們通過一個具體的 Portlet 過濾器部署實例來說明。參見清單 20: 
清單 20. Portlet 過濾器聲明

                    
<portlet-app ...>
    ...
    <filter>
        <filter-name>TestRenderFilter</filter-name>     
        <filter-class>com.ibm.jsr286.TestRenderFilter</filter-class>
        <lifecycle>RENDER_PHASE</lifecycle>
    </filter>

    <filter>
        <filter-name>TestAllFilter</filter-name>
        <filter-class>com.ibm.jsr286.TestAllFilter</filter-class>
        <lifecycle>ACTION_PHASE</lifecycle>
        <lifecycle>RENDER_PHASE</lifecycle>
        <lifecycle>EVENT_PHASE</lifecycle>
        <lifecycle>RESOURCE_PHASE</lifecycle>
    </filter>

    <filter-mapping>    
        <filter-name>TestRenderFilter</filter-name>
        <portlet-name>DocumentPortlet</portlet-name>
        </filter-mapping>

    <filter-mapping>    
        <filter-name>TestAllFilter</filter-name>
        <portlet-name>Test*</portlet-name>
    </filter-mapping>
</portlet-app>

 

關於 Portlet 過濾器有幾點需要聲明的是:

  • 對於一個 Portlet 過濾器的聲明亦包括兩部分,過濾器的定義聲明以及過濾器的映射聲明。
  • 一個 Portlet 過濾器可以爲多個 Portlet 服務,而且 一個 Portlet 可以同時有多個 Portlet 過濾器。
  • 一個 Portlet 過濾器可以有多個生命週期階段,當然前提是該 Portlet 過濾器實現了相應過濾器接口。

 





回頁首


Portlet 窗口

Portlet 窗口在 JSR 168 中僅間接地得到反映,並作爲容器爲 Portlet 範圍的會話條目生成的前綴的一部分。JSR 286 規範現在使該 Portlet 窗口 ID 可通過請求供 Portlet 使用,簡單的說就是,PortletRequest 新增了一個方法 getWindowID(),可以獲得 Portlet 的窗口 ID,這個 ID 是由容器生成的。在 Portal 容器中佈局同一個 Portlet 多次的情況下,windowID 可以用來區分同一個 Portlet 的不同窗口,從而可以使這些 Portlet 窗口緩存並呈現不同的數據。

Portlet 窗口支持的一個常見用例是在 Portlet 中緩存數據;例如,一個 Portlet,呈現所使用的數據是通過 web services 從遠端服務器獲得,而且網絡調用速度比較慢,且呈現的數據爲只讀,這種情況下就可以把 web services 獲得的數據和窗口 ID 關聯並緩存起來,在頻繁調用 Portlet 的時候,就不必頻繁等待 web services 的返回。





回頁首

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章