分享

编写 portlet

 bluecrystal 2006-05-25

本部分向您介绍有关创建 portlet 的概念,从一个彻底修改过的简单的 portlet 开始。使用有关 Portlet API 的部分和 Javadoc 作为参考。

如果您熟悉为 WebSphere Portal Family 产品版本 2.1 开发 portlet,应该可以注意到 Portlet API 已作了显著改进。请参阅迁移 portlet 以获取更多信息。

创建简单 portlet 实例

WebSphere Portal 包括可在 wp_root/install 目录中找到的下列预定义的 portlet 集合。

portlet 文件名
文件服务器 portlet,提供静态 HTML 文件 fileserverportlet.war
Servlet 调用器 portlet,将 servlet 作为 portlet 调用 ServletInvoker.war
JSP portlet,服务 JSP jspserverportlet.war
CSV 查看器,显示数据以逗号分隔值的格式排列的文件 csv.war
RSS portlet,显示提供使用丰富站点摘要格式的数据的远程 URL。 xslt.war
OCS 查看器,显示“打开内容辛迪加”通道供给。 ocsviewer.war

这些 portlet 提供了基本功能(例如提供静态 HTML 服务或动态 JSP 文件服务),这样不必编写代码就可以把这些功能集成到您的门户网站中。可以通过使用门户网站管理来创建和部署这些 portlet 任意数量的实例。请参阅 portlet 管理以获取更多信息。

使用文件服务器 portlet 服务于静态内容

文件服务器 portlet 可以在它到 portlet 窗口的路径下显示任何 HTML 文件。缺省情况下,它显示位于 WAR 文件的 FileServerPortlet/html 目录中的 test.html。要服务其它内容,可将 HTML 文件添加到文件服务器 portlet 的路径下并且在门户网站管理中使用管理 portlet 修改它的 url 参数至新建的文件中。url 参数的根指向 was_root/installedApps/portlet_id.ear/FileServer.war 目录,其中 portlet_id 是在部署期间创建的唯一标识。可以创建多个 portlet 实例,每个实例从各自的路径服务不同的内容。

样本 portlet

提供了一组样本 portlet,它们演示了 Portlet API 的功能。这些 portlet 由 wp_root/dev 目录下的 bookmark_samplets.zip 文件提供。这些样本 portlet 包含以下文件:

bookmark0.war 演示如何获取、设置和除去某一具体 portlet 的变量。然而,这个 portlet 不产生任何输出。
bookmark1.war 使用 PortletResponse 写输出到门户网站。
bookmark2.war 例如,实现在页面中 portlet 标记之前插入 HTML 输出的侦听器。
bookmark3.war 从 PortletConfig 检索参数和从 PortletData 与 PortletSettings 检索属性。
bookmark4.war 从资源束获取本地化的文本。
bookmark5.war 包含用于 portlet 的视图方式的 JSP。
bookmark6.war 包含用于编辑方式和实现 ActionListener 的 JSP,以便用户添加书签。

下面几部分描述如何创建一个简单的 Hello World portlet,以及如何编译、封装和部署这个 portlet。没有为 Hello World 提供文件样本;您必须使用文本中提供的示例来创建它。然而,在 wp_root/dev 目录下提供了 HelloWorld2.war,它演示了如何使用 JSP 来提供 portlet 标记。

设置 portlet 开发环境

在尝试本部分所讨论的任何类和样本之前,您应该设置一个让编写、编译和测试 portlet 各任务更易于实现的环境。WebSphere Portal 产品软件包包含下列开发工具:

  • WebSphere Studio Application Developer 版本 4.0.3
    支持电子商务应用程序端到端的开发、测试和部署。
  • 门户网站工具箱
    门户网站工具箱插入到 Application Developer 中并为创建 portlet 应用程序项目和创建基于 PortletAdapter 和 MVCPortlet 类的 portlet 以及基于模板的 portlet(ServletInvokerPortletJSPPortlet XSLTPortlet)提供向导。

    确保将您的系统 PATH 环境变量设置为使用 JDK 1.3.0,这是 WebSphere Application Server 所使用的 JDK。需要使用该 JDK 级别来编译类文件以便在 portlet 中使用。

除了开发工作站之外,还应设置门户网站服务器以便通过安装下列组件来发布和测试您的 portlet 应用程序项目:

  • WebSphere Portal(开发选项)
  • WebSphere Application Server - 高级版,单服务器

请参阅在 WebSphere Application Server 高级单服务器版上安装 WebSphere Portal,以获取进一步的信息。

Hello World portlet

Hello World portlet 提供编写您的第一个 portlet 的介绍。Hello World 扩展 AbstractPortlet 帮助器类,并提供一个 portlet 必需的最少方法。它使用 PortletResponse 提供到门户网站页面的简单输出。

示例:Hello World portlet


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>");
}
}

编译 Java 源代码

使用 WebSphere Application Server 提供的 JDK 编译 Java 源文件。编译 Java 源代码之前,为编译器设置 CLASSPATH 以便查找 portlet 使用的任何 portlet 软件包的 JAR 文件。下列 JAR 文件总是应该在 CLASSPATH 中设置以便编译:

   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 文件,并把它安装到门户网站服务器。然而,第一步是把 portlet 封装成 JAR 文件格式。要创建名为 HelloWorld.jar 的 JAR 文件,输入以下命令:

   jar -cf HelloWorld.jar HelloWorld.class

请参阅 JDK 文档,以获取有关 JAR 命令的更多信息。

要知道门户网站服务器类装入是按照 WebSphere Application Server 的类路径层次结构和搜索次序进行的。portlet 需要的类必须由 portlet 的类装入器或它的一个父类装入器装入。请参阅为 portlet 装入类,以获取更多信息。

封装和部署 portlet

完成开发和测试 portlet 之后,portlet 便已准备好以 Web 应用程序归档WAR 文件的形式部署到门户网站服务器。您还需要把您的 portlet 封装成一个 WAR 文件以便在门户网站服务器中测试它。

WAR 文件格式包含组成单个 portlet 的 Java 类和资源。资源可以是图像、JSP 文件或包含翻译的消息文本的属性文件。除了 portlet 代码和资源以外,WAR 文件还包含 Web 应用程序部署描述符(web.xml)和 portlet 部署描述符(portlet.xml),该文件包含门户网站服务器安装和配置 portlet 所需的信息。将 portlet 的类、资源和描述性信息封装到单个文件,使得 portlet 的分发和部署更容易。

WebSphere Portal 包含一个用于安装、卸载和更新 portlet 的管理 portlet。在 WAR 文件中包含 portlet 的好处是可以动态下载和安装。门户网站管理员可以从因特网下载 WAR 文件,然后使用门户网站管理界面把该 portlet 安装到 WebSphere Portal。该 portlet 已为使用准备就绪,不需要重新启动服务器。

要在 WAR 文件中封装 portlet,请按照这些步骤操作:

  1. 创建部署描述符
  2. WAR 文件目录结构排列 portlet 文件。
  3. 使用 JAR 实用程序来封装文件

Hello World 的部署描述符

以下样本可与 Hello World portlet 一起封装。请参阅部署描述符以获取有关这个主题的完整信息。

Web 应用程序部署描述符:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.2//EN"
"http://java./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>

WAR 文件目录结构

封装您的 portlet 之前,您必须按照此处描述的目录结构排列类文件和资源。portlet 应用程序作为结构化的目录层次结构而存在。

/
portlet 文件结构的根目录。
/images
portlet 必需的任何图像的位置。
/WEB-INF
所有受保护资源的位置。/WEB-INF 目录存储 portlet 描述符文档,以及封装的 portlet 所需的所有运行时可执行 JAR 文件和类。

portlet 信息目录不是应用程序公用文档树的一部分。驻留在 /WEB-INF 中的文件并不直接服务客户机。

/WEB-INF/lib
存储 portlet JAR 文件的位置。
/jsp
JSP 文件的位置。这是建议的路径名。您的 JSP 可以封装在 /WEB-INF 目录外的任何位置。
/WEB-INF/classes
portlet 类文件的位置。个别的类文件应该存储到 /WEB-INF/classes 下反映类软件包的目录结构中。例如,软件包 com.ibm.wps.samples.HelloWorld 中类 HelloWorld.class 应该存储到 /WEB-INF/classes/com/ibm/wps/samples/HelloWorld.class
/META-INF
manifest 文件 manifest.mf 的位置。manifest 的格式为由 Java 1.3 规范定义的标准 JAR 文件格式。/META-INF 目录中的内容不是服务于客户机的。
支持多个标记和语言环境

门户网站聚集允许您封装 JSP 以支持多个标记、客户机和语言环境。那些包含大部分文本的 JSP(例如,帮助 JSP)可以直接翻译而不是将字符串存储在资源束中。对于不使用资源束的 JSP,您需要把它存储到相应的本地化位置。当 portlet 为呈现 portlet 的内容使用 JSP 时,门户网站将基于请求中表明的客户机类型(包含浏览器)、标记语言和语言环境搜索和选择正确的 JSP。要把 JSP 包含进 portlet,使用 PortletContext.include() 函数:

   getPortletConfig().getContext().include(jsp_path/jspname.jsp, portletRequest, portletResponse);

要支持多种标记类型和语言环境,必须使用下列目录结构把 portlet 的 JSP 封装到 WAR 文件中:

jsp_path/markup_type /language _country/client/jspname.jsp

其中

jsp_path
开发者定义的路径。例如,JSP 可以定位在 WAR 文件或 jsp 目录的根中。然而,此路径不能包含 mime-type/language_country_variant。include() 方法已经定位了也在这些目录中的正确的 JSP。
markup_type
htmlwmlchtml
language
是 JSP 的语言,例如 enjade
country
是 JSP 的国家或地区,例如 US、UK 或 CA。
client
是设备的类型。例如,它可以表明具有浏览器特定标记的 JSP,如 iens4管理客户机帮助描述门户网站服务器是如何标识客户机的。

例如,如果客户机使用的是语言特性设置为英语(美国)的 Internet Explorer 5,方法 include(/mypath/mytemplate.jsp, portletRequest, portletResponse) 让门户网站服务器按以下次序查找 JSP。

  1. /html/mypath/ie5/en_US/mytemplate.jsp
  2. /html/mypath/ie5/en/mytemplate.jsp
  3. /html/mypath/ie5/mytemplate.jsp
  4. /html/mypath/en_US/mytemplate.jsp
  5. /html/mypath/en/mytemplate.jsp
  6. /html/mypath/mytemplate.jsp
  7. /html/en_US/mytemplate.jsp
  8. /html/en/mytemplate.jsp
  9. /html/mytemplate.jsp
  10. /mytemplate.jsp

把 portlet 和资源封装进 WAR 文件

任何 JAR 实用程序都可用于构建 WAR 文件。下面是如何使用 WebSphere Application Server 提供的 JAR 实用程序的示例。


  • 要创建名称为 MailPortlet.par 的 WAR 文件并包含 /WEB-INF/images 目录中的所有文件:
       jar -cf HelloWorld.war images WEB-INF
        
  • 要使用修改后的 portlet 描述符更新现有的 WAR 文件 HelloWorld.war
       jar -uf HelloWorld.war WEB-INF/portlet.xml
        
  • 要从 WAR 文件 HelloWorld.war 抽取 portlet 描述符:
       jar -xf HelloWorld.war WEB-INF/portlet.xml
        
  • 要从现有的 WAR 文件 HelloWorld.war 抽取所有的文件:
       jar -xf HelloWorld.war
        

创建 WAR 文件之后,可按 portlet 管理所述将它安装到 WebSphere Portal。

为便于 portlet 应用程序和复杂 portlet 的部署,提供了可以由 XML 配置接口调用的 portlet 配置文件。XML 配置接口允许 portlet 开发者指定一些位置、页面、主题、外观、支持的标记和客户机以及其它 portlet 应用程序的设置。这对于使用消息传递的 portlet 特别有用,因为这些 portlet 必须放置在相同的页面上。要获取更多有关 XML 配置接口的信息,请参阅 XML 输入和输出的整个结构以及 XML 中门户网站配置的表示法

生成标记

在第一个示例中,portlet 通过使用 Java PrintWriter 提供标记。多数标记使用 JSP 生成。当 portlet 必须变换 XML 源时,对此有一个例外。在这种情况下,portlet 可使用 XSLT 生成标记。

使用 JSP 生成标记

将 portlet 标记从 portlet 的主功能分隔开最简单的方法之一是使用 JSP。下面是用于 Hello World2 样本的编辑页面的 JSP。分隔的视图或帮助 JSP 将存在以便为支持附加的 portlet 方式提供用户界面。

当编写您的 JSP 时有几点注意事项:

  1. 为保持门户网站外观的一致性,请使用 portlet 的样式表中的 portlet 类规范。
  2. 确保包含 WebSphere Portal 的 JSP 标记库以获取管理您的 portlet 的名称空间所需的功能。此外,使用 <portletAPI:encodeNamespace> 标记来设置请求参数名称。请参阅使用 Portlet API 标记以获取更多信息。
  3. 在本示例中,Java String 对象从 portlet 的 doEdit() 方法被传递给 JSP。对于更复杂的数据传递,可能需要创建单独的对象(数据视图 bean 或散列表)来包含显示所需的数据。

示例:用于 Hello World2 的编辑方式的 JSP


<%@ 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 的主要功能之一是它对多种设备的支持能力。WebSphere Portal 支持 PC 浏览器、i-mode 和 WAP 电话,本产品将来的版本还会支持其它设备类型。支持多种设备的挑战是根据浏览器的特征以不同的方式来呈现内容。某个浏览器可接受 HTML 4.0;另一个可接受 WML;某个 WAP 电话可显示四行文字、每行 25 个字符;而另一种电话可能会有自己 PDA 风格的界面。

以下示例演示了一种方法,在生成 portlet 的标记之前,先选择与当前设备相关的标记类型。提供了 doMarkupOutput() 方法,调用这个方法来处理对于每种 portlet 方式的输出的请求。从 PortletRequest 获取的 Client 对象标识当前设备所需的标记语言。

示例:添加方法以处理不同的标记


...
{
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") );
}
}
}

使用 MVCPortlet 类

WebSphere Portal 提供 MVCPortlet 类作为 com.ibm.wps.portlets 软件包的一部分。发送输出前,扩展该类的 portlet 不必检查客户机标记。相反,它们为每个标记类型提供控制器类。Web 应用程序描述符中的 servlet 类标记定义扩展 MVCPortlet 的空的调试文件类。控制器类被标识为初始化参数,如下例所示。

  <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(若有必要)。应用程序开发者允许您从创建 portlet 项目向导创建 MVCPortlet。

使用持久性

使用 PortletData 对象保存、检索或删除 portlet 数据到持久性 portlet 数据。只有当 portlet 处于编辑方式下时,portlet 才可在 PortletData 对象中存储值。如果 portlet 在组页面上,则 PortletData 中保存的信息对所有 portlet 的用户都是可用的。portlet 通过调用 PortletRequest 对象的 getData() 方法来检索对 PortletData 实例的引用。

以下 BookmarkPortlet.javabookmark6.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 类型的数据才可保存到 PortletData 对象。

注:位于缺省门户网站页面的 portlet(在用户登录前)不能访问 PortletData。要防止缺省页面上出现不希望的错误,通知管理员不要在缺省页面上包含此 portlet,或者在尝试访问其属性之前测试 PortletData 的可用性。

Hello World2 样本中也使用了 PortletData,使用户能编辑问候语并将其保存为持久性。此外,PortletContext 用于调用 JSP 以呈现查看和编辑标记。

  1. 要显示的缺省问候语是从 Web 应用程序部署描述符获取的。下面演示了把初始化参数 defaultHelloString 设置为“Hello!”的描述符。

     

    示例:Hello World2 的 Web 应用程序描述符


    <?xml version="1.0" encoding="UTF-8"?>
        <!DOCTYPE web-app
        PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.2//EN"
        "http://java./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> 标记设置的配置数据是只读的,且为每个用户和每个 portlet 派生出来的具体的 portlet 维护。如果需要允许每个具体的 portlet 有不同的配置,则应该在 portlet 部署描述符的 <concrete-portlet> 标记中设置数据。

  2. doView() 方法在此 portlet 的标准显示之前接收控制。访问 PortletData 对象以获取要显示的字符串。如果用户尚未指定要显示的字符串,则将使用缺省字符串。该字符串存储在 PortletRequest 对象中,使它可用于为这个 portlet 生成查看标记的 JSP(viewJSP)。
  3. doEdit() 方法在为这个 portlet 显示编辑页面之前接收控制。一个返回 URI 被创建并使用 PortletRequest 对象传递给编辑方式的 JSP。保存操作包含在返回 URI 中,以便为这个 portlet 调用 ActionListener。门户网站在处理保存操作时把控制传递给 ActionListenerActionListener 可以在持久存储器中保留用户输入的“编辑”信息。请参阅操作事件以获取有关 ActionListener 和 portlet 操作的更多信息。

    HelloActionListener 的代码显示为下列 portlet 代码。

示例:从 PortletConfig 保存和检索数据


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 portlet
private 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 parameters
defaultString = portletConfig.getInitParameter("defaultHelloString");
}
public void doView( PortletRequest request, PortletResponse response )
throws PortletException, IOException
{
//Get the user‘s name to display from persistent storage
PortletData 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 storage
if (stringToDisplay == null) {
stringToDisplay = defaultString;    // set default string
}
// Add the display string to the portlet request to make it accessible by the view JSP
request.setAttribute("userName", stringToDisplay);
// Get a context for the current session for invoking the JSP
PortletContext 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 page
PortletURI returnURI = portletResponse.createReturnURI();
// Preserve the Cancel URI in the request to make it accessible by the edit JSP
portletRequest.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 invoked
PortletAction saveAction = new DefaultPortletAction("save");
returnURI.addAction(saveAction);
// Preserve the Save URI in the request to make it accessible by the edit JSP
portletRequest.setAttribute("saveURI", returnURI.toString());
//Get the user‘s name to display from persistent storage
String 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 form
portletRequest.setAttribute("userName", stringToDisplay);
// Get a context for the current session for invoking the JSP
PortletContext 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 name
if (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 user
if (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 实现了 ActionListener 以处理保存操作。用户在编辑页面上输入名称,ActionListener 的 actionPerformed() 方法从 PortletRequest 对象获取特定用户的字符串,以存储到用户的持久存储器。在返回到 portlet 的 doView() 方法之前,ActionListener 被调用,这样如果用户输入名称失败,则 ActionListener 可强制 portlet 保留在编辑方式,等待来自用户的输入。

portlet 消息传递

Portlet API 支持一张页面上的 portlet 之间的消息传递。例如,如果四个 portlet(Left、Right、Top、Bottom)是称为 Sides 的 portlet 应用程序一部分,则 portlet Left 能向 portlet Right、Top 和 Bottom 发送信息(只要它们在用户的相同页面上)。下列条件应用于发送和接收消息的 portlet。

  • portlet 必须在相同的页面上。可以使用 XML 访问为 portlet 应用程序创建 portlet 配置文件,该 portlet 应用程序在安装时间内在页面上配置 portlet。请参阅门户网站配置界面以获取更多信息。
  • portlet 必须为相同 portlet 应用程序的一部分。该条件仅应用于实现 PortletMessage 接口的 portlet。扩展 DefaultPortletMessage 的 portlet 不必是相同 portlet 应用程序的成员。
  • 作为 Web 服务部署的 portlet 无法发送和接收消息。

通常,消息是从 portlet 的操作侦听器发送的,并由另一个 portlet 的消息侦听器接收。用户在一个 portlet 中执行操作。捕捉和处理操作事件。根据该操作结果,portlet 可使用 PortletContext 对象的 send() 方法把消息发送到其它 portlet。

示例:发送消息的 ActionListener


...
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 中已经定义“浏览”操作。

   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 的名称。在上述示例中,将消息发送到 null,这意味着它在相同的 portlet 应用程序中对所有 portlet 广播。要将消息发送到特定的 portlet,指定 portlet 的名称,就象在 portlet 部署描述符中的 <portlet-name> 标记所定义的那样。
message
要发送的消息。消息必须是实现那个接口的 PortletMessage 对象或任何子类。在上述示例中,消息在 DefaultPortletMessage 对象中例示,包含从所执行操作的 url 字符串。

正在接收的 portlet 有一个消息侦听器,它使用消息事件的 getMessage() 方法检索消息。

示例:接收消息的 MessageListener


    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 将已接收的消息设置为会话属性,正在接收的 portlet 必须从会话获取“url”参数。

要获取有关操作事件和消息事件的更多信息,请参阅 Portlet 事件

消息和跟踪记录日志

Portlet 可以把消息和跟踪信息写到日志文件,该文件在 wp_root/log/ 目录中维护。该日志文件帮助门户网站管理员审查 portlet 错误和特殊情况并帮助 portlet 开发者测试和调试 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!");
}

要获取有关 WebSphere Portal 中日志记录的更多信息,请参阅日志管理

刷新 portlet 高速缓存

portlet 高速缓存保持 portlet 的完整输出。结果,在用户更改 portlet 状态时,门户网站服务器不调用 portlet 的 service() 或 doView() 方法。当前 portlet 的高速缓存条目应该为无效时,getLastModified() 方法使 portlet 开发者能通知容器,因此,应该刷新 portlet 的内容。您能使用 WindowListeners 设置新的时间戳记并返回 getLastModified 中的时间戳记。下例显示高速缓存其输出的书签 portlet 的一部分,但如果窗口状态更改为提供其它输出,则需要立即更改其内容。

首先,在 portlet 部署描述符中,注册 WindowListener 和所支持的 portlet 状态并启用高速缓存。

getLastModified() 示例:Portlet 部署描述符


  <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 属性设置时间戳记。

getLastModified() 示例:WindowListener


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 stuff
public 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
{
}
}

最终,当发出请求时,portlet 的 getLastModified() 方法返回时间戳记。

getLastModified() 示例:BookmarkPortlet


    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;
}

并行 portlet 呈现

缺省情况下,门户网站服务器并行呈现到 portlet 到页面(使用分隔处理线程)。管理员可以设置用于 portlet 呈现的一定数量的线程或关闭该能力,使得可以使用单线程串行呈现 portlet。这些设置在 JetspeedResources.properties 文件中进行。请参阅管理门户网站下的并行 portlet 呈现以获取更多信息。

还在 portlet 级别设置 portlet 呈现,缺省情况下它是关闭的。要为 portlet 设置并行 portlet 呈现,请在 portlet 部署描述符的 <concrete-portlet> 标记中设置该配置参数。

      <config-param>
<param-name>parallel</param-name>
<param-value>true</param-value>
</config-param>

portlet.xml 中设置该参数帮助管理员避免部署 portlet 之后才进行设置。

个性化 portlet

WebSphere Personalization 使客户能轻松构建 Web 站点,使站点内容与站点访问者相匹配。尽管定制允许用户设置他们自己的首选项或确定查看什么内容,门户网站供应商(开发者、管理员)使用个性化来确定基于用户的特性显示什么内容。

所有个性化解决方案都有用户概念、内容,以及匹配技术。WebSphere Portal 提供用户概念,它作为带用户概要文件的 User 类实现。对于每个安装的门户网站内容是特定的,并可以包含客户数据仓库、旧的数据库、预订内容供应商及其它。对于匹配技术,WebSphere Personzalization 提供一个启用基于规则的个性化的资源引擎和规则引擎。结合到一起这些组件允许您使用内容与用户相匹配的个性化规则来开发 portlet。

考虑一个为采购办公室用品提供 portlet 的内部网门户网站的示例。超过 50 美元的订单必须由经理批准。仅当 portlet 用户是经理时,portlet 需要显示一个启动批准表单的按钮。在这种情况下,可以把按钮作为内容点添加到 portlet 的视图 JSP。内容点就是您要显示个性化内容的 web 页面的位置。然后创建把该点映射到 portlet 用户的规则,例如:

当用户是经理时,显示批准按钮

WebSphere Studio Application Developer V4.0.3 用于在 portlet JSP 中创建内容点。“个性化工作区”用于开发在基于用户特性的点中显示内容的规则。WebSphere Portal 包含“样本个性化 portlet”,它演示了可以如何将个性化规则包含到 portlet 的 JSP 中,以确定要显示的标记。此样本是作为个性化的概念引进的。演示的特定类型的规则是分类器规则。规则基于门户网站用户概要文件中的“兴趣”属性区分门户网站用户。JSP 调用个性化来分类当前用户,然后基于结果生成标记以显示四个可能的图形中的一个。

下列部分描述如何在样本 portlet 中包含个性化。可以在门户网站服务器的 wp_root/dev/SampPers 目录中找到 portlet 代码和资源。

WebSphere Portal 用户类

 

WebSphere Portal 提供下列类,这些类实现必需的接口以使得可以从个性化访问门户网站用户概要文件。
  • com/ibm/wps/puma/User.class 实现 com.ibm.websphere.personalization.resources.Resource 接口
  • com/ibm/wps/puma/UserManager.class 实现 com.ibm.websphere.personalization.resources.ResourceManager2com.ibm.websphere.personalization.resources.ResourceDomain2 接口。
作为实现这些接口的一部分,为保存在用户概要文件中的用户的所有属性提供了适当的获取方法(getter)和设置方法(setter)。

 

User 类实现两种类型的用户属性:固定属性和动态属性。这两种类型都是持久的(存储在后端数据库),并且都可以用于个性化。两种类型的差异主要在于处理添加新属性中涉及的内容。

  • 添加新的固定属性需要在后端仓库(如 LDAP 或数据库系统)中创建新的结构、提供植入新的属性值的方法以及具有代表性地(对于个性化最为有效地执行)写一些代码来扩展或替换 User 类。
  • 相反,可以完成添加新的动态属性,而不需要通过调用门户网站用户对象上的 put() 方法重新启动门户网站服务器。

应在性能和效率中进行权衡。使用固定属性对于运行时有一些好处,而使用动态属性对于较简短的开发和管理时有些好处。User 类提供固定属性的一个小的集合,以及添加和使用动态属性的能力。

样本的目标

WebSphere Portal 的签名页面包含固定的和动态的属性。名字、姓氏、电子邮件地址和首选语言是固定属性;而兴趣是动态属性。这是此样本 portlet 访问的动态兴趣属性。对于兴趣有四种可能的值:音乐、政治、运动和未选择。此示例使用个性化规则来确定当前门户网站用户的分类,这是基于此属性的设置,并使用这个分类来确定要显示四种可能的图像中的哪一种。

  • 对音乐感兴趣的用户将看到带有音乐注解的图像:音乐图像
  • 对运动感兴趣的用户将看到运动的图像:运动图像
  • 对政治感兴趣的用户将看到与这个世界有关的图像:政治图像
  • 未选择任何兴趣的用户将看到计算机图像:计算机图像

 

WebSphere Personalization 的能力要大大超出此样本中显示的那些。除了用户资源之外,个性化还可以访问内容资源。分类器规则仅是三种类型的个性化规则中的一种。您还可以创建操作规则来允许个性化选择数据或内容,因而可以在 portlet 外部作出决定;和绑定规则来组合操作和分类器,以指定在遇到您定义的条件时要执行的操作。查询 WebSphere Personalization 文档,以获取进一步的信息。

此样本是一个了解练习。样本 portlet 提供个性化。下面的步骤描述将个性化包含到 portlet 中必须执行的操作。为您提供的说明是为了:

  1. 使用“Portlet 应用程序向导”将 portlet war 文件导入 WebSphere Studio Application Developer。
  2. 使用应用程序开发者中的“个性化向导”创建内容点。内容点是您的 Web 页面的一部分,在该 Web 页面中将调用规则来个性化内容。
  3. 添加内容点到 portlet 的视图 JSP。
  4. 使用“个性化工作区”完成下列操作:
    • 为管理个性化资源和规则创建项目。
    • 创建分类器规则。
    • 将分类器规则与 portlet 的 JSP 上的内容点关联起来。

必备软件

要按照此处略述的步骤,您需要安装下列产品:

  • WebSphere Studio Application Developer 4.0.3。
  • 应用程序开发者的“个性化向导”。
  • 应用程序开发者的“portlet 应用程序向导”,这可以在门户网站工具箱中找到。
  • 带有 Personalization 4.1 的 WebSphere Portal 4.1。

样本包含的文件

与此样本相关的文件可以在 <wp_root>\dev\SampPers\ 目录中找到。

文件 内容
<wp_root>\dev\SampPers\war\SampPersPortlet.war 样本个性化 portlet(包含源文件)。此处包含的说明用于添加个性化到此 portlet。
<wp_root>\dev\SampPers\resources\User.hrf XML 文件标识门户网站用户资源。给出了让此文件可用于 Personalization 的说明。
<wp_root>\dev\SampPers\solution\SampPersPortlet_Solution.war
<wp_root>\dev\SampPers\solution\ClassifyByInterest.clf
如果您对使用此样本有任何的疑问,那么您会发现查看 solution 子目录中的文件会大有帮助。包含了样本 portlet(经修改已包含了个性化)和分类规则的 XML 文件。

导入 SampPersPortlet.war 文件

要使用“个性化内容点”向导,您必须导入 <wp_root>\dev\SampPers\war\SampPersPortlet.war 文件到 WebSphere Studio Application Developer。

  1. 打开应用程序开发者并单击文件然后单击新建然后单击项目,创建新的项目。
  2. 在“新建项目”对话框中选择 portlet 开发portlet 应用程序项目,并单击下一步
  3. 输入您的项目名称,选取标题为使用缺省位置的框,并单击下一步
  4. 为 portlet 选择选择并单击完成。您将导入一个已存在的 portlet 到应用程序开发者。向导在项目类路径中自动包含编译 portlet 需要的必需的 jar 文件。此向导也可以用于创建新的 portlet。查询“portlet 应用程序向导”文档,以获取有关创建新的 portlet 的进一步信息。
  5. 突出显示应用程序开发者浏览器窗格中的新建项目,并单击文件然后单击导入
  6. 在“选择”对话框中选择 WAR 文件并单击下一步
  7. 使用浏览按钮定位 <wp_root>\dev\SampPers\war\SampPersPortlet.war 文件。单击完成。提示您覆盖 portlet.xml 文件时,单击全部覆盖
  8. 验证在“任务”视图中没有错误列出。

    注:如果您遇到表明“portlet 的不正确 servlet 引用”和“需要为 portlet 指定 servlet”的错误时,那么您需要在“浏览器”窗格菜单中选择项目,右击以显示弹出菜单,并单击运行验证

创建内容点

  1. 在应用程序开发者的浏览器窗格中为您的项目选择 <project_name>\source\com\ibm\wps\portlets\samppers 目录。
  2. 在菜单栏上单击内容点向导图标
  3. 在“内容点向导”欢迎页面上单击下一步
  4. 为内容点 Java bean 指定 UserTypeSpot 名称。
  5. 选择作为规则的返回类型。分类器规则具有“无”的返回类型。如果您正在为返回内容创建内容点,那么必须将该资源的 .hrf 文件导入到您的 portlet 应用程序中,并选择该资源作为您的内容点的返回类型。查询个性化文档,以获取有关资源创建和从规则返回资源的进一步信息。单击下一步
  6. 完成页面显示将由您的内容点向导创建的文件的名称。文件将在 com.ibm.wps.portlets.samppers 软件包中创建。单击完成

添加内容点到 SamplePersView.jsp

  1. 双击位于您的应用程序开发者中的 portlet 应用程序的 <project_name>\webApplication\JSP\html 目录中的 SamplePersView.jsp,打开 JSP。这是 portlet 的视图方式 JSP。确保显示 JSP 的设计视图。如果未显示,则单击当前视图下的设计选项卡。
  2. 展开 <project_name>\webApplication\WEB-INF\classes\com\ibm\wps\portlets\samppers 目录以定位文件 UserTypeSpot.class。要添加内容点到 JSP,拖动这个内容点类到 JSP 并将它放在设计视图窗口的顶部。将打开属性窗口。
  3. 单击确定关闭“属性” 窗口。
  4. 打开 JSP 的源视图。定位为内容点创建的 jsp:useBean 标记。这会类似于:
    	<jsp:useBean class=com.ibm.wps.portlets.samppers.UserTypeSpot id=userTypeSpot />
        

    在含 jsp:useBean 的语句后输入下列行:

    	<% userTypeSpot.setRequest(request); %>
        

    此语句使得 HttpServletRequest 对象可用于个性化规则处理程序。完成后的内容点应该如下所显示:

    	<jsp:useBean class=com.ibm.wps.portlets.samppers.UserTypeSpot id=userTypeSpot />
        <% userTypeSpot.setRequest(request); %>
        
  5. 因为此内容点最后将使用分类器规则(仍将创建),所以您需要添加代码来确定分类的结果。用户有四种可能的分类:音乐、运动、政治或与这些都无关。基于返回的分类,将显示匹配分类的图形。例如,如果将用户分类到音乐,那么将出现显示音乐注解的图形。在 JSP 内查找包含下列内容的表:
    	<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>

    仅应该显示这些图形中的一个,以作为由用户分类确定的图形。输入下面显示的下列 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> 标记。

  6. 保存 JSP。
  7. 突出显示浏览器窗格中的 portlet 应用程序项目,并右击鼠标按钮以显示弹出菜单。选择导出 WAR
  8. 在“WAR 导出”对话框上,单击浏览,定位保存 portlet war 文件的目录。稍后安装 portlet 时,您选择的目录必须是可访问的。保存 war 文件为 SampPersPortlet.war
  9. 单击完成生成 war 文件。
  10. 现在,您需要导出 UserTypeSpot.class 文件到安装 Personalization 的服务器的位置。再次突出显示浏览器窗格中的 portlet 应用程序项目,并单击菜单栏上的文件然后单击导出
  11. 选择文件系统并单击下一步
  12. 浏览到 <project_name>\webApplication\WEB-INF\classes\com\ibm\wps\portlets\samppers目录并在选择框中选择 UserTypeSpot.class。单击浏览...,以定位可访问安装 Personalization 的 WebSphere Application Server 的目录。在稍后的步骤中,假设此目录的名称是 C:\PZNPortlet;要帮助您遵循这些说明,您可能需要使用这个目录名称。选取框创建文件的目录结构。单击完成

安装 SamplePZNPortlet.war

  1. 以管理员用户标识登录 WebSphere Portal。
  2. 使用 门户网站管理portlet 页面上的安装 portlet portlet,安装 SampPersPortlet.war 文件。
  3. 使用门户网站管理安全性页面上的访问控制管理 portlet 给予所有已认证用户对“样本个性化 portlet”的查看访问权。
  4. 使用使用页面页面组中的编辑布局和内容任务,添加“样本个性化 portlet”到所有用户都可以访问的页面。(这将便利于稍后对 portlet 的测试。)

创建个性化项目

  1. 要创建访问用户概要文件的分类器规则,您必须复制门户网站用户 XML 资源文件到安装 Personalization 的服务器可访问的位置。将文件 User.hrf<wp_root>\dev\SampPers\resources 目录复制到 C:\PZNPortlet\resources(这是您先前导出 UserTypeSpot.class 的同一根目录)。

    注:与此样本一起提供的 User.hrf 文件是基于与 WebSphere Portal 一起提供的基本用户概要文件。它可以照原样被其它使用个性化的 portlet 使用。如果您添加任何动态属性到门户网站用户概要文件,则需要创建新的 User.hrf 文件。查询 Personalization 文档,以获取有关创建此文件的说明。

  2. 从浏览器,打开“个性化工作区”(例如:http://your_hostname/wps/PersWorkspace/index.jsp)并用具有开发者角色的用户标识登录到工作区。
  3. 单击全局设置打开“个性化全局设置”对话框。
  4. 单击图标添加新的项目。“添加项目”对话框打开。
  5. 输入您项目的路径和项目名称。您指定的路径定位于安装 WebSphere Application Server 和 Personalization 的机器上。为了方便起见,使用您复制 User.hrf 和 UserTypeSpot.class 文件的相同目录,例如,C:\PZNPortlet。单击确定
  6. 资源路径标识包含资源 XML 文件(.hrf 文件)的目录。输入 C:\PZNPortlet\resources 作为资源路径。资源和内容点类路径标识已编译资源和内容点的位置。输入 C:\PZNPortlet\webApplication\WEB-INF\classes 作为路径。(在这两种情况下,都用您先前为内容点类和用户资源使用的目录替换 C:\PZNPortlet)。单击保存保存项目。
  7. 如果项目不是管理项目列表框中的当前项目,则选择该项目并单击使之成为当前按钮。

创建个性化规则

下一个任务是要使用“个性化工作区”来创建由样本 portlet 的视图 JSP 访问的分类规则,来基于用户的属性确定要显示的内容。

  1. 在“个性化工作区”的规则撰写者中,确保在下拉选择框中选择了分类器
  2. 单击图标创建新的分类器规则。“添加分类器”对话框显示。
  3. 为分类器的名称输入 ClassifierByInterest。您还可以可选地添加注释。
  4. 在“分类器描述”区域中单击分类打开一个窗口,该窗口允许您输入分类名称音乐。在“分类名”弹出窗口中单击保存
  5. 在“分类器描述”区域中单击 Resource.Attribute,打开“选择资源”和它的“属性”对话框。单击当前用户的单选按钮作为资源。因为您使得 User.hrf 资源文件可用于“个性化工作区”,所以当前用户选择出现。在右边的滚动列表中选择兴趣属性。让属性类型为文本。单击保存关闭对话框。
  6. 在“分类器描述”区域中单击打开一个可以指定类型文本值的窗口。输入 music 作为值并单击保存
  7. 在“分类器描述”区域中单击 add Classification 两次,重复前 3 个步骤来创建规则,就象:

    分类器描述(单击加下划线的值来编辑它)


        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。

  8. 单击保存保存规则。

将规则与内容点关联起来

  1. 打开“个性化工作区”的竞销管理器
  2. 单击正常视图显示内容点和其关联的规则。UserTypeSpot 的规则标题的链接。
  3. 单击以显示对话框,在该对话框中您可以选择规则来填充内容点。
  4. 选择 ClassifyByInterest 并单击确定。您现在已将内容点与规则关联起来了。

发布规则

  1. 从“个性化工作区”内,单击全局设置打开“个性化全局设置”对话框。
  2. 单击管理发布服务器显示发布服务器的列表框。
  3. 单击图标以添加发布服务器。输入您安装 Personalization 的服务器的名称,以及到达该服务器的 URL(例如:http://cayuga.endicott.ibm.com)。如果服务器需要认证,选择需要认证复选框,并输入用户标识和密码以访问服务器。单击保存
  4. 单击发布文件
  5. 选择发布服务器和全部发布。单击发布

发布门户网站用户资源

您需要让门户网站用户资源文件(User.hrf)可用于个性化运行时。此步骤仅需执行一次。

从浏览器窗口,输入:

http://servername/PersAdmin_path/ImportServlet?filename=path_to_User.hrf

例如,如果到资源文件的全路径是 C:\PZNPortlet\resources\User.hrf;对于“个性化管理”的上下文路径是 /wps/PersAdmin;并且服务器名是 cayuga.endicott.ibm.com,那么使用下列 url(全部都在一行上)。

http://cayuga.endicott.ibm.com/wps/PersAdmin/ImportServlet?
filename=C:\PZNPortlet\resources\User.hrf

一旦用户资源成功发布,现在它就可为所有 portlet 应用程序使用。

测试 portlet

创建几个门户网站用户,为每个用户在签名页面上选择不同的兴趣。portlet 显示的图形将取决于您选择的兴趣。例如,对于一个爱好音乐的名为 Jimi Hendrix 的用户,portlet 输出将显示如下。



样本个性化 portlet portlet 标题栏控件
欢迎使用“样本个性化 portlet”  
当前用户概要文件设置:  
用户标识:Jimi  
名字:Jimi  
姓氏:Hendrix  
兴趣:音乐  
左边的图形是基于您的标号为兴趣的用户概要文件设置选择的:

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多