本部分向您介紹有關(guān)創(chuàng)建 portlet 的概念,從一個徹底修改過的簡單的 portlet 開始。使用有關(guān)
Portlet API 的部分和
Javadoc 作為參考。
創(chuàng)建簡單 portlet 實例樣本 portlet設(shè)置 portlet 開發(fā)環(huán)境Hello World portlet編譯 Java 源代碼封裝和部署 portlet生成標(biāo)記使用持久性portlet 消息傳遞消息和跟蹤記錄日志刷新 portlet 高速緩存并行 portlet 呈現(xiàn)個性化 portlet如果您熟悉為 WebSphere Portal Family 產(chǎn)品版本 2.1 開發(fā) portlet,應(yīng)該可以注意到 Portlet API 已作了顯著改進。請參閱
遷移 portlet 以獲取更多信息。
WebSphere Portal 包括可在 wp_root/install 目錄中找到的下列預(yù)定義的 portlet 集合。 portlet 文件名
文件服務(wù)器 portlet,提供靜態(tài) HTML 文件 fileserverportlet.war
Servlet 調(diào)用器 portlet,將 servlet 作為 portlet 調(diào)用 ServletInvoker.war
JSP portlet,服務(wù) JSP jspserverportlet.war
CSV 查看器,顯示數(shù)據(jù)以逗號分隔值的格式排列的文件 csv.war
RSS portlet,顯示提供使用豐富站點摘要格式的數(shù)據(jù)的遠程 URL。 xslt.war
OCS 查看器,顯示“打開內(nèi)容辛迪加”通道供給。 ocsviewer.war
這些 portlet 提供了基本功能(例如提供靜態(tài) HTML 服務(wù)或動態(tài) JSP 文件服務(wù)),這樣不必編寫代碼就可以把這些功能集成到您的門戶網(wǎng)站中。可以通過使用門戶網(wǎng)站管理來創(chuàng)建和部署這些 portlet 任意數(shù)量的實例。請參閱
portlet 管理以獲取更多信息。
文件服務(wù)器 portlet 可以在它到 portlet 窗口的路徑下顯示任何 HTML 文件。缺省情況下,它顯示位于 WAR 文件的 FileServerPortlet/html 目錄中的 test.html。要服務(wù)其它內(nèi)容,可將 HTML 文件添加到文件服務(wù)器 portlet 的路徑下并且在門戶網(wǎng)站管理中使用管理 portlet 修改它的 url 參數(shù)至新建的文件中。url 參數(shù)的根指向 was_root/installedApps/portlet_id.ear/FileServer.war 目錄,其中 portlet_id 是在部署期間創(chuàng)建的唯一標(biāo)識??梢詣?chuàng)建多個 portlet 實例,每個實例從各自的路徑服務(wù)不同的內(nèi)容。
提供了一組樣本 portlet,它們演示了 Portlet API 的功能。這些 portlet 由 wp_root/dev 目錄下的 bookmark_samplets.zip 文件提供。這些樣本 portlet 包含以下文件:
bookmark0.war 演示如何獲取、設(shè)置和除去某一具體 portlet 的變量。然而,這個 portlet 不產(chǎn)生任何輸出。
bookmark1.war 使用 PortletResponse 寫輸出到門戶網(wǎng)站。
bookmark2.war 例如,實現(xiàn)在頁面中 portlet 標(biāo)記之前插入 HTML 輸出的偵聽器。
bookmark3.war 從 PortletConfig 檢索參數(shù)和從 PortletData 與 PortletSettings 檢索屬性。
bookmark4.war 從資源束獲取本地化的文本。
bookmark5.war 包含用于 portlet 的視圖方式的 JSP。
bookmark6.war 包含用于編輯方式和實現(xiàn) ActionListener 的 JSP,以便用戶添加書簽。
下面幾部分描述如何創(chuàng)建一個簡單的 Hello World portlet,以及如何編譯、封裝和部署這個 portlet。沒有為 Hello World 提供文件樣本;您必須使用文本中提供的示例來創(chuàng)建它。然而,在 wp_root/dev 目錄下提供了 HelloWorld2.war,它演示了如何使用 JSP 來提供 portlet 標(biāo)記。
在嘗試本部分所討論的任何類和樣本之前,您應(yīng)該設(shè)置一個讓編寫、編譯和測試 portlet 各任務(wù)更易于實現(xiàn)的環(huán)境。WebSphere Portal 產(chǎn)品軟件包包含下列開發(fā)工具: WebSphere Studio Application Developer 版本 4.0.3
支持電子商務(wù)應(yīng)用程序端到端的開發(fā)、測試和部署。 門戶網(wǎng)站工具箱
門戶網(wǎng)站工具箱插入到 Application Developer 中并為創(chuàng)建 portlet 應(yīng)用程序項目和創(chuàng)建基于 PortletAdapter 和 MVCPortlet 類的 portlet 以及基于模板的 portlet(
ServletInvokerPortlet、
JSPPortlet 和
XSLTPortlet)提供向?qū)А?div style="height:15px;">
確保將您的系統(tǒng) PATH 環(huán)境變量設(shè)置為使用 JDK 1.3.0,這是 WebSphere Application Server 所使用的 JDK。需要使用該 JDK 級別來編譯類文件以便在 portlet 中使用。
除了開發(fā)工作站之外,還應(yīng)設(shè)置門戶網(wǎng)站服務(wù)器以便通過安裝下列組件來發(fā)布和測試您的 portlet 應(yīng)用程序項目:
WebSphere Portal(開發(fā)選項) WebSphere Application Server - 高級版,單服務(wù)器
請參閱
在 WebSphere Application Server 高級單服務(wù)器版上安裝 WebSphere Portal,以獲取進一步的信息。
Hello World portlet 提供編寫您的第一個 portlet 的介紹。Hello World 擴展 AbstractPortlet 幫助器類,并提供一個 portlet 必需的最少方法。它使用
PortletResponse 提供到門戶網(wǎng)站頁面的簡單輸出。
package com.ibm.wps.samples.HelloWorld;import org.apache.jetspeed.portlet.*;import org.apache.jetspeed.portlets.*;import java.io.*;public class HelloWorld extends AbstractPortlet{public void init(PortletConfig portletConfig) throws UnavailableException{super.init( portletConfig );}public void service( PortletRequest portletRequest,PortletResponse portletResponse)throws PortletException, IOException{PrintWriter writer = portletResponse.getWriter();writer.println("<p>Hello Portal World!</p>");}}
使用 WebSphere Application Server 提供的 JDK 編譯 Java 源文件。編譯 Java 源代碼之前,為編譯器設(shè)置 CLASSPATH 以便查找 portlet 使用的任何 portlet 軟件包的 JAR 文件。下列 JAR 文件總是應(yīng)該在 CLASSPATH 中設(shè)置以便編譯:
was_root/lib/app/portlet-api.jar;was_root/lib/app/wpsportlets.jar;was_root/lib/app/wps.jar;
其中 was_root 是 WebSphere Application Server 的安裝目錄。此外,如果需要 servlet 功能的任何類,添加下列:
was_root/lib/j2ee.jar;was_root/lib/websphere.jar;
然后,使用到 Java portlet 源代碼的全限定路徑來編譯 portlet。 javac -classpath %CLASSPATH% com.ibm.wps.samples.HelloWorld.java
要在編譯之后測試 Hello World,必須先把它
封裝成一個 WAR 文件,并把它安裝到門戶網(wǎng)站服務(wù)器。然而,第一步是把 portlet 封裝成 JAR 文件格式。要創(chuàng)建名為 HelloWorld.jar 的 JAR 文件,輸入以下命令: jar -cf HelloWorld.jar HelloWorld.class
請參閱 JDK 文檔,以獲取有關(guān) JAR 命令的更多信息。
要知道門戶網(wǎng)站服務(wù)器類裝入是按照 WebSphere Application Server 的類路徑層次結(jié)構(gòu)和搜索次序進行的。portlet 需要的類必須由 portlet 的類裝入器或它的一個父類裝入器裝入。請參閱
為 portlet 裝入類,以獲取更多信息。
完成開發(fā)和測試 portlet 之后,portlet 便已準(zhǔn)備好以 Web 應(yīng)用程序歸檔或 WAR 文件的形式部署到門戶網(wǎng)站服務(wù)器。您還需要把您的 portlet 封裝成一個 WAR 文件以便在門戶網(wǎng)站服務(wù)器中測試它。
WAR 文件格式包含組成單個 portlet 的 Java 類和資源。資源可以是圖像、JSP 文件或包含翻譯的消息文本的屬性文件。除了 portlet 代碼和資源以外,WAR 文件還包含 Web 應(yīng)用程序部署描述符(web.xml)和 portlet 部署描述符(portlet.xml),該文件包含門戶網(wǎng)站服務(wù)器安裝和配置 portlet 所需的信息。將 portlet 的類、資源和描述性信息封裝到單個文件,使得 portlet 的分發(fā)和部署更容易。
WebSphere Portal 包含一個用于安裝、卸載和更新 portlet 的管理 portlet。在 WAR 文件中包含 portlet 的好處是可以動態(tài)下載和安裝。門戶網(wǎng)站管理員可以從因特網(wǎng)下載 WAR 文件,然后使用門戶網(wǎng)站管理界面把該 portlet 安裝到 WebSphere Portal。該 portlet 已為使用準(zhǔn)備就緒,不需要重新啟動服務(wù)器。
要在 WAR 文件中封裝 portlet,請按照這些步驟操作:
創(chuàng)建部署描述符。 按
WAR 文件目錄結(jié)構(gòu)排列 portlet 文件。 使用 JAR 實用程序來
封裝文件。
以下樣本可與 Hello World portlet 一起封裝。請參閱
部署描述符以獲取有關(guān)這個主題的完整信息。
Web 應(yīng)用程序部署描述符:
<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.2//EN""http://java.sun.com/j2ee/dtds/web-app_2.2.dtd"><web-app id="WebApp_504848313"><display-name>Hello World Portlet Application - Portlet Sample #1</display-name><servlet id="Servlet_439329280"><servlet-name>HelloWorld</servlet-name><servlet-class>com.ibm.wps.samples.HelloWorld</servlet-class></servlet><servlet-mapping id="ServletMapping_439329280"><servlet-name>HelloWorld</servlet-name><url-pattern>/HelloWorld/*</url-pattern></servlet-mapping></web-app>Portlet 部署描述符:
<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE portlet-app-def PUBLIC "-//IBM//DTD Portlet Application 1.1//EN""portlet_1.1.dtd"><portlet-app-def><portlet-app uid="504848313"><portlet-app-name>Hello World Portlet Application - Portlet Sample #1</portlet-app-name><portlet href="WEB-INF/web.xml#Servlet_439329280" id="Portlet_439329280"><portlet-name>HelloWorld</portlet-name><cache><expires>0</expires><shared>no</shared></cache><allows> <minimized/> </allows><supports><markup name="html"><view/></markup></supports></portlet></portlet-app><concrete-portlet-app uid="640682430"><portlet-app-name>Concrete Hello World Portlet Application - Portlet Sample #1</portlet-app-name><context-param><param-name>Portlet Master</param-name><param-value>yourid@yourdomnain.com</param-value></context-param><concrete-portlet href="Portlet_439329280"><portlet-name>HelloWorld</portlet-name><default-locale>en</default-locale><language locale="en_US"><title>Hello World - Sample Portlet #1</title><title-short>Hello-World</title-short><description>Hello World - Sample Portlet #1</description><keywords>portlet hello world</keywords></language></concrete-portlet></concrete-portlet-app></portlet-app-def>
封裝您的 portlet 之前,您必須按照此處描述的目錄結(jié)構(gòu)排列類文件和資源。portlet 應(yīng)用程序作為結(jié)構(gòu)化的目錄層次結(jié)構(gòu)而存在。
/portlet 文件結(jié)構(gòu)的根目錄。 /imagesportlet 必需的任何圖像的位置。/WEB-INF所有受保護資源的位置。/WEB-INF 目錄存儲 portlet 描述符文檔,以及封裝的 portlet 所需的所有運行時可執(zhí)行 JAR 文件和類。
portlet 信息目錄不是應(yīng)用程序公用文檔樹的一部分。駐留在 /WEB-INF 中的文件并不直接服務(wù)客戶機。
/WEB-INF/lib存儲 portlet JAR 文件的位置。/jspJSP 文件的位置。這是建議的路徑名。您的 JSP 可以封裝在 /WEB-INF 目錄外的任何位置。/WEB-INF/classesportlet 類文件的位置。個別的類文件應(yīng)該存儲到 /WEB-INF/classes 下反映類軟件包的目錄結(jié)構(gòu)中。例如,軟件包 com.ibm.wps.samples.HelloWorld 中類 HelloWorld.class 應(yīng)該存儲到 /WEB-INF/classes/com/ibm/wps/samples/HelloWorld.class。/META-INFmanifest 文件 manifest.mf 的位置。manifest 的格式為由 Java 1.3 規(guī)范定義的標(biāo)準(zhǔn) JAR 文件格式。/META-INF 目錄中的內(nèi)容不是服務(wù)于客戶機的。
門戶網(wǎng)站聚集允許您封裝 JSP 以支持多個標(biāo)記、客戶機和語言環(huán)境。那些包含大部分文本的 JSP(例如,幫助 JSP)可以直接翻譯而不是將字符串存儲在資源束中。對于不使用資源束的 JSP,您需要把它存儲到相應(yīng)的本地化位置。當(dāng) portlet 為呈現(xiàn) portlet 的內(nèi)容使用 JSP 時,門戶網(wǎng)站將基于請求中表明的客戶機類型(包含瀏覽器)、標(biāo)記語言和語言環(huán)境搜索和選擇正確的 JSP。要把 JSP 包含進 portlet,使用 PortletContext.include() 函數(shù):
getPortletConfig().getContext().include(jsp_path/jspname.jsp, portletRequest, portletResponse);
要支持多種標(biāo)記類型和語言環(huán)境,必須使用下列目錄結(jié)構(gòu)把 portlet 的 JSP 封裝到 WAR 文件中:
jsp_path/markup_type /language _country/client/jspname.jsp
其中
jsp_path開發(fā)者定義的路徑。例如,JSP 可以定位在 WAR 文件或 jsp 目錄的根中。然而,此路徑不能包含 mime-type/language_country_variant。include() 方法已經(jīng)定位了也在這些目錄中的正確的 JSP。markup_type是 html、wml 或 chtml。language是 JSP 的語言,例如 en、ja 或 de。country是 JSP 的國家或地區(qū),例如 US、UK 或 CA。client是設(shè)備的類型。例如,它可以表明具有瀏覽器特定標(biāo)記的 JSP,如 ie 或 ns4。
管理客戶機幫助描述門戶網(wǎng)站服務(wù)器是如何標(biāo)識客戶機的。
例如,如果客戶機使用的是語言特性設(shè)置為英語(美國)的 Internet Explorer 5,方法 include(/mypath/mytemplate.jsp, portletRequest, portletResponse) 讓門戶網(wǎng)站服務(wù)器按以下次序查找 JSP。 /html/mypath/ie5/en_US/mytemplate.jsp /html/mypath/ie5/en/mytemplate.jsp /html/mypath/ie5/mytemplate.jsp /html/mypath/en_US/mytemplate.jsp /html/mypath/en/mytemplate.jsp /html/mypath/mytemplate.jsp /html/en_US/mytemplate.jsp /html/en/mytemplate.jsp /html/mytemplate.jsp /mytemplate.jsp
任何 JAR 實用程序都可用于構(gòu)建 WAR 文件。下面是如何使用 WebSphere Application Server 提供的 JAR 實用程序的示例。
要創(chuàng)建名稱為 MailPortlet.par 的 WAR 文件并包含 /WEB-INF 和 /images 目錄中的所有文件: jar -cf HelloWorld.war images WEB-INF 要使用修改后的 portlet 描述符更新現(xiàn)有的 WAR 文件 HelloWorld.war: jar -uf HelloWorld.war WEB-INF/portlet.xml 要從 WAR 文件 HelloWorld.war 抽取 portlet 描述符: jar -xf HelloWorld.war WEB-INF/portlet.xml 要從現(xiàn)有的 WAR 文件 HelloWorld.war 抽取所有的文件: jar -xf HelloWorld.war
創(chuàng)建 WAR 文件之后,可按
portlet 管理所述將它安裝到 WebSphere Portal。
為便于 portlet 應(yīng)用程序和復(fù)雜 portlet 的部署,提供了可以由 XML 配置接口調(diào)用的 portlet 配置文件。XML 配置接口允許 portlet 開發(fā)者指定一些位置、頁面、主題、外觀、支持的標(biāo)記和客戶機以及其它 portlet 應(yīng)用程序的設(shè)置。這對于使用消息傳遞的 portlet 特別有用,因為這些 portlet 必須放置在相同的頁面上。要獲取更多有關(guān) XML 配置接口的信息,請參閱
XML 輸入和輸出的整個結(jié)構(gòu)以及
XML 中門戶網(wǎng)站配置的表示法。
在第一個示例中,portlet 通過使用 Java PrintWriter 提供標(biāo)記。多數(shù)標(biāo)記使用 JSP 生成。當(dāng) portlet 必須變換 XML 源時,對此有一個例外。在這種情況下,portlet 可使用 XSLT 生成標(biāo)記。
將 portlet 標(biāo)記從 portlet 的主功能分隔開最簡單的方法之一是使用 JSP。下面是用于 Hello World2 樣本的編輯頁面的 JSP。分隔的視圖或幫助 JSP 將存在以便為支持附加的 portlet 方式提供用戶界面。
當(dāng)編寫您的 JSP 時有幾點注意事項:
為保持門戶網(wǎng)站外觀的一致性,請使用
portlet 的樣式表中的 portlet 類規(guī)范。 確保包含 WebSphere Portal 的 JSP 標(biāo)記庫以獲取管理您的 portlet 的名稱空間所需的功能。此外,使用 <portletAPI:encodeNamespace> 標(biāo)記來設(shè)置請求參數(shù)名稱。請參閱
使用 Portlet API 標(biāo)記以獲取更多信息。 在本示例中,Java String 對象從 portlet 的 doEdit() 方法被傳遞給 JSP。對于更復(fù)雜的數(shù)據(jù)傳遞,可能需要創(chuàng)建單獨的對象(數(shù)據(jù)視圖 bean 或散列表)來包含顯示所需的數(shù)據(jù)。
<%@ taglib uri="/WEB-INF/tld/portlet.tld" prefix="portletAPI" %><portletAPI:init /><jsp:useBean id="saveURI" class="java.lang.String" scope="request" /><jsp:useBean id="cancelURI" class="java.lang.String" scope="request" /><jsp:useBean id="userName" class="java.lang.String" scope="request" /><!-- build table for edit screen --><div CLASS="wpsEditBack"><span class="wpsEditHead">Configure Hello World Portlet</SPAN> <br><form method="post" name="form" action="<%= saveURI %>"><table WIDTH="100%" CELLSPACING="0" CELLPADDING="0" BORDER="0"><tr><td align="right" class="wpsEditText">Enter string to display:</TD><td><input class="wpsEditField" size="20" type="text"name="<%=portletResponse.encodeNamespace("userName")%>"value=<%= userName %>></td></tr><!-- Empty row --><tr><td> </td></tr><tr><td class="wpsButtonText"><input type="submit" name="save" value="Save" ><input type="button" value="Cancel"onClick="window.location.href=‘<%= cancelURI %>‘" ></td></tr></table></form></div>
WebSphere Portal 的主要功能之一是它對多種設(shè)備的支持能力。WebSphere Portal 支持 PC 瀏覽器、i-mode 和 WAP 電話,本產(chǎn)品將來的版本還會支持其它設(shè)備類型。支持多種設(shè)備的挑戰(zhàn)是根據(jù)瀏覽器的特征以不同的方式來呈現(xiàn)內(nèi)容。某個瀏覽器可接受 HTML 4.0;另一個可接受 WML;某個 WAP 電話可顯示四行文字、每行 25 個字符;而另一種電話可能會有自己 PDA 風(fēng)格的界面。
以下示例演示了一種方法,在生成 portlet 的標(biāo)記之前,先選擇與當(dāng)前設(shè)備相關(guān)的標(biāo)記類型。提供了 doMarkupOutput() 方法,調(diào)用這個方法來處理對于每種 portlet 方式的輸出的請求。從 PortletRequest 獲取的 Client 對象標(biāo)識當(dāng)前設(shè)備所需的標(biāo)記語言。
...{public void init (PortletConfig portletConfig) throws UnavailableException{super.init( portletConfig ); // Call super to do further init}public void doView( PortletRequest request, PortletResponse response )throws PortletException, IOException{doMarkupOutput( request, response, "View" );}public void doHelp( PortletRequest request, PortletResponse response )throws PortletException, IOException{doMarkupOutput( request, response, "Help" );}public void doEdit( PortletRequest request, PortletResponse response )throws PortletException, IOException{doMarkupOutput( request, response, "Edit" );}public void doMarkupOutput( PortletRequest request,PortletResponse response,String portletModeString ) throws PortletException, IOException{String markup = request.getClient().getMarkupName();PrintWriter writer = response.getWriter();//-------------------------------------------------------------------------------------// Check the client device to determine the type of markup to generate//-------------------------------------------------------------------------------------if( markup.equalsIgnoreCase("HTML") ) // Standard HTML: text/html{writer.println( "<p>Hello Portal... The Portlet Mode is: "+portletModeString+" </p>" );}else if( markup.equalsIgnoreCase("WML") ) // WML: text/wml{writer.println( "<card id=\"hello\"><P>Hello Portal... " );writer.println( "The Portlet Mode is: "+portletModeString+" </P></card>" );}else if( markup.equalsIgnoreCase("CHTML") ) // Compact HTML: text/html{writer.println( "<P>Hello Portal... The Portlet Mode is: "+portletModeString+" </P>" );}else // Unrecognized Markup Type Error: Throw An Exception{throw( new PortletException( "Unknown Markup Type") );}}}
WebSphere Portal 提供 MVCPortlet 類作為 com.ibm.wps.portlets 軟件包的一部分。發(fā)送輸出前,擴展該類的 portlet 不必檢查客戶機標(biāo)記。相反,它們?yōu)槊總€標(biāo)記類型提供控制器類。Web 應(yīng)用程序描述符中的 servlet 類標(biāo)記定義擴展 MVCPortlet 的空的調(diào)試文件類??刂破黝惐粯?biāo)識為初始化參數(shù),如下例所示。
<servlet-class>com.mycompany.myportlet.myMVCportlet</servlet-class><init-param><param-name>controller.html</param-name><param-value>com.mycompany.myportlet.HTMLController</param-value></init-param><init-param><param-name>controller.wml</param-name><param-value>com.mycompany.myportlet.WMLController</param-value></init-param><init-param><param-name>controller.chtml</param-name><param-value>com.mycompany.myportlet.CHTMLController</param-value></init-param>
控制器類擴展 AbstractPortletController 并包含 portlet 代碼,如 doView()、doEdit() 方法或 ActionListener(若有必要)。應(yīng)用程序開發(fā)者允許您從創(chuàng)建 portlet 項目向?qū)?chuàng)建 MVCPortlet。
使用
PortletData 對象保存、檢索或刪除 portlet 數(shù)據(jù)到持久性 portlet 數(shù)據(jù)。只有當(dāng) portlet 處于編輯方式下時,portlet 才可在 PortletData 對象中存儲值。如果 portlet 在組頁面上,則 PortletData 中保存的信息對所有 portlet 的用戶都是可用的。portlet 通過調(diào)用 PortletRequest 對象的 getData() 方法來檢索對 PortletData 實例的引用。
以下 BookmarkPortlet.java 到 bookmark6.war 的示例中,在用戶在編輯頁面上輸入到書簽的 URL 后,setAttribute() 和 store() 方法把信息保存到 PortletData。然而,首先要從 PortletData 檢索用戶的 URL_COUNT,以便更新 URL_COUNT。
PortletData data = event.getRequest().getData();String count = (String) data.getAttribute(URL_COUNT);int i = 0;if (count != null){i = Integer.parseInt(count);}i++;data.setAttribute(NAME_PREFIX + i, name);data.setAttribute(URL_PREFIX + i, url);data.setAttribute(URL_COUNT , Integer.toString(i));try{data.store();}catch (IOException e){throw new PortletException (e);}
只有 Java String 類型的數(shù)據(jù)才可保存到 PortletData 對象。
注:位于缺省門戶網(wǎng)站頁面的 portlet(在用戶登錄前)不能訪問 PortletData。要防止缺省頁面上出現(xiàn)不希望的錯誤,通知管理員不要在缺省頁面上包含此 portlet,或者在嘗試訪問其屬性之前測試 PortletData 的可用性。
Hello World2 樣本中也使用了 PortletData,使用戶能編輯問候語并將其保存為持久性。此外,PortletContext 用于調(diào)用 JSP 以呈現(xiàn)查看和編輯標(biāo)記。
要顯示的缺省問候語是從
Web 應(yīng)用程序部署描述符獲取的。下面演示了把初始化參數(shù) defaultHelloString 設(shè)置為“Hello!”的描述符。
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.2//EN" "http://java.sun.com/j2ee/dtds/web-app_2.2.dtd"> <web-app id="WebApp_3"> <display-name>HelloPortlet</display-name> <servlet id="Servlet_1"> <servlet-name>Hello World2</servlet-name> <servlet-class>com.ibm.wps.samplets.helloworld.HelloWorld2</servlet-class> <init-param> <param-name>defaultHelloString</param-name> <param-value>Hello!</param-value> </init-param> </servlet> <servlet-mapping id="ServletMapping_1"> <servlet-name>Hello World2</servlet-name> <url-pattern>/Hello World2/*</url-pattern> </servlet-mapping> </web-app>
<init-param> 標(biāo)記設(shè)置的配置數(shù)據(jù)是只讀的,且為每個用戶和每個 portlet 派生出來的具體的 portlet 維護。如果需要允許每個具體的 portlet 有不同的配置,則應(yīng)該在 portlet 部署描述符的 <concrete-portlet> 標(biāo)記中設(shè)置數(shù)據(jù)。
doView() 方法在此 portlet 的標(biāo)準(zhǔn)顯示之前接收控制。訪問 PortletData 對象以獲取要顯示的字符串。如果用戶尚未指定要顯示的字符串,則將使用缺省字符串。該字符串存儲在 PortletRequest 對象中,使它可用于為這個 portlet 生成查看標(biāo)記的 JSP(viewJSP)。 doEdit() 方法在為這個 portlet 顯示編輯頁面之前接收控制。一個返回 URI 被創(chuàng)建并使用 PortletRequest 對象傳遞給編輯方式的 JSP。保存操作包含在返回 URI 中,以便為這個 portlet 調(diào)用 ActionListener。門戶網(wǎng)站在處理保存操作時把控制傳遞給 ActionListener。ActionListener 可以在持久存儲器中保留用戶輸入的“編輯”信息。請參閱
操作事件以獲取有關(guān) ActionListener 和 portlet 操作的更多信息。
HelloActionListener 的代碼顯示為下列 portlet 代碼。
package com.ibm.wps.samplets.helloworld;import org.apache.jetspeed.portlet.DefaultPortletAction;import org.apache.jetspeed.portlet.*;import org.apache.jetspeed.portlet.event.*;import org.apache.jetspeed.portlets.*;import java.io.*;import java.util.*;public class HelloWorld2 extends AbstractPortlet implements ActionListener{// Since there is a single instance of the portlet, only use instance variables// for immutable values that are the same for all users of the portletprivate final static String viewJSP = "/WEB-INF/helloworld/html/HelloWorldView.jsp";private final static String editJSP = "/WEB-INF/helloworld/html/HelloWorldEdit.jsp";private String defaultString;public void init (PortletConfig portletConfig) throws UnavailableException{super.init( portletConfig );if ( getPortletLog().isDebugEnabled() ) {getPortletLog().debug("HelloWorld: init called");}// The default Hello String is obtained from the portlet configuration parametersdefaultString = portletConfig.getInitParameter("defaultHelloString");}public void doView( PortletRequest request, PortletResponse response )throws PortletException, IOException{//Get the user‘s name to display from persistent storagePortletData portletData = request.getData();String stringToDisplay = (String) portletData.getAttribute("userName");// If this is the first time the user has accessed this portlet, then// no display string will be found for this user in persistent storageif (stringToDisplay == null) {stringToDisplay = defaultString; // set default string}// Add the display string to the portlet request to make it accessible by the view JSPrequest.setAttribute("userName", stringToDisplay);// Get a context for the current session for invoking the JSPPortletContext context = getPortletConfig().getContext();context.include(viewJSP, request, response);}public void doEdit(PortletRequest portletRequest, PortletResponse portletResponse )throws PortletException, IOException{// Create the return URI for the edit pagePortletURI returnURI = portletResponse.createReturnURI();// Preserve the Cancel URI in the request to make it accessible by the edit JSPportletRequest.setAttribute("cancelURI", returnURI.toString());// For the "Save" button the return URI must include the "Save" action// so the Action Listener for this portlet will be invokedPortletAction saveAction = new DefaultPortletAction("save");returnURI.addAction(saveAction);// Preserve the Save URI in the request to make it accessible by the edit JSPportletRequest.setAttribute("saveURI", returnURI.toString());//Get the user‘s name to display from persistent storageString stringToDisplay = (String)portletRequest.getData().getAttribute("userName");if (stringToDisplay == null) {stringToDisplay = defaultString; // none found, set default string}// Add the display string to the request to make it accessible by the edit JSP// as an inital value of the input field on the edit formportletRequest.setAttribute("userName", stringToDisplay);// Get a context for the current session for invoking the JSPPortletContext context = getPortletConfig().getContext();context.include(editJSP, portletRequest, portletResponse);}public void actionPerformed(ActionEvent event) {DefaultPortletAction action = (DefaultPortletAction)event.getAction();HelloWorld2 helloPortlet = (HelloWorld2)event.getPortlet();PortletLog log = helloPortlet.getPortletLog();// If this is a save action, then see if the user specified a nameif (action!=null) {if (action.getName().equals("save")) {PortletRequest request = event.getRequest();PortletData portData = request.getData();String userName = request.getParameter("userName");try {// Save the name specified by the userif (userName != null) {portData.setAttribute("userName", userName);portData.store();}} catch (AccessDeniedException ade) {} catch (IOException ioe) {log.error( "<i><b>Couldn‘t write the user date to persistence " );log.error( "because an I/O Error occurred.</b></i>" );}}}}}
如前面所述,Hello World2 portlet 實現(xiàn)了 ActionListener 以處理保存操作。用戶在編輯頁面上輸入名稱,ActionListener 的 actionPerformed() 方法從 PortletRequest 對象獲取特定用戶的字符串,以存儲到用戶的持久存儲器。在返回到 portlet 的 doView() 方法之前,ActionListener 被調(diào)用,這樣如果用戶輸入名稱失敗,則 ActionListener 可強制 portlet 保留在編輯方式,等待來自用戶的輸入。
Portlet API 支持一張頁面上的 portlet 之間的消息傳遞。例如,如果四個 portlet(Left、Right、Top、Bottom)是稱為 Sides 的 portlet 應(yīng)用程序一部分,則 portlet Left 能向 portlet Right、Top 和 Bottom 發(fā)送信息(只要它們在用戶的相同頁面上)。下列條件應(yīng)用于發(fā)送和接收消息的 portlet。
portlet 必須在相同的頁面上??梢允褂?XML 訪問為 portlet 應(yīng)用程序創(chuàng)建 portlet 配置文件,該 portlet 應(yīng)用程序在安裝時間內(nèi)在頁面上配置 portlet。請參閱
門戶網(wǎng)站配置界面以獲取更多信息。 portlet 必須為相同 portlet 應(yīng)用程序的一部分。該條件僅應(yīng)用于實現(xiàn) PortletMessage 接口的 portlet。擴展 DefaultPortletMessage 的 portlet 不必是相同 portlet 應(yīng)用程序的成員。 作為 Web 服務(wù)部署的 portlet 無法發(fā)送和接收消息。
通常,消息是從 portlet 的操作偵聽器發(fā)送的,并由另一個 portlet 的消息偵聽器接收。用戶在一個 portlet 中執(zhí)行操作。捕捉和處理操作事件。根據(jù)該操作結(jié)果,portlet 可使用 PortletContext 對象的 send() 方法把消息發(fā)送到其它 portlet。
...public void actionPerformed (ActionEvent event) {...if (action.getName().equals("browse")) {log.debug("BookmarkActionListener - browse action");String url = (String) action.getParameters().get("url");log.debug("BookmarkPortletActionListener - opening link: " + url);...try {portlet.getConfig().getContext().send(null, new DefaultPortletMessage(url));}catch (AccessDeniedException ade) {log.error("BookmarkPortletActionListener - unable to send message.");log.error("URL = " + url + " - AccessDenied");}}...}
在該樣本中,在書簽 portlet 中已經(jīng)定義“瀏覽”操作。
DefaultPortletAction browseAction = new org.apache.jetspeed.portlets.DefaultPortletAction("browse");browseAction.addParameter("url", url);PortletURI portletURI = response.createReturnURI();portletURI.addAction(browseAction);String actionURI = portletURI.toString();
send() 方法采用下列自變量:
portletName接收該請求的 portlet 的名稱。在上述示例中,將消息發(fā)送到 null,這意味著它在相同的 portlet 應(yīng)用程序中對所有 portlet 廣播。要將消息發(fā)送到特定的 portlet,指定 portlet 的名稱,就象在 portlet 部署描述符中的 <portlet-name> 標(biāo)記所定義的那樣。message要發(fā)送的消息。消息必須是實現(xiàn)那個接口的 PortletMessage 對象或任何子類。在上述示例中,消息在 DefaultPortletMessage 對象中例示,包含從所執(zhí)行操作的 url 字符串。
正在接收的 portlet 有一個消息偵聽器,它使用消息事件的 getMessage() 方法檢索消息。
public void messageReceived (MessageEvent event)throws PortletException{PortletMessage msg = event.getMessage();if (msg instanceof DefaultPortletMessage) {String url = ((DefaultPortletMessage)msg).getText();PortletAdapter portlet = (PortletAdapter)event.getPortlet();portlet.getPortletLog().debug("BookmarkPortletMessageListener messageReceived");PortletRequest request = event.getRequest();PortletSession session = request.getSession();session.setAttribute("url",url);}}}
由于 MessageListener 將已接收的消息設(shè)置為會話屬性,正在接收的 portlet 必須從會話獲取“url”參數(shù)。
要獲取有關(guān)操作事件和消息事件的更多信息,請參閱
Portlet 事件。
Portlet 可以把消息和跟蹤信息寫到日志文件,該文件在 wp_root/log/ 目錄中維護。該日志文件幫助門戶網(wǎng)站管理員審查 portlet 錯誤和特殊情況并幫助 portlet 開發(fā)者測試和調(diào)試 portlet。Portlet API 提供 PortletLog 類,它有把消息和跟蹤信息寫到日志的方法:
debug()把跟蹤信息寫到 wps_[timestamp].log。info()把信息性消息寫到 wps_[timestamp].log。error()把錯誤消息寫到 wps_[timestamp].log。warn()把警告消息寫到 wps_[timestamp].log。
[timestamp] 的格式如下:
year.month.date-hour.minute.second
例如:wps_2002.03.08-14.00.00.log 是 2002 年 3 月 8 日下午 2:00 寫入的。
如果您在一個方法中多次訪問 portlet 日志,建議把日志引用指定到變量,例如:
private PortletLog myLogRef = getPortletLog();
由于日志操作是代價高昂的,PortletLog 提供了確定是否要為給定級別啟用日志記錄的方法。僅在日志正在跟蹤那個級別的消息時,您的 portlet 才寫到給定級別的日志。例如:
if( getPortletLog().isDebugEnabled() ){myLogRef.debug("Warning, Portlet Resources are low!");}
要獲取有關(guān) WebSphere Portal 中日志記錄的更多信息,請參閱
日志管理。
portlet 高速緩存保持 portlet 的完整輸出。結(jié)果,在用戶更改 portlet 狀態(tài)時,門戶網(wǎng)站服務(wù)器不調(diào)用 portlet 的 service() 或 doView() 方法。當(dāng)前 portlet 的高速緩存條目應(yīng)該為無效時,
getLastModified() 方法使 portlet 開發(fā)者能通知容器,因此,應(yīng)該刷新 portlet 的內(nèi)容。您能使用 WindowListeners 設(shè)置新的時間戳記并返回 getLastModified 中的時間戳記。下例顯示高速緩存其輸出的書簽 portlet 的一部分,但如果窗口狀態(tài)更改為提供其它輸出,則需要立即更改其內(nèi)容。
首先,在 portlet 部署描述符中,注冊 WindowListener 和所支持的 portlet 狀態(tài)并啟用高速緩存。
<listener><listener-class type="window">com.mycompany.portlets.bookmark.BookmarkPortletWindowListener</listener-class></listener><cache><expires>-1</expires><shared>NO</shared></cache><allows><maximized/><minimized/></allows>
下一步,WindowListener 為 portlet 會話對 LAST_MODIFIED 屬性設(shè)置時間戳記。
package com.mycompany.portlets.bookmark;import org.apache.jetspeed.portlets.*;import org.apache.jetspeed.portlet.*;Import org.apache.jetspeed.portlet.event.*;Import java.io.IOException; //Java stuffpublic class BookmarkPortletWindowListener extends WindowAdapter {public void windowMaximized (WindowEvent event) throws PortletException{setLastModified(event);}public void windowRestored (WindowEvent event) throws PortletException{setLastModified(event);}private void setLastModified(WindowEvent event) {PortletSession session = event.getRequest().getSession(false);if (session != null) {session.setAttribute(BookmarkPortlet.LAST_MODIFIED, new Long(System.currentTimeMillis()));}}public void windowDetached (WindowEvent event) throws PortletException{}}
最終,當(dāng)發(fā)出請求時,portlet 的 getLastModified() 方法返回時間戳記。
public long getLastModified(PortletRequest request) {PortletSession session = request.getSession(false);if (session != null) {Long lastModified = (Long) session.getAttribute(LAST_MODIFIED);if (lastModified != null) {return lastModified.longValue();}}return -1;}
缺省情況下,門戶網(wǎng)站服務(wù)器并行呈現(xiàn)到 portlet 到頁面(使用分隔處理線程)。管理員可以設(shè)置用于 portlet 呈現(xiàn)的一定數(shù)量的線程或關(guān)閉該能力,使得可以使用單線程串行呈現(xiàn) portlet。這些設(shè)置在 JetspeedResources.properties 文件中進行。請參閱
管理門戶網(wǎng)站下的
并行 portlet 呈現(xiàn)以獲取更多信息。
還在 portlet 級別設(shè)置 portlet 呈現(xiàn),缺省情況下它是關(guān)閉的。要為 portlet 設(shè)置并行 portlet 呈現(xiàn),請在 portlet 部署描述符的 <concrete-portlet> 標(biāo)記中設(shè)置該配置參數(shù)。
<config-param><param-name>parallel</param-name><param-value>true</param-value></config-param>
在 portlet.xml 中設(shè)置該參數(shù)幫助管理員避免部署 portlet 之后才進行設(shè)置。
WebSphere Personalization 使客戶能輕松構(gòu)建 Web 站點,使站點內(nèi)容與站點訪問者相匹配。盡管定制允許用戶設(shè)置他們自己的首選項或確定查看什么內(nèi)容,門戶網(wǎng)站供應(yīng)商(開發(fā)者、管理員)使用個性化來確定基于用戶的特性顯示什么內(nèi)容。
所有個性化解決方案都有用戶概念、內(nèi)容,以及匹配技術(shù)。WebSphere Portal 提供用戶概念,它作為帶用戶概要文件的 User 類實現(xiàn)。對于每個安裝的門戶網(wǎng)站內(nèi)容是特定的,并可以包含客戶數(shù)據(jù)倉庫、舊的數(shù)據(jù)庫、預(yù)訂內(nèi)容供應(yīng)商及其它。對于匹配技術(shù),WebSphere Personzalization 提供一個啟用基于規(guī)則的個性化的資源引擎和規(guī)則引擎。結(jié)合到一起這些組件允許您使用內(nèi)容與用戶相匹配的個性化規(guī)則來開發(fā) portlet。
考慮一個為采購辦公室用品提供 portlet 的內(nèi)部網(wǎng)門戶網(wǎng)站的示例。超過 50 美元的訂單必須由經(jīng)理批準(zhǔn)。僅當(dāng) portlet 用戶是經(jīng)理時,portlet 需要顯示一個啟動批準(zhǔn)表單的按鈕。在這種情況下,可以把按鈕作為內(nèi)容點添加到 portlet 的視圖 JSP。內(nèi)容點就是您要顯示個性化內(nèi)容的 web 頁面的位置。然后創(chuàng)建把該點映射到 portlet 用戶的規(guī)則,例如:
當(dāng)用戶是經(jīng)理時,顯示批準(zhǔn)按鈕
WebSphere Studio Application Developer V4.0.3 用于在 portlet JSP 中創(chuàng)建內(nèi)容點。“個性化工作區(qū)”用于開發(fā)在基于用戶特性的點中顯示內(nèi)容的規(guī)則。WebSphere Portal 包含“樣本個性化 portlet”,它演示了可以如何將個性化規(guī)則包含到 portlet 的 JSP 中,以確定要顯示的標(biāo)記。此樣本是作為個性化的概念引進的。演示的特定類型的規(guī)則是分類器規(guī)則。規(guī)則基于門戶網(wǎng)站用戶概要文件中的“興趣”屬性區(qū)分門戶網(wǎng)站用戶。JSP 調(diào)用個性化來分類當(dāng)前用戶,然后基于結(jié)果生成標(biāo)記以顯示四個可能的圖形中的一個。
下列部分描述如何在樣本 portlet 中包含個性化??梢栽陂T戶網(wǎng)站服務(wù)器的 wp_root/dev/SampPers 目錄中找到 portlet 代碼和資源。
WebSphere Portal 提供下列類,這些類實現(xiàn)必需的接口以使得可以從個性化訪問門戶網(wǎng)站用戶概要文件。 com/ibm/wps/puma/User.class 實現(xiàn) com.ibm.websphere.personalization.resources.Resource 接口 com/ibm/wps/puma/UserManager.class 實現(xiàn) com.ibm.websphere.personalization.resources.ResourceManager2 和 com.ibm.websphere.personalization.resources.ResourceDomain2 接口。
作為實現(xiàn)這些接口的一部分,為保存在用戶概要文件中的用戶的所有屬性提供了適當(dāng)?shù)墨@取方法(getter)和設(shè)置方法(setter)。
User 類實現(xiàn)兩種類型的用戶屬性:固定屬性和動態(tài)屬性。這兩種類型都是持久的(存儲在后端數(shù)據(jù)庫),并且都可以用于個性化。兩種類型的差異主要在于處理添加新屬性中涉及的內(nèi)容。
添加新的固定屬性需要在后端倉庫(如 LDAP 或數(shù)據(jù)庫系統(tǒng))中創(chuàng)建新的結(jié)構(gòu)、提供植入新的屬性值的方法以及具有代表性地(對于個性化最為有效地執(zhí)行)寫一些代碼來擴展或替換 User 類。 相反,可以完成添加新的動態(tài)屬性,而不需要通過調(diào)用門戶網(wǎng)站用戶對象上的 put() 方法重新啟動門戶網(wǎng)站服務(wù)器。
應(yīng)在性能和效率中進行權(quán)衡。使用固定屬性對于運行時有一些好處,而使用動態(tài)屬性對于較簡短的開發(fā)和管理時有些好處。User 類提供固定屬性的一個小的集合,以及添加和使用動態(tài)屬性的能力。
WebSphere Portal 的簽名頁面包含固定的和動態(tài)的屬性。名字、姓氏、電子郵件地址和首選語言是固定屬性;而興趣是動態(tài)屬性。這是此樣本 portlet 訪問的動態(tài)興趣屬性。對于興趣有四種可能的值:音樂、政治、運動和未選擇。此示例使用個性化規(guī)則來確定當(dāng)前門戶網(wǎng)站用戶的分類,這是基于此屬性的設(shè)置,并使用這個分類來確定要顯示四種可能的圖像中的哪一種。 對音樂感興趣的用戶將看到帶有音樂注解的圖像:
對運動感興趣的用戶將看到運動的圖像:
對政治感興趣的用戶將看到與這個世界有關(guān)的圖像:
未選擇任何興趣的用戶將看到計算機圖像:
WebSphere Personalization 的能力要大大超出此樣本中顯示的那些。除了用戶資源之外,個性化還可以訪問內(nèi)容資源。分類器規(guī)則僅是三種類型的個性化規(guī)則中的一種。您還可以創(chuàng)建操作規(guī)則來允許個性化選擇數(shù)據(jù)或內(nèi)容,因而可以在 portlet 外部作出決定;和綁定規(guī)則來組合操作和分類器,以指定在遇到您定義的條件時要執(zhí)行的操作。查詢 WebSphere Personalization 文檔,以獲取進一步的信息。
此樣本是一個了解練習(xí)。樣本 portlet 不提供個性化。下面的步驟描述將個性化包含到 portlet 中必須執(zhí)行的操作。為您提供的說明是為了:
使用“Portlet 應(yīng)用程序向?qū)?#8221;將 portlet war 文件導(dǎo)入 WebSphere Studio Application Developer。 使用應(yīng)用程序開發(fā)者中的“個性化向?qū)?#8221;創(chuàng)建內(nèi)容點。內(nèi)容點是您的 Web 頁面的一部分,在該 Web 頁面中將調(diào)用規(guī)則來個性化內(nèi)容。 添加內(nèi)容點到 portlet 的視圖 JSP。 使用“個性化工作區(qū)”完成下列操作: 為管理個性化資源和規(guī)則創(chuàng)建項目。 創(chuàng)建分類器規(guī)則。 將分類器規(guī)則與 portlet 的 JSP 上的內(nèi)容點關(guān)聯(lián)起來。
要按照此處略述的步驟,您需要安裝下列產(chǎn)品: WebSphere Studio Application Developer 4.0.3。 應(yīng)用程序開發(fā)者的“個性化向?qū)?#8221;。 應(yīng)用程序開發(fā)者的“portlet 應(yīng)用程序向?qū)?#8221;,這可以在門戶網(wǎng)站工具箱中找到。 帶有 Personalization 4.1 的 WebSphere Portal 4.1。
與此樣本相關(guān)的文件可以在 <wp_root>\dev\SampPers\ 目錄中找到。
文件 內(nèi)容
<wp_root>\dev\SampPers\war\SampPersPortlet.war 樣本個性化 portlet(包含源文件)。此處包含的說明用于添加個性化到此 portlet。
<wp_root>\dev\SampPers\resources\User.hrf XML 文件標(biāo)識門戶網(wǎng)站用戶資源。給出了讓此文件可用于 Personalization 的說明。
<wp_root>\dev\SampPers\solution\SampPersPortlet_Solution.war
<wp_root>\dev\SampPers\solution\ClassifyByInterest.clf 如果您對使用此樣本有任何的疑問,那么您會發(fā)現(xiàn)查看 solution 子目錄中的文件會大有幫助。包含了樣本 portlet(經(jīng)修改已包含了個性化)和分類規(guī)則的 XML 文件。
要使用“個性化內(nèi)容點”向?qū)?,您必須?dǎo)入 <wp_root>\dev\SampPers\war\SampPersPortlet.war 文件到 WebSphere Studio Application Developer。
打開應(yīng)用程序開發(fā)者并單擊文件
新建
項目,創(chuàng)建新的項目。 在“新建項目”對話框中選擇 portlet 開發(fā)和 portlet 應(yīng)用程序項目,并單擊下一步。 輸入您的項目名稱,選取標(biāo)題為使用缺省位置的框,并單擊下一步。 為 portlet 選擇選擇無并單擊完成。您將導(dǎo)入一個已存在的 portlet 到應(yīng)用程序開發(fā)者。向?qū)г陧椖款惵窂街凶詣影幾g portlet 需要的必需的 jar 文件。此向?qū)б部梢杂糜趧?chuàng)建新的 portlet。查詢“portlet 應(yīng)用程序向?qū)?#8221;文檔,以獲取有關(guān)創(chuàng)建新的 portlet 的進一步信息。 突出顯示應(yīng)用程序開發(fā)者瀏覽器窗格中的新建項目,并單擊文件
導(dǎo)入。 在“選擇”對話框中選擇 WAR 文件并單擊下一步。 使用瀏覽按鈕定位 <wp_root>\dev\SampPers\war\SampPersPortlet.war 文件。單擊完成。提示您覆蓋 portlet.xml 文件時,單擊全部覆蓋。 驗證在“任務(wù)”視圖中沒有錯誤列出。
注:如果您遇到表明“portlet 的不正確 servlet 引用”和“需要為 portlet 指定 servlet”的錯誤時,那么您需要在“瀏覽器”窗格菜單中選擇項目,右擊以顯示彈出菜單,并單擊運行驗證。
在應(yīng)用程序開發(fā)者的瀏覽器窗格中為您的項目選擇 <project_name>\source\com\ibm\wps\portlets\samppers 目錄。 在菜單欄上單擊內(nèi)容點向?qū)D標(biāo)
。 在“內(nèi)容點向?qū)?#8221;歡迎頁面上單擊下一步。 為內(nèi)容點 Java bean 指定 UserTypeSpot 名稱。 選擇無作為規(guī)則的返回類型。分類器規(guī)則具有“無”的返回類型。如果您正在為返回內(nèi)容創(chuàng)建內(nèi)容點,那么必須將該資源的 .hrf 文件導(dǎo)入到您的 portlet 應(yīng)用程序中,并選擇該資源作為您的內(nèi)容點的返回類型。查詢個性化文檔,以獲取有關(guān)資源創(chuàng)建和從規(guī)則返回資源的進一步信息。單擊下一步。 完成頁面顯示將由您的內(nèi)容點向?qū)?chuàng)建的文件的名稱。文件將在 com.ibm.wps.portlets.samppers 軟件包中創(chuàng)建。單擊完成。
雙擊位于您的應(yīng)用程序開發(fā)者中的 portlet 應(yīng)用程序的 <project_name>\webApplication\JSP\html 目錄中的 SamplePersView.jsp,打開 JSP。這是 portlet 的視圖方式 JSP。確保顯示 JSP 的設(shè)計視圖。如果未顯示,則單擊當(dāng)前視圖下的設(shè)計選項卡。 展開 <project_name>\webApplication\WEB-INF\classes\com\ibm\wps\portlets\samppers 目錄以定位文件 UserTypeSpot.class。要添加內(nèi)容點到 JSP,拖動這個內(nèi)容點類到 JSP 并將它放在設(shè)計視圖窗口的頂部。將打開屬性窗口。 單擊確定關(guān)閉“屬性” 窗口。 打開 JSP 的源視圖。定位為內(nèi)容點創(chuàng)建的 jsp:useBean 標(biāo)記。這會類似于: <jsp:useBean class=com.ibm.wps.portlets.samppers.UserTypeSpot id=userTypeSpot />
在含 jsp:useBean 的語句后輸入下列行:
<% userTypeSpot.setRequest(request); %>
此語句使得 HttpServletRequest 對象可用于個性化規(guī)則處理程序。完成后的內(nèi)容點應(yīng)該如下所顯示:
<jsp:useBean class=com.ibm.wps.portlets.samppers.UserTypeSpot id=userTypeSpot /> <% userTypeSpot.setRequest(request); %> 因為此內(nèi)容點最后將使用分類器規(guī)則(仍將創(chuàng)建),所以您需要添加代碼來確定分類的結(jié)果。用戶有四種可能的分類:音樂、運動、政治或與這些都無關(guān)。基于返回的分類,將顯示匹配分類的圖形。例如,如果將用戶分類到音樂,那么將出現(xiàn)顯示音樂注解的圖形。在 JSP 內(nèi)查找包含下列內(nèi)容的表: <TD><IMG src="<%=response.encodeURL("images/samppers/music.gif")%>" width="96" height="30" border="0"></TD>
<TD><IMG src="<%=response.encodeURL("images/samppers/sports.gif")%>" width="107" height="30" border="0"></TD>
<TD><IMG src="<%=response.encodeURL("images/samppers/politics.gif")%>" width="34" height="35" border="0"></TD>
<TD><IMG src="<%=response.encodeURL("images/samppers/computer.gif")%>" width="34" height="30" border="0"></TD>
僅應(yīng)該顯示這些圖形中的一個,以作為由用戶分類確定的圖形。輸入下面顯示的下列 if-then-else 語句行以在表周圍添加此邏輯。 <% if (userTypeSpot.isClassifiedAs("musical")) {%> <TD><IMG src="<%=response.encodeURL("images/samppers/music.gif")%>" width="96" height="30" border="0"></TD> <% } else { if (userTypeSpot.isClassifiedAs("athletic")) {%> <TD><IMG src="<%=response.encodeURL("images/samppers/sports.gif")%>" width="107" height="30" border="0"></TD> <% } else { if (userTypeSpot.isClassifiedAs("political")) {%> <TD><IMG src="<%=response.encodeURL("images/samppers/politics.gif")%>" width="34" height="35" border="0"></TD> <% } else {%> <TD><IMG src="<%=response.encodeURL("images/samppers/computer.gif")%>" width="34" height="30" border="0"></TD> <% } } } %>
注:在 JSP 中,UserTypeSpot 的 <jsp:usebean> 必須定位在 <table> 中使用它的上方。對于可維護性,您可能需要移動它,以接近文件中的其它 <jsp:usebean> 標(biāo)記。
保存 JSP。 突出顯示瀏覽器窗格中的 portlet 應(yīng)用程序項目,并右擊鼠標(biāo)按鈕以顯示彈出菜單。選擇導(dǎo)出 WAR。 在“WAR 導(dǎo)出”對話框上,單擊瀏覽,定位保存 portlet war 文件的目錄。稍后安裝 portlet 時,您選擇的目錄必須是可訪問的。保存 war 文件為 SampPersPortlet.war 單擊完成生成 war 文件。 現(xiàn)在,您需要導(dǎo)出 UserTypeSpot.class 文件到安裝 Personalization 的服務(wù)器的位置。再次突出顯示瀏覽器窗格中的 portlet 應(yīng)用程序項目,并單擊菜單欄上的文件
導(dǎo)出。 選擇文件系統(tǒng)并單擊下一步。 瀏覽到 <project_name>\webApplication\WEB-INF\classes\com\ibm\wps\portlets\samppers目錄并在選擇框中選擇 UserTypeSpot.class。單擊瀏覽...,以定位可訪問安裝 Personalization 的 WebSphere Application Server 的目錄。在稍后的步驟中,假設(shè)此目錄的名稱是 C:\PZNPortlet;要幫助您遵循這些說明,您可能需要使用這個目錄名稱。選取框創(chuàng)建文件的目錄結(jié)構(gòu)。單擊完成。
以管理員用戶標(biāo)識登錄 WebSphere Portal。 使用 門戶網(wǎng)站管理的 portlet 頁面上的安裝 portlet portlet,安裝 SampPersPortlet.war 文件。 使用門戶網(wǎng)站管理的安全性頁面上的訪問控制管理 portlet 給予所有已認證用戶對“樣本個性化 portlet”的查看訪問權(quán)。 使用使用頁面頁面組中的編輯布局和內(nèi)容任務(wù),添加“樣本個性化 portlet”到所有用戶都可以訪問的頁面。(這將便利于稍后對 portlet 的測試。)
要創(chuàng)建訪問用戶概要文件的分類器規(guī)則,您必須復(fù)制門戶網(wǎng)站用戶 XML 資源文件到安裝 Personalization 的服務(wù)器可訪問的位置。將文件 User.hrf 從 <wp_root>\dev\SampPers\resources 目錄復(fù)制到 C:\PZNPortlet\resources(這是您先前導(dǎo)出 UserTypeSpot.class 的同一根目錄)。
注:與此樣本一起提供的 User.hrf 文件是基于與 WebSphere Portal 一起提供的基本用戶概要文件。它可以照原樣被其它使用個性化的 portlet 使用。如果您添加任何動態(tài)屬性到門戶網(wǎng)站用戶概要文件,則需要創(chuàng)建新的 User.hrf 文件。查詢 Personalization 文檔,以獲取有關(guān)創(chuàng)建此文件的說明。
從瀏覽器,打開“個性化工作區(qū)”(例如:http://your_hostname/wps/PersWorkspace/index.jsp)并用具有開發(fā)者角色的用戶標(biāo)識登錄到工作區(qū)。 單擊全局設(shè)置打開“個性化全局設(shè)置”對話框。 單擊圖標(biāo)添加新的項目。“添加項目”對話框打開。 輸入您項目的路徑和項目名稱。您指定的路徑定位于安裝 WebSphere Application Server 和 Personalization 的機器上。為了方便起見,使用您復(fù)制 User.hrf 和 UserTypeSpot.class 文件的相同目錄,例如,C:\PZNPortlet。單擊確定 資源路徑標(biāo)識包含資源 XML 文件(.hrf 文件)的目錄。輸入 C:\PZNPortlet\resources 作為資源路徑。資源和內(nèi)容點類路徑標(biāo)識已編譯資源和內(nèi)容點的位置。輸入 C:\PZNPortlet\webApplication\WEB-INF\classes 作為路徑。(在這兩種情況下,都用您先前為內(nèi)容點類和用戶資源使用的目錄替換 C:\PZNPortlet)。單擊保存保存項目。 如果項目不是管理項目列表框中的當(dāng)前項目,則選擇該項目并單擊使之成為當(dāng)前按鈕。
下一個任務(wù)是要使用“個性化工作區(qū)”來創(chuàng)建由樣本 portlet 的視圖 JSP 訪問的分類規(guī)則,來基于用戶的屬性確定要顯示的內(nèi)容。
在“個性化工作區(qū)”的規(guī)則撰寫者中,確保在下拉選擇框中選擇了分類器。 單擊圖標(biāo)創(chuàng)建新的分類器規(guī)則。“添加分類器”對話框顯示。 為分類器的名稱輸入 ClassifierByInterest。您還可以可選地添加注釋。 在“分類器描述”區(qū)域中單擊分類打開一個窗口,該窗口允許您輸入分類名稱音樂。在“分類名”彈出窗口中單擊保存。 在“分類器描述”區(qū)域中單擊 Resource.Attribute,打開“選擇資源”和它的“屬性”對話框。單擊當(dāng)前用戶的單選按鈕作為資源。因為您使得 User.hrf 資源文件可用于“個性化工作區(qū)”,所以當(dāng)前用戶選擇出現(xiàn)。在右邊的滾動列表中選擇興趣屬性。讓屬性類型為文本。單擊保存關(guān)閉對話框。 在“分類器描述”區(qū)域中單擊值打開一個可以指定類型文本值的窗口。輸入 music 作為值并單擊保存。 在“分類器描述”區(qū)域中單擊 add Classification 兩次,重復(fù)前 3 個步驟來創(chuàng)建規(guī)則,就象:
分類器描述(單擊加下劃線的值來編輯它)
ClassifierByInterest is
musical when
current User.Interest is equal to music
add condition
athletic when
current User.Interest is equal to sport
add condition
political when
current User.Interest is equal to politics
add condition
add Classification
Otherwise Classification
此樣本不需要 addConditions 也不需要提供 Otherwise classification。
單擊保存保存規(guī)則。
打開“個性化工作區(qū)”的競銷管理器。 單擊正常視圖顯示內(nèi)容點和其關(guān)聯(lián)的規(guī)則。UserTypeSpot 的規(guī)則是空標(biāo)題的鏈接。 單擊空以顯示對話框,在該對話框中您可以選擇規(guī)則來填充內(nèi)容點。 選擇 ClassifyByInterest 并單擊確定。您現(xiàn)在已將內(nèi)容點與規(guī)則關(guān)聯(lián)起來了。
從“個性化工作區(qū)”內(nèi),單擊全局設(shè)置打開“個性化全局設(shè)置”對話框。 單擊管理發(fā)布服務(wù)器顯示發(fā)布服務(wù)器的列表框。 單擊圖標(biāo)以添加發(fā)布服務(wù)器。輸入您安裝 Personalization 的服務(wù)器的名稱,以及到達該服務(wù)器的 URL(例如:http://cayuga.endicott.ibm.com)。如果服務(wù)器需要認證,選擇需要認證復(fù)選框,并輸入用戶標(biāo)識和密碼以訪問服務(wù)器。單擊保存。 單擊發(fā)布文件。 選擇發(fā)布服務(wù)器和全部發(fā)布。單擊發(fā)布。
您需要讓門戶網(wǎng)站用戶資源文件(User.hrf)可用于個性化運行時。此步驟僅需執(zhí)行一次。
從瀏覽器窗口,輸入:
http://servername/PersAdmin_path/ImportServlet?filename=path_to_User.hrf
例如,如果到資源文件的全路徑是 C:\PZNPortlet\resources\User.hrf;對于“個性化管理”的上下文路徑是 /wps/PersAdmin;并且服務(wù)器名是 cayuga.endicott.ibm.com,那么使用下列 url(全部都在一行上)。http://cayuga.endicott.ibm.com/wps/PersAdmin/ImportServlet?filename=C:\PZNPortlet\resources\User.hrf
一旦用戶資源成功發(fā)布,現(xiàn)在它就可為所有 portlet 應(yīng)用程序使用。
創(chuàng)建幾個門戶網(wǎng)站用戶,為每個用戶在簽名頁面上選擇不同的興趣。portlet 顯示的圖形將取決于您選擇的興趣。例如,對于一個愛好音樂的名為 Jimi Hendrix 的用戶,portlet 輸出將顯示如下。
樣本個性化 portlet
歡迎使用“樣本個性化 portlet”
當(dāng)前用戶概要文件設(shè)置:
用戶標(biāo)識:Jimi
名字:Jimi
姓氏:Hendrix
興趣:音樂
左邊的圖形是基于您的標(biāo)號為興趣的用戶概要文件設(shè)置選擇的: