首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 相關知識

JSR 286 Portlet 新特性全覽(一):Portlet 2.0 核心增強功能詳細解析

     編輯:Java 相關知識

Java Portlet 規格自 JSR 168(2003 年發布)以來廣獲業界支持,但首版功能僅涵蓋基礎用例,導致各 Portal 廠商紛紛自行擴展,造成標準不一、互通性差。為解決此問題,JCP 於 2005 年 11 月啟動 JSR 286(Java Portlet Specification V2.0)開發,旨在提供標準化的高階功能解決方案。JSR 286 於 2008 年 3 月正式發布,完全相容 JSR 168,並基於 J2EE 1.4,可利用 JSP 2.0 等增強特性。

五大核心新特性

  1. 資源服務:全新資源提供方式,解決直接連結與 Portal 轉發的雙重缺點。
  2. 事件機制:鬆耦合代理事件模型,實現 Portlet 間跨請求通訊。
  3. Portlet 過濾器:四類過濾器攔截生命週期方法,動態轉換請求/回應。
  4. 共享渲染參數:跨 Portlet 共享渲染參數,建立頁面層級上下文。
  5. Portlet 窗口:暴露窗口 ID,支援同一 Portlet 多實例區分與資料快取。

詳細特性解析

一、資源服務

JSR 168 兩種舊模式缺點:

  • 直接連結靜態資源:無法存取 Portlet 模式、視窗狀態、渲染參數、偏好設定等上下文。
  • 經由 Portlet/Servlet 轉發:雖可受 Portal 保護,但增加 Portal 請求開銷,加重伺服器負載。

JSR 286 解決方案:引入可選介面 ResourceServingPortlet 及 serveResource(ResourceRequest, ResourceResponse) 方法。Portlet 透過 PortletResponse.createResourceURL() 產生資源 URL,攜帶當前 Portlet 瞬時狀態(模式、視窗狀態、渲染參數),但不允許修改狀態;可額外附加資源參數。容器僅輸出 serveResource() 回傳內容,無額外 Portal 修飾,效能大幅提升,Portal 僅扮演代理角色。

// 介面實作範例
public class TestPortlet implements Portlet, ResourceServingPortlet {
    public void serveResource(ResourceRequest req, ResourceResponse resp) 
        throws PortletException, IOException {
        // 業務邏輯與存取控制
        getPortletContext().getRequestDispatcher("/WEB-INF/jsp/TestPortletResource.jsp")
            .include(req, resp);
    }
}
// JSP 中產生資源 URL
<a href="<portlet:resourceURL/>">請求資源</a>

二、事件機制

採鬆耦合代理事件模型:Portlet 於部署描述符宣告可發布/處理的事件,執行期由 Portal 管理員連線。事件非可靠訊息服務,開發者需容忍遺失;事件鏈衍生深度可能受容器限制以防死鎖。

事件宣告三層次

  1. 事件定義(<event-definition>):指定名稱(支援預設命名空間或自訂 QName)與 <value-type>(簡單型別或實作 Serializable 的複雜物件)。
  2. 發布者宣告(<supported-publishing-event>):於 <portlet> 內宣告支援發布的事件。
  3. 接收者宣告(<supported-processing-event>):於 <portlet> 內宣告支援處理的事件。

發布與處理流程

  • 發布:於 processAction() 呼叫 actionResponse.setEvent(eventName, eventObject)。
  • 接收:Portlet 實作 EventPortlet 介面,於 processEvent(EventRequest, EventResponse) 中透過 eventRequest.getEvent() 取得事件物件,再以 getName()/getQName() 取名稱,getValue() 取值。

GenericPortlet API 變化

JSR 286 的 GenericPortlet 新增實作 EventPortlet 與 ResourceServingPortlet,提供 processEvent()、serveResource() 預設實作,簡化開發。

JSR 168 GenericPortlet 類圖 JSR 286 GenericPortlet 類圖

三、共享渲染參數

JSR 168 僅有私有渲染參數(Portlet 內部使用)。JSR 286 新增共享渲染參數,多個 Portlet 宣告支援同一參數識別碼,任一 Portlet 以 setRenderParameter() 修改,其他 Portlet 於渲染階段自動可見,無需事件處理開銷。

宣告方式

  1. 全域定義:<public-render-parameter><identifier>paramName</identifier></public-render-parameter>(<portlet-app> 直屬)。
  2. Portlet 宣告支援:<supported-public-render-parameter>paramName</supported-public-render-parameter>(<portlet> 內)。

使用範例

天氣 Portlet 以郵遞區號為共享參數;地圖、旅遊資訊 Portlet 同樣宣告支援。使用者於天氣 Portlet 切換城市,其他 Portlet 即時同步更新。

// 設定共享參數
actionResponse.setRenderParameter("zipCode", "10001");
// 取得共享參數
String zip = renderRequest.getParameter("zipCode");

四、Portlet 過濾器

JSR 286 標準化過濾器,解決廠商擴展不相容問題。過濾器非 Portlet,不產生回應,但可攔截請求/回應進行預處理/後處理(修改標頭、資料、攔截調用)。

與 Servlet 過濾器差異

  • Servlet 過濾器為 Portal 層級,處理整個聚合頁面;Portlet 過濾器僅針對單一 Portlet 片段。
  • 請求流向:Client → Servlet Filter Chain → Portlet Request Dispatch → Portlet Filter Chain → Portlet → Portlet Filter Chain → Aggregation → Servlet Filter Chain → Client。
  • 優先序:Servlet 過濾器先於 Portlet 過濾器執行。

四類過濾器對應生命週期

過濾器類型攔截方法
Action FilterprocessAction(ActionRequest, ActionResponse)
Render Filterrender(RenderRequest, RenderResponse)
Resource FilterserveResource(ResourceRequest, ResourceResponse)
Event FilterprocessEvent(EventRequest, EventResponse)

所有過濾器實作 PortletFilter(init()、destroy())及各自的 doFilter()。部署描述符以 <filter> 定義類別與 <lifecycle>,以 <filter-mapping> 繫結 Portlet(支援通配符)。單一過濾器可服務多 Portlet、跨多生命週期;單一 Portlet 可掛載多過濾器形成鏈。

帶有 Servlet 過濾器和 Portlet 過濾器的客戶端請求事件序列 Portlet 過濾器繼承圖

五、Portlet 窗口

JSR 168 僅間接透過 Session 屬性前綴反映窗口 ID。JSR 286 新增 PortletRequest.getWindowID(),由容器產生唯一 ID。同一 Portlet 於頁面多處佈局時,可用 Window ID 區分實例,進而針對不同窗口快取資料(如緩慢 Web Service 呼叫結果),避免重複請求。

結語

本文系統梳理了 JSR 286 五大核心增強功能的理論基礎、宣告機制與運作原理。後續兩篇將透過 Apache Pluto 2.0 實際開發部署範例,示範各特性的具體應用步驟,敬請期待。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved