在本系列的 第 1 部分 簡要回顧了 JSR 168 Portlet,並對 JSR 286 Portlet 的新增特性做了詳細的介紹, 本文將通過在 Apache Pluto 2.0 平台上開發和部署 Portlet 應用程序, 向讀者介紹 JSR 286 Portlet 新特性的使用方法。本文將首先介紹 JSR 286 參考實 現 Apache Pluto 2.0 平台的構建過程,然後通過在 Apache Pluto 2.0 平台上開發和部署 JSR 286 Portlet 應用程序, 向讀者介紹 JSR 286 Portlet 資源服務和新增的交互功能:事件和共享呈現參數。
關於本系列
本系列 專門針對具有 JSR 168 Portlet 開發基礎,並且想了解 JSR 286 Portlet 新特性和開發流程的開發人員。在學完本系列後, 您將了解到相對於 JSR 168 Portlet,JSR 286 Portlet 究竟提供了哪些增強功能, 以及這些新增特性在實際開發中的應用。
本系列的 第 1 部分 簡單回顧了 JSR 168 Portlet, 並列出了 JSR 286 Portlet 的新增內容。第 2 部分和第 3 部分將通過在 Apache Pluto 2.0 平台上開發和部署 Portlet 應用程序, 向讀者介紹 JSR 286 Portlet 新特性的使用方法。
關於本文
本文將首先介紹 JSR 286 參考實現 Apache Pluto 2.0 平台的構建過程,然後通過在 Apache Pluto 2.0 平台上開發和部署 JSR 286 Portlet 應用程序, 向讀者介紹 JSR 286 Portlet 資源服務和新增的交互功能:事件和共享呈現參數。
Portlet 過濾器和 Portlet 窗口方面應用程序的開發過程,將在第 3 部分進行詳細介紹。
在示例應用程序的開發和部署中用到了下列產品:
Sun JDK 1.5
Apache Tomcat 6.x
Apache Pluto 2.0
Apache Maven 2.x
Eclipse Europa(Eclipse V3.3) for JavaEE Developers
閱讀本文之前,您應當對 JSR 168 Portlet 有所了解,並閱讀了本系列的 第 1 部分。
准備工作
Apache Pluto 2.0 是 JSR 286 的參考實現,是實現了 Portlet 2.0 API 的 Portlet 容器,充當 Portlet 的運行時環境,與 web 應 用服務器的 Servlet 容器的運行時環境支持 Servlet 的情形非常相似。Pluto 2.0 目前支持的 JSR 286 Portlet 新特性有資源服務、事 件、Portlet 過濾器、共享呈現參數、 Portlet 窗口。
在本文中,我們將使用 Apache Pluto 2.0 開發測試我們的 JSR 286 Portlet 應用程序。以下操作均在 Windows XP操作系統環境下進 行。
1. 構建 JSR 286 Portlet 運行環境 Apache Pluto 2.0
Apache Pluto 2.0 目前還處於開發階段,我們只能通過其源代碼構建出一個支持 JSR 286 Portlet 標准的 Portlet 2.0 容器。
安裝 Sun JDK 1.5 並設定環境變量
該步驟一般讀者都比較熟悉,不再拗述。需要注意的是,經過筆者測試,Pluto 2.0 源碼工程只可以在 Sun JDK 1.5 下構建成功,筆 者使用 Sun JDK 1.6 和 IBM JDK 1.5 均構建失敗。
安裝 Maven 2
Pluto 源代碼使用 Maven 2 進行項目管理和構建,我們必須首先安裝該工具。
從 http://maven.apache.org/ 上尋找 Maven 2 的最新版本壓縮包,下載並解壓,設定 Maven 2 的安裝路徑為 ${M2_HOME}。將 ${M2_HOME}\bin 目錄加到系統的 PATH 環境變量中。
安裝 Tomcat 6
從 http://tomcat.apache.org/ 上尋找 Tomcat 6 的最新版本壓縮包,下載並解壓,設定安裝路徑為 ${TOMCAT_HOME}。
獲取 Apache Pluto 2.0 源碼
使用 SVN 客戶端從官方 SVN 服務器上獲得源代碼:
清單 1. 使用 SVN 客戶端從官方 SVN 服務器上獲得源代碼
svn checkout https://svn.apache.org/repos/asf/portals/pluto/trunk/ pluto2
使用 Maven 2 構建 Pluto 2.0
編輯 ${M2_HOME}\conf 目錄下的 settings.xml 文件,增加 <pluginGroups> 元素:
清單 2. settings.xml 文件
<settings>
...
<pluginGroups>
<pluginGroup>org.apache.pluto</pluginGroup>
</pluginGroups>
...
</settings>
打開 pluto2 目錄下的 pom.xml 文件,找到
清單 3. pom.xml 文件
...
<jaxb-impl.version>2.1.2</jaxb-impl.version>
...
改為
清單 4. pom.xml 文件
<jaxb-impl.version>2.1.3</jaxb-impl.version>
命令行模式下進入 pluto2 目錄,執行以下命令:
清單 5.
D:\>cd pluto2
D:\pluto2>mvn install
D:\pluto2>mvn pluto:install -DinstallDir=${TOMCAT_HOME}
如果您的 Tomcat 安裝路徑中存在空格,則需要用雙引號把路徑引起來:
清單 6.
mvn pluto:install
-DinstallDir="C:\Program Files\Apache Software Foundation\Tomcat 6.0"
從網上尋找 commons-logging-api-1.1.jar 文件,拷貝到 ${TOMCAT_HOME}\lib\ 目錄下。
至此,pluto2.0 的相關文件就被安裝到 tomcat 相應目錄下。
編輯 ${TOMCAT_HOME}\conf\tomcat-users.xml 文件,添加角色 pluto,並在該角色下新增一個用戶,以下為示例文件:
清單 7. tomcat-users.xml 文件
<?xml version="1.0" encoding="UTF-8"?>
<tomcat-users>
<role rolename="role1"/>
<role rolename="pluto"/>
<role rolename="tomcat"/>
<role rolename="manager"/>
<user password="pluto" roles="pluto,manager" username="pluto"/>
<user password="tomcat" roles="role1" username="role1"/>
<user password="tomcat" roles="tomcat,role1" username="both"/>
<user password="tomcat" roles="tomcat,pluto,manager" username="tomcat"/>
</tomcat-users>
驗證安裝
運行 ${TOMCAT_HOME}\bin\startup.bat,啟動 tomcat 服務器。浏覽器訪問 URL http://localhost:8080/pluto/portal,如圖 1 所 示:
圖 1. Pluto 登錄界面
輸入添加到 pluto 角色的用戶名和密碼,進入 Pluto 的 Portal 頁面:
圖 2. Pluto Portal界面
至此,JSR 286 Portlet 運行環境 Apache Pluto 2.0 搭建成功。
2. 使用 Eclipse Europa 建立開發環境
首先,需要 從 Eclipse 官方網站 http://www.eclipse.org 下載 Eclipse Europa,針對不同的開發需求,有幾種包可供下載。我們進行的是 J2EE Web 開發,所以注意要下載 Eclipse IDE for Java EE Developers。
啟動 Eclipse,對 Eclipse 進行配置:
執行菜單項 目 Window -> Preferences,打開 Preferences 對話框,選擇 Server -> Installed Runtimes 項,如 圖 3 所示:
圖 3. Preferences 對話框
點擊 Add 按鈕,將 Tomcat 6 添加為運行時,如 圖 4、圖 5 所示:
圖 4. 選擇運行時類型
圖 5. 設定 Tomcat 安裝路徑
單擊 Finish 結束配置,單擊 OK 關閉 Preferences 對話框。
在 Eclipse 的 Servers 視圖中單擊鼠標右鍵,選擇 New -> Server 。如 圖 6 所示:
圖 6. 新建服務器
在彈出的窗口中選擇目標運行服務器 Apache Tomcat 6.0 Server,運行時呈現 Apache Tomcat v6.0,如圖7所示,點擊 Finish。
圖 7. 選擇目標運行服務器
在 Servers 視圖中雙擊剛剛新建的 Tomcat 服務器,打開服務器配置頁面,如圖 8 所示:
圖 8. Tomcat 服務器配置頁面
在 Server Locations 中選擇 Use Tomcat Installation,Deploy Path選擇 ${TOMCAT_HOME}\webapps,如圖 9 所示。至此開發環境 設置完畢。
必須設定 Deploy Path 為 Tomcat 安裝目錄下的 webapps 目錄,否則使用 Eclipse 啟動 Tomcat 後,Pluto 不能加載進來。
圖 9. Tomcat 服務器配置
創建 JSR 286 Portlet 應用
下面,我們開始創建一系列程序來演示 JSR 286 Portlet 的新特性。主要分為以下六個部分:
使用 Eclipse 創建 Portlet Web 項目
資源服務
事件
Portlet 過濾器
共享呈現參數
Portlet 窗口
1. 使用 Eclipse 創建 Portlet Web 項目
新建項目,項目類型選擇 Web->Dynamic Web Project,如圖 10 所示:
圖 10. 新建動態 Web 項目
接下來,設置項目屬性,項目名稱 jsr286portlets, 目標運行時 Apache Tomcat V6.0,保留默認設置,點擊 Finish,如 圖 11 所示 :
圖 11. 設置項目屬性
生成項目結構如圖 12:
圖 12. 項目結構
在 META-INF 下新建 context.xml 文件,內容如下:
清單 8. context.xml 文件
<Context crossContext="true" />
該文件為 Tomcat 的特有配置文件,根據 Pluto 的要求,該 Web 工程的上下文應該可以被其它 JavaEE 程序訪問,所以 crossContext 參數設置為 true。
在 WEB-INF 下新建 portlet.xml 文件,內容如下:
清單 9. portlet.xml 文件
<?xml version="1.0" encoding="UTF-8"?>
<portlet-app
xmlns="http://java.sun.com/xml/ns/portlet/portlet-app_2_0.xsd"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/portlet/portlet-app_2_0.xsd
http://java.sun.com/xml/ns/portlet/portlet-app_2_0.xsd"
version="2.0">
<!-- 在該位置填寫portlet描述內容 -->
</portlet-app>
下面我們將在黑體部分填寫 portlet 定義。
2. 資源服務
新增 Java 類 TestPortlet,實現了 javax.portlet.Portlet 和 javax.portlet.ResourceServingPortlet 接口:
清單 10. TestPortlet.java 文件
package com.ibm.samples.jsr286.portlets;
import ...
public class TestPortlet implements Portlet, ResourceServingPortlet {
private PortletConfig portletConfig;
public void init(PortletConfig portletConfig) throws PortletException {
this.portletConfig = portletConfig;
}
public void destroy() {
}
public void processAction(ActionRequest actionRequest,
ActionResponse actionResponse) throws PortletException, IOException {
}
public void render(RenderRequest renderRequest,
RenderResponse renderResponse) throws PortletException, IOException {
PortletRequestDispatcher portletRequestDispatcher = portletConfig
.getPortletContext().getRequestDispatcher(
"/WEB-INF/jsp/TestPortletView.jsp");
portletRequestDispatcher.include(renderRequest, renderResponse);
}
public void serveResource(ResourceRequest resourceRequest,
ResourceResponse resourceResponse) throws PortletException,
IOException {
PortletRequestDispatcher portletRequestDispatcher = portletConfig
.getPortletContext().getRequestDispatcher(
"/WEB-INF/jsp/TestPortletResource.jsp");
portletRequestDispatcher.include(resourceRequest, resourceResponse);
}
}
在 WEB-INF 目錄下新建 jsp 目錄,在 jsp 目錄下新建 portlet 呈現階段所顯示的 jsp 文件 TestPortletView.jsp。
清單 11. TestPortletView.jsp 文件
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@taglib prefix="portlet" uri="http://java.sun.com/portlet_2_0"%>
<portlet:defineObjects />
<table>
<tr>
<td><h1>Test portlet page.</h1></td>
</tr>
<tr>
<td><a href="<portlet:resourceURL/>">Click me to request Resource URL</a></td>
</tr>
</table>
在 jsp 目錄下新建 portlet 資源服務所請求的 jsp 文件 TestPortletResource.jsp。
清單 12. TestPortletResource.jsp 文件
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@taglib prefix="portlet" uri="http://java.sun.com/portlet_2_0"%>
<portlet:defineObjects />
<table>
<tr>
<td><h1>Test portlet resource page.</h1></td>
</tr>
</table>
編輯 portlet.xml 文件, 為 TestPortlet 增加一個 portlet 定義片斷,該 TestPortlet 僅支持 View 模式。
清單 13. TestPortlet 定義片斷
<portlet>
<portlet-name>TestPortlet</portlet-name>
<display-name>TestPortlet</display-name>
<portlet-class>com.ibm.samples.jsr286.portlets.TestPortlet</portlet-class>
<supports>
<mime-type>text/html</mime-type>
<portlet-mode>VIEW</portlet-mode>
</supports>
<portlet-info>
<title>TestPortlet</title>
</portlet-info>
</portlet>
編輯 web.xml 文件,增加 Pluto 所需的 servlet 定義及映射。讀者請注意,該定義為 Pluto 2.0 Portlet 容器所需,不屬於 JSR 286 標准的要求。
清單 14. Pluto 所需的 servlet 定義及映射片斷
<servlet>
<servlet-name>TestPortlet</servlet-name>
<servlet-class>
org.apache.pluto.core.PortletServlet
</servlet-class>
<init-param>
<param-name>portlet-name</param-name>
<param-value>TestPortlet</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>TestPortlet</servlet-name>
<url-pattern>/PlutoInvoker/TestPortlet</url-pattern>
</servlet-mapping>
在 Eclipse 的 Servers 視圖中,右鍵單擊 Tomcat 服務器,點擊 Add and Remove Projects,在彈出的對話框中將 jsr286portlets 項目添加到右側欄目中,點擊 Finish 確認,如圖13:
圖 13. 部署項目到服務器
在 Servers 視圖中啟動服務器,Console 視圖中輸出 Tomcat 啟動信息。
浏覽器中輸入相應 url 訪問 pluto 的 portal 頁面,登錄,點擊 Pluto Admin 導航欄,如圖14:
圖 14. Pluto 管理界面
使用該工具新建一個頁面,如 "Test JSR 286 Portlet Page"。導航欄中馬上新增一項 "Test JSR 286 Portlet Page",點擊進入該頁 面可以見到目前該頁面沒有內容。
選擇 jsr286portlets 應用程序中的 Portlet TestPortlet,選擇上一步新建的頁面,點擊 Add Portlet 按鈕,將 TestPortlet 布局 到 "Test JSR 286 Portlet Page"頁面。如圖 15:
圖 15. 布局 Portlet 到 Portal 頁面
進入"Test JSR 286 Portlet Page"頁面,該頁面新增了一個 Portlet TestPortlet,如圖16:
圖 16. TestPortlet 界面
注意到上圖 portlet 的標題顯示為 null, 這是由於 pluto 2.0 目前處於開發階段,存在一些 bug,讀者可不必理會。
點擊超鏈接,進入所請求的資源頁面,如圖 17:
圖 17. TestPortlet 資源界面
觀察此頁面,發現此頁面只顯示了 TestPortletResource.jsp 的內容,未經過 Portal 容器的修飾, 和直接請求一個 Servlet 或者 JSP 頁面的效果是一樣的。這就是 JSR 286 Portlet 資源服務的主要特性。對照此示例,讀者可加深對 第 1 部分 相關內容的理解。
3. 事件
簡單事件
新建 Java 類 TestSimpleEventSenderPortlet, 在該 Portlet 類的 processAction 方法中,發送一個簡單事件,事件內容為一個字 符串。
清單 15. TestSimpleEventSenderPortlet.java 文件
package com.ibm.samples.jsr286.portlets;
import ...
public class TestSimpleEventSenderPortlet implements Portlet {
...
public void processAction(ActionRequest actionRequest,
ActionResponse actionResponse) throws PortletException, IOException {
actionResponse.setEvent("simple-event", "simple-event is sent by "
+ portletConfig.getPortletName());
}
public void render(RenderRequest renderRequest,
RenderResponse renderResponse) throws PortletException, IOException {
PortletRequestDispatcher portletRequestDispatcher = portletConfig
.getPortletContext().getRequestDispatcher(
"/WEB-INF/jsp/TestSimpleEventSenderPortletView.jsp");
portletRequestDispatcher.include(renderRequest, renderResponse);
}
}
在 jsp 目錄下新建 jsp 文件 TestSimpleEventSenderPortletView.jsp
清單 16. TestSimpleEventSenderPortletView.jsp 文件
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@taglib prefix="portlet" uri="http://java.sun.com/portlet_2_0"%>
<portlet:defineObjects />
<form action="<portlet:actionURL/>">
<table>
<tr>
<td><h1>Test simple event sender portlet page.</h1></td>
</tr>
<tr>
<td>
<input type="submit" value="Click me to send simple event to other portlets">
</td>
</tr>
</table>
</form>
新建 Java 類 TestSimpleEventReceiverPortlet, 在該 Portlet 實現了 javax.portlet.EventPortlet 接口,可以響應事件。
清單 17. TestSimpleEventReceiverPortlet.java 文件
package com.ibm.samples.jsr286.portlets;
import ...
public class TestSimpleEventReceiverPortlet implements Portlet, EventPortlet {
...
public void processAction(ActionRequest actionRequest,
ActionResponse actionResponse) throws PortletException, IOException {
}
public void render(RenderRequest renderRequest,
RenderResponse renderResponse) throws PortletException, IOException {
PortletRequestDispatcher portletRequestDispatcher = portletConfig
.getPortletContext().getRequestDispatcher(
"/WEB-INF/jsp/TestSimpleEventReceiverPortletView.jsp");
portletRequestDispatcher.include(renderRequest, renderResponse);
}
public void processEvent(EventRequest eventRequest,
EventResponse eventResponse) throws PortletException, IOException {
Event event = eventRequest.getEvent();
eventResponse.setRenderParameter("eventName", event.getName());
eventResponse.setRenderParameter("eventValue", event.getValue().toString());
}
}
在 jsp 目錄下新建 jsp 文件 TestSimpleEventReceiverPortletView.jsp
清單 18. TestSimpleEventReceiverPortletView.jsp 文件
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@taglib prefix="portlet" uri="http://java.sun.com/portlet_2_0"%>
<portlet:defineObjects />
<table>
<tr>
<td><h1>Test simple event receiver portlet page.</h1></td>
</tr>
<tr>
<td><h2>Received simple event:</h2></td>
</tr>
<tr>
<td>Event name:<%=renderRequest.getParameter("eventName")%></td>
</tr>
<tr>
<td>Event value:<%=renderRequest.getParameter("eventValue")%></td>
</tr>
</table>
在 portlet.xml 文件中新增 TestSimpleEventSenderPortlet 定義, 該 portlet 支持事件的發布,注意 supported-publishing- event 元素中定義所支持發布的事件名稱為 simple-event。
清單 19. TestSimpleEventSenderPortlet 定義
<portlet>
<portlet-name>TestSimpleEventSenderPortlet</portlet-name>
<display-name>TestSimpleEventSenderPortlet</display-name>
<portlet-class>
com.ibm.samples.jsr286.portlets.TestSimpleEventSenderPortlet
</portlet-class>
<supports>
<mime-type>text/html</mime-type>
<portlet-mode>VIEW</portlet-mode>
</supports>
<portlet-info>
<title>TestSimpleEventSenderPortlet</title>
</portlet-info>
<supported-publishing-event>
<name>simple-event</name>
</supported-publishing-event>
</portlet>
在 portlet.xml 文件中新增 TestSimpleEventReceiverPortlet 定義, 該 portlet 支持事件的響應處理,注意 supported- processing-event 元素中定義所支持處理的事件名稱為 simple-event。
清單 20. TestSimpleEventReceiverPortlet 定義
<portlet>
<portlet-name>TestSimpleEventReceiverPortlet</portlet-name>
<display-name>TestSimpleEventReceiverPortlet</display-name>
<portlet-class>
com.ibm.samples.jsr286.portlets.TestSimpleEventReceiverPortlet
</portlet-class>
<supports>
<mime-type>text/html</mime-type>
<portlet-mode>VIEW</portlet-mode>
</supports>
<portlet-info>
<title>TestSimpleEventReceiverPortlet</title>
</portlet-info>
<supported-processing-event>
<name>simple-event</name>
</supported-processing-event>
</portlet>
您還需要在 portlet.xml 文件中添加以下聲明,定義 QName 默認的命名空間和事件定義,該事件類型為 java.lang.String。
清單 21. simple-event 定義
<default-namespace>http://cn.ibm.com/</default-namespace>
<event-definition>
<name>simple-event</name>
<value-type>java.lang.String</value-type>
</event-definition>
參照 TestPortlet 的定義,為 TestSimpleEventSenderPortlet 和 TestSimpleEventReceiverPortlet 在 web.xml 裡添加 Pluto 所 需的 servlet 定義及映射。
將 TestSimpleEventSenderPortlet 和 TestSimpleEventReceiverPortlet 部署到"Test JSR 286 Portlet Page"頁面,如圖 18 和 圖 19。
圖 18. 簡單事件發布 portlet
圖 19. 簡單事件響應 portlet
點擊 TestSimpleEventSenderPortlet 中的按鈕,TestSimpleEventReceiverPortlet 如圖 20 所示:
圖 20. 簡單事件響應
表明 TestSimpleEventReceiverPortlet 接收到了名為 simple-event 的事件,事件值為 "simple-event is sent by TestSimpleEventSenderPortlet"。
復合事件
定義一個 復合事件 Java 類 SampleComplexEvent, 該類是可序列化的,並且存在 int, String, Date 三種類型的屬性。
清單 22. SampleComplexEvent.java 文件
package com.ibm.samples.jsr286.events;
import ...
public class SampleComplexEvent implements Serializable {
private static final long serialVersionUID = -1447091586272283310L;
private int intItem;
private String strItem;
private Date dateItem;
//setters and getters
...
}
新建 Java 類 TestComplexEventSenderPortlet, 在該 Portlet 類的 processAction 方法中,發送一個復合事件,事件類型為 com.ibm.samples.jsr286.events.SampleComplexEvent。
清單 23. TestComplexEventSenderPortlet.java 文件
package com.ibm.samples.jsr286.portlets;
import ...
public class TestComplexEventSenderPortlet implements Portlet {
...
public void processAction(ActionRequest actionRequest,
ActionResponse actionResponse) throws PortletException, IOException {
SampleComplexEvent event = new SampleComplexEvent();
event.setIntItem(new Random().nextInt());
event.setStrItem("complex-event is sent by "
+ portletConfig.getPortletName());
event.setDateItem(new Date());
actionResponse.setEvent("complex-event", event);
}
public void render(RenderRequest renderRequest,
RenderResponse renderResponse) throws PortletException, IOException {
PortletRequestDispatcher portletRequestDispatcher = portletConfig
.getPortletContext().getRequestDispatcher(
"/WEB-INF/jsp/TestComplexEventSenderPortletView.jsp");
portletRequestDispatcher.include(renderRequest, renderResponse);
}
}
在 jsp 目錄下新建 jsp 文件 TestComplexEventSenderPortletView.jsp, 內容同 清單 16. TestSimpleEventSenderPortletView.jsp 文件 類似。
新建 Java 類 TestComplexEventReceiverPortlet, 在該 Portlet 實現了 javax.portlet.EventPortlet 接口,可以響應復合事件。
清單 24. TestComplexEventReceiverPortlet.java 文件
package com.ibm.samples.jsr286.portlets;
import ...
public class TestComplexEventReceiverPortlet implements Portlet, EventPortlet {
...
public void processAction(ActionRequest actionRequest,
ActionResponse actionResponse) throws PortletException, IOException {
}
public void render(RenderRequest renderRequest,
RenderResponse renderResponse) throws PortletException, IOException {
PortletRequestDispatcher portletRequestDispatcher = portletConfig
.getPortletContext().getRequestDispatcher(
"/WEB-INF/jsp/TestComplexEventReceiverPortletView.jsp");
portletRequestDispatcher.include(renderRequest, renderResponse);
}
public void processEvent(EventRequest eventRequest,
EventResponse eventResponse) throws PortletException, IOException {
Event event = eventRequest.getEvent();
eventResponse.setRenderParameter("eventName", event.getName());
SampleComplexEvent eventValue = (SampleComplexEvent) event.getValue();
eventResponse.setRenderParameter("intItem", Integer.toString(eventValue
.getIntItem()));
eventResponse.setRenderParameter("strItem", eventValue.getStrItem());
eventResponse.setRenderParameter("dateItem", eventValue.getDateItem().toString());
}
}
在 jsp 目錄下新建 jsp 文件 TestComplexEventReceiverPortletView.jsp
清單 25. TestComplexEventReceiverPortletView.jsp 文件
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@taglib prefix="portlet" uri="http://java.sun.com/portlet_2_0"%>
<portlet:defineObjects />
<table>
<tr>
<td><h1>Test complex event receiver portlet page.</h1></td>
</tr>
<tr>
<td><h2>Received complex event:</h2></td>
</tr>
<tr>
<td>Event name:<%=renderRequest.getParameter("eventName")%></td>
</tr>
<tr><td>Event value</td></tr>
<tr>
<td>Integer item:<%=renderRequest.getParameter("intItem")%></td>
</tr>
<tr>
<td>String item:<%=renderRequest.getParameter("strItem")%></td>
</tr>
<tr>
<td>Date item:<%=renderRequest.getParameter("dateItem")%></td>
</tr>
</table>
請讀者自行參照清單 19 和 清單 20 在 portlet.xml 文件中定義兩個portlet TestComplexEventSenderPortlet 和 TestComplexEventReceiverPortlet, 使其分別支持發布和響應事件 complex-event。
在 portlet.xml 文件中添加以下聲明,定義事件名稱和類型,該事件類型為com.ibm.samples.jsr286.events.SampleComplexEvent, 如清單 26 所示:
清單 26.
<event-definition>
<name>complex-event</name>
<value-type>com.ibm.samples.jsr286.events.SampleComplexEvent</value-type>
</event-definition>
參照 TestPortlet 的定義, 為 TestComplexEventSenderPortlet 和 TestComplexEventReceiverPortlet 在 web.xml 裡添加 Pluto 所需的 servlet 定義及映射。
將 TestComplexEventSenderPortlet 和 TestComplexEventSenderPortlet 部署到"Test JSR 286 Portlet Page"頁面,如圖 21 和 圖 22。
圖 21. 復合事件發布 portlet
圖 22. 復合事件響應 portlet
點擊 TestComplexEventSenderPortlet 中的按鈕,TestComplexEventReceiverPortlet 如圖 23 所示:
圖 23. 復合事件響應
表明 TestComplexEventReceiverPortlet 接收到了名為 complex-event 的事件,事件值如圖 23 所示。
4. 共享呈現參數
更改 TestPortletView.jsp 文件,在文件末尾增加表單和輸入框接收輸入參數,如清單 26 所示:
清單 26. 表單和共享呈現參數值輸入框
...
<form action="<portlet:actionURL/>">
<table>
<tr><td>Input public render parameter value:</td></tr>
<tr>
<td><input type="text" name="public-render-param"></td>
</tr>
<tr>
<td><input type="submit" value="Submit"></td>
</tr>
</table>
</form>
更改 TestPortlet 的 processAction 方法,將從輸入框中得到的值傳送到呈現階段的請求參數中,如清單 27 所示:
清單 27. TestPortlet 的 processAction 方法
...
public void processAction(ActionRequest actionRequest,
ActionResponse actionResponse) throws PortletException, IOException {
String publicRenderParamValue = actionRequest.getParameter("public-render-param");
actionResponse.setRenderParameter("public-render-param", publicRenderParamValue);
}
...
新建 portlet 類 TestPublicRenderParameterPortlet, 如清單 28 所示:
清單 28. TestPublicRenderParameterPortlet.java 文件
package com.ibm.samples.jsr286.portlets;
import ...
public class TestPublicRenderParameterPortlet implements Portlet {
private PortletConfig portletConfig;
public void init(PortletConfig portletConfig) throws PortletException {
this.portletConfig = portletConfig;
}
public void destroy() {
}
public void processAction(ActionRequest actionRequest,
ActionResponse actionResponse) throws PortletException, IOException {
}
public void render(RenderRequest renderRequest,
RenderResponse renderResponse) throws PortletException, IOException {
PortletRequestDispatcher portletRequestDispatcher = portletConfig
.getPortletContext()
.getRequestDispatcher(
"/WEB-INF/jsp/TestPublicRenderParameterPortletView.jsp");
portletRequestDispatcher.include(renderRequest, renderResponse);
}
}
TestPublicRenderParameterPortlet 呈現所需的 jsp 頁面 TestPublicRenderParameterPortletView.jsp 如清單 29 所示:
清單 29. TestPublicRenderParameterPortletView.jsp 文件
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@taglib prefix="portlet" uri="http://java.sun.com/portlet_2_0"%>
<portlet:defineObjects />
<table>
<tr><td><h1>Test public render parameter test page.</h1></td></tr>
<tr><td><h2>Received public render parameter value:</h2></td></tr>
<tr>
<td>Parameter value:<%=renderRequest.getParameter("public-render-param")%></td>
</tr>
</table>
編輯 portlet.xml 文件, 在 TestPortlet 定義的尾端加入 清單 30 中 的內容,使得 portlet TestPortlet 支持共享呈現參數 public-render-param。
清單 30.
<portlet>
...
<supported-public-render-parameter>
public-render-param
</supported-public-render-parameter>
</portlet>
在 portlet.xml 中增加 TestPublicRenderParameterPortlet 的定義,並加入清單 30 中的內容。
在 portlet.xml 末尾添加 清單 31 中的內容:
清單 31.
...
<public-render-parameter>
<identifier>public-render-param</identifier>
</public-render-parameter>
</portlet-app>
為 TestPublicRenderParameterPortlet 在 web.xml 裡添加 Pluto 所需的 servlet 定義及映射。
將 TestPortlet 和 TestPublicRenderParameterPortlet 部署到 "Test JSR 286 Portlet Page" 頁面,如圖 24 和 圖 25。
圖 24. 輸入共享呈現參數值
圖 25. 顯示共享呈現參數值的 portlet
在 TestPortlet 中輸入參數值 testvalue, 提交表單,則在 TestPublicRenderParameterPortlet 呈現圖 26 所示結果:
圖 26. 顯示共享呈現參數值
小結
本部分介紹了 JSR 286 Portlet 容器的參考實現 Apache Pluto 2.0 的構建過程,以及使用 Eclipse 和 Apache Pluto 2.0 進行 Portlet 開發的方法流程,並且通過示例代碼介紹了JSR 286 Portlet 資源服務、事件交互和共享呈現參數的實際開發步驟。JSR 286 規 范目前還處於草案階段,而且相應的 Portlet 容器還處於不穩定版本的開發階段,在具體的實驗性開發過程中需要讀者對 Portelt 容器 本身的 Bug 加以注意。