本部分向您介绍有关创建 portlet 的概念,从一个彻底修改过的简单的 portlet 开始。使用有关 Portlet API 的部分和 Javadoc 作为参考。
如果您熟悉为 WebSphere Portal Family 产品版本 2.1 开发 portlet,应该可以注意到 Portlet API 已作了显著改进。请参阅迁移 portlet 以获取更多信息。 创建简单 portlet 实例WebSphere Portal 包括可在 wp_root/install 目录中找到的下列预定义的 portlet 集合。
这些 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 包含以下文件:
下面几部分描述如何创建一个简单的 Hello World portlet,以及如何编译、封装和部署这个 portlet。没有为 Hello World 提供文件样本;您必须使用文本中提供的示例来创建它。然而,在 wp_root/dev 目录下提供了 HelloWorld2.war,它演示了如何使用 JSP 来提供 portlet 标记。 设置 portlet 开发环境在尝试本部分所讨论的任何类和样本之前,您应该设置一个让编写、编译和测试 portlet 各任务更易于实现的环境。WebSphere Portal 产品软件包包含下列开发工具:
除了开发工作站之外,还应设置门户网站服务器以便通过安装下列组件来发布和测试您的 portlet 应用程序项目:
请参阅在 WebSphere Application Server 高级单服务器版上安装 WebSphere Portal,以获取进一步的信息。 Hello World portletHello World portlet 提供编写您的第一个 portlet 的介绍。Hello World 扩展 AbstractPortlet 帮助器类,并提供一个 portlet 必需的最少方法。它使用 PortletResponse 提供到门户网站页面的简单输出。 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 文件格式。要创建名为 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,请按照这些步骤操作:
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 应用程序作为结构化的目录层次结构而存在。
支持多个标记和语言环境门户网站聚集允许您封装 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 其中
例如,如果客户机使用的是语言特性设置为英语(美国)的 Internet Explorer 5,方法
把 portlet 和资源封装进 WAR 文件任何 JAR 实用程序都可用于构建 WAR 文件。下面是如何使用 WebSphere Application Server 提供的 JAR 实用程序的示例。
创建 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 时有几点注意事项:
<%@ 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 提供 <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> 控制器类扩展 使用持久性使用 PortletData 对象保存、检索或删除 portlet 数据到持久性 portlet 数据。只有当 portlet 处于编辑方式下时,portlet 才可在 PortletData 对象中存储值。如果 portlet 在组页面上,则 PortletData 中保存的信息对所有 portlet 的用户都是可用的。portlet 通过调用 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 类型的数据才可保存到 注:位于缺省门户网站页面的 portlet(在用户登录前)不能访问 Hello World2 样本中也使用了 PortletData,使用户能编辑问候语并将其保存为持久性。此外,
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 实现了 portlet 消息传递Portlet API 支持一张页面上的 portlet 之间的消息传递。例如,如果四个 portlet(Left、Right、Top、Bottom)是称为 Sides 的 portlet 应用程序一部分,则 portlet Left 能向 portlet Right、Top 和 Bottom 发送信息(只要它们在用户的相同页面上)。下列条件应用于发送和接收消息的 portlet。
通常,消息是从 portlet 的操作侦听器发送的,并由另一个 portlet 的消息侦听器接收。用户在一个 portlet 中执行操作。捕捉和处理操作事件。根据该操作结果,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 中已经定义“浏览”操作。 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() 方法采用下列自变量:
正在接收的 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); } } } 由于 要获取有关操作事件和消息事件的更多信息,请参阅 Portlet 事件。 消息和跟踪记录日志Portlet 可以把消息和跟踪信息写到日志文件,该文件在 wp_root/log/ 目录中维护。该日志文件帮助门户网站管理员审查 portlet 错误和特殊情况并帮助 portlet 开发者测试和调试 portlet。Portlet API 提供
[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 之后才进行设置。 个性化 portletWebSphere 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 提供下列类,这些类实现必需的接口以使得可以从个性化访问门户网站用户概要文件。
User 类实现两种类型的用户属性:固定属性和动态属性。这两种类型都是持久的(存储在后端数据库),并且都可以用于个性化。两种类型的差异主要在于处理添加新属性中涉及的内容。
应在性能和效率中进行权衡。使用固定属性对于运行时有一些好处,而使用动态属性对于较简短的开发和管理时有些好处。User 类提供固定属性的一个小的集合,以及添加和使用动态属性的能力。 样本的目标WebSphere Portal 的签名页面包含固定的和动态的属性。名字、姓氏、电子邮件地址和首选语言是固定属性;而兴趣是动态属性。这是此样本 portlet 访问的动态兴趣属性。对于兴趣有四种可能的值:音乐、政治、运动和未选择。此示例使用个性化规则来确定当前门户网站用户的分类,这是基于此属性的设置,并使用这个分类来确定要显示四种可能的图像中的哪一种。
WebSphere Personalization 的能力要大大超出此样本中显示的那些。除了用户资源之外,个性化还可以访问内容资源。分类器规则仅是三种类型的个性化规则中的一种。您还可以创建操作规则来允许个性化选择数据或内容,因而可以在 portlet 外部作出决定;和绑定规则来组合操作和分类器,以指定在遇到您定义的条件时要执行的操作。查询 WebSphere Personalization 文档,以获取进一步的信息。 此样本是一个了解练习。样本 portlet 不提供个性化。下面的步骤描述将个性化包含到 portlet 中必须执行的操作。为您提供的说明是为了:
必备软件要按照此处略述的步骤,您需要安装下列产品:
样本包含的文件与此样本相关的文件可以在 <wp_root>\dev\SampPers\ 目录中找到。
导入 SampPersPortlet.war 文件要使用“个性化内容点”向导,您必须导入 <wp_root>\dev\SampPers\war\SampPersPortlet.war 文件到 WebSphere Studio Application Developer。
创建内容点
添加内容点到 SamplePersView.jsp
安装 SamplePZNPortlet.war
创建个性化项目
创建个性化规则下一个任务是要使用“个性化工作区”来创建由样本 portlet 的视图 JSP 访问的分类规则,来基于用户的属性确定要显示的内容。
将规则与内容点关联起来
发布规则
发布门户网站用户资源您需要让门户网站用户资源文件(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 输出将显示如下。
|
|
来自: bluecrystal > 《Portal》