承接本系列第一部分對 JSR 168 Portlet 的回顧與 JSR 286 新特性的概覽,本文將透過在 Apache Pluto 2.0 平台上實際開發與部署 Portlet 應用程式,深入示範 JSR 286 三大核心增強功能的使用方法:資源服務、事件驅動互動,以及共享渲染參數。
本系列專為具備 JSR 168 Portlet 開發基礎、欲掌握 JSR 286 新特性與開發流程的開發者設計。學完本系列後,您將清楚 JSR 286 相較於 JSR 168 具體增強了哪些功能,並能將這些新特性應用於實際開發中。
本文範例使用以下軟體版本(作業系統為 Windows XP):
閱讀前請確已熟悉 JSR 168 基礎並閱讀過第一部分。
Apache Pluto 2.0 為 JSR 286 參考實作,提供 Portlet 2.0 API 的容器執行環境,猶如 Servlet 容器之於 Servlet。目前 Pluto 2.0 已支援資源服務、事件、Portlet 過濾器、共享渲染參數及 Portlet 窗口等新特性。
此步驟略過,請自行完成 JAVA_HOME 與 PATH 設定。
從 Maven 官網 下載最新版壓縮包,解壓後設定 M2_HOME 並將 %M2_HOME%\bin 加入系統 PATH。
從 Tomcat 官網 下載最新版,解壓並設定 TOMCAT_HOME。
使用 SVN 客戶端從官方倉庫棧出:
svn checkout https://svn.apache.org/repos/asf/portals/pluto/trunk/ pluto2
${M2_HOME}\conf\settings.xml,新增 <pluginGroup>org.apache.pluto</pluginGroup>。pluto2\pom.xml,將 <jaxb-impl.version>2.1.2</jaxb-impl.version> 改為 2.1.3。pluto2 目錄執行:mvn install
mvn pluto:install -DinstallDir=${TOMCAT_HOME}
若 Tomcat 路徑含空格,請以雙引號括住:-DinstallDir="C:\Program Files\Apache Software Foundation\Tomcat 6.0"。
commons-logging-api-1.1.jar 放入 ${TOMCAT_HOME}\lib\。編輯 ${TOMCAT_HOME}\conf\tomcat-users.xml,新增 pluto 角色與使用者,範例如下:
<?xml version="1.0" encoding="UTF-8"?>
<tomcat-users>
<role rolename="pluto"/>
<user password="pluto" roles="pluto,manager" username="pluto"/>
...(其餘預設使用者保留)...
</tomcat-users>
啟動 Tomcat(startup.bat),瀏覽器訪問 https://localhost:8080/pluto/portal,若出現登入頁(圖 1)並能以 pluto/pluto 登入進入 Portal 首頁(圖 2),即代表環境建置成功。


TOMCAT_HOME。${TOMCAT_HOME}\webapps(關鍵步驟,否則 Eclipse 啟動 Tomcat 時 Pluto 無法載入)。

jsr286portlets,Target Runtime 選 Apache Tomcat v6.0。META-INF 下建立 context.xml:<Context crossContext="true" />(允許其他 Java EE 程式存取此 Web 應用上下文)。WEB-INF 下建立 portlet.xml,命名空間宣告為 version="2.0",portlet-app_2_0.xsd。

JSR 286 引入 ResourceServingPortlet 介面與 serveResource() 生命週期方法,允許 Portlet 直接提供資源(如圖片、JSON、PDF),且不經 Portal 容器修飾,效能優於傳統 Servlet 轉發。
TestPortlet 實作 Portlet 與 ResourceServingPortlet,於 serveResource() 中 forward 至 /WEB-INF/jsp/TestPortletResource.jsp。TestPortletView.jsp,以 <portlet:resourceURL/> 產生資源請求連結。TestPortletResource.jsp,內容純粹為資源本體。portlet.xml 註冊 TestPortlet(僅支援 VIEW 模式)。web.xml 新增 Pluto 專用 Servlet 定義與映射(非 JSR 286 標準要求)。程式碼片段:
// TestPortlet.java 關鍵片段
public void serveResource(ResourceRequest req, ResourceResponse resp)
throws PortletException, IOException {
getPortletContext().getRequestDispatcher("/WEB-INF/jsp/TestPortletResource.jsp")
.include(req, resp);
}
<!-- TestPortletView.jsp -->
<a href="<portlet:resourceURL/>">Click me to request Resource URL</a>
TestPortlet 加入該頁。TestPortletResource.jsp 內容,無 Portal 裝飾框,證明資源服務運作正常。

JSR 286 採鬆耦合代理事件模型:Portlet 於 portlet.xml 宣告支援發布/處理的事件,執行期由 Portal 管理員連線。事件非可靠訊息服務(如 JMS),開發者需容忍事件可能遺失;亦需注意事件鏈衍生深度限制以防死鎖。
<event-definition> 指定名稱(可含 QName)與 <value-type>(需實作 Serializable)。<supported-publishing-event>。<supported-processing-event>。TestSimpleEventSenderPortlet 於 processAction() 呼叫 actionResponse.setEvent("simple-event", "simple-event is sent by " + portletName)。TestSimpleEventReceiverPortlet 實作 EventPortlet,於 processEvent() 取得 Event 物件,將名稱與值寫入 renderParameter 供 View 顯示。portlet.xml 同步定義 simple-event(value-type: java.lang.String)與雙方宣告。SampleComplexEvent(含 int、String、Date 欄位)。setEvent("complex-event", eventObj);接收端 processEvent() 取出並拆解欄位寫入渲染參數。portlet.xml 定義 complex-event,value-type: com.ibm.samples.jsr286.events.SampleComplexEvent。將兩組 Portlet 部署至同一頁面,點擊發送端按鈕,接收端即顯示對應事件資訊(圖 18-23)。

共享渲染參數(Public Render Parameter)讓多個 Portlet 能共享同一參數值,任一 Portlet 修改即自動同步至其他支援該參數的 Portlet,避免事件處理的繁瑣流程,適合建立頁面層級的上下文(如共同的城市代碼、使用者偏好)。
portlet.xml 全域定義 <public-render-parameter><identifier>public-render-param</identifier></public-render-parameter>。<supported-public-render-parameter>public-render-param</supported-public-render-parameter> 宣告支援。actionResponse.setRenderParameter("public-render-param", value) 設定,renderRequest.getParameter("public-render-param") 取得。TestPortlet 新增表單輸入框,processAction() 將輸入值寫入共享參數。TestPublicRenderParameterPortlet 僅於 View 階段讀取該參數顯示。

本文完整示範了 Apache Pluto 2.0 的建置流程、Eclipse 開發環境配置,以及 JSR 286 三大核心新特性——資源服務、事件機制、共享渲染參數——的實際開發步驟與程式碼範例。提醒讀者:JSR 286 規範與 Pluto 2.0 當時均處於開發階段,實驗時需留意容器本身的 Bug。