JSR 286 Portlet 的新特性,第 2 部分: 资源服务、事件与共享呈现参数


       在本系列的 第 1 部分 简要回顾了 JSR 168 Portlet,并对 JSR 286 Portlet 的新增特性做了详细的介绍, 本文将通过在 Apache Pluto 2.0 平台上开发和部署 Portlet 应用程序, 向读者介绍 JSR 286 Portlet 新特性的使用方法。本文将首先介绍 JSR 286 参考实现 Apache Pluto 2.0 平台的构建过程,然后通过在 Apache Pluto 2.0 平台上开发和部署 JSR 286 Portlet 应用程序, 向读者介绍 JSR 286 Portlet 资源服务和新增的交互功能:事件和共享呈现参数。


  关于本系列


   本系列 专门针对具有 JSR 168 Portlet 开发基础,并且想了解 JSR 286 Portlet 新特性和开发流程的开发人员。在学完本系列后,您将了解到相对于 JSR 168 Portlet,JSR 286 Portlet 究竟提供了哪些增强功能, 以及这些新增特性在实际开发中的应用。


  本系列的 第 1 部分 简单回顾了 JSR 168 Portlet, 并列出了 JSR 286 Portlet 的新增内容。第 2 部分和第 3 部分将通过在 Apache Pluto 2.0 平台上开发和部署 Portlet 应用程序, 向读者介绍 JSR 286 Portlet 新特性的使用方法。


  关于本文


   本文将首先介绍 JSR 286 参考实现 Apache Pluto 2.0 平台的构建过程,然后通过在 Apache Pluto 2.0 平台上开发和部署 JSR 286 Portlet 应用程序, 向读者介绍 JSR 286 Portlet 资源服务和新增的交互功能:事件和共享呈现参数。


  Portlet 过滤器和 Portlet 窗口方面应用程序的开发过程,将在第 3 部分进行详细介绍。


  在示例应用程序的开发和部署中用到了下列产品:


  Sun JDK 1.5


  Apache Tomcat 6.x


  Apache Pluto 2.0


        Apache Maven 2.x


  Eclipse Europa(Eclipse V3.3) for JavaEE Developers


  阅读本文之前,您应当对 JSR 168 Portlet 有所了解,并阅读了本系列的 第 1 部分。


  准备工作


  Apache Pluto 2.0 是 JSR 286 的参考实现,是实现了 Portlet 2.0 API 的 Portlet 容器,充当 Portlet 的运行时环境,与 web 应用服务器的 Servlet 容器的运行时环境支持 Servlet 的情形非常相似。Pluto 2.0 目前支持的 JSR 286 Portlet 新特性有资源服务、事件、Portlet 过滤器、共享呈现参数、 Portlet 窗口。


  在本文中,我们将使用 Apache Pluto 2.0 开发测试我们的 JSR 286 Portlet 应用程序。以下操作均在 Windows XP操作系统环境下进行。


  1. 构建 JSR 286 Portlet 运行环境 Apache Pluto 2.0


  Apache Pluto 2.0 目前还处于开发阶段,我们只能通过其源代码构建出一个支持 JSR 286 Portlet 标准的 Portlet 2.0 容器。


  安装 Sun JDK 1.5 并设定环境变量


  该步骤一般读者都比较熟悉,不再拗述。需要注意的是,经过笔者测试,Pluto 2.0 源码工程只可以在 Sun JDK 1.5 下构建成功,笔者使用 Sun JDK 1.6 和 IBM JDK 1.5 均构建失败。


  安装 Maven 2


  Pluto 源代码使用 Maven 2 进行项目管理和构建,我们必须首先安装该工具。


  从 http://maven.apache.org/ 上寻找 Maven 2 的最新版本压缩包,下载并解压,设定 Maven 2 的安装路径为 ${M2_HOME}。将 ${M2_HOME}\bin 目录加到系统的 PATH 环境变量中。


      安装 Tomcat 6


  从 http://tomcat.apache.org/ 上寻找 Tomcat 6 的最新版本压缩包,下载并解压,设定安装路径为 ${TOMCAT_HOME}。


  获取 Apache Pluto 2.0 源码


  使用 SVN 客户端从官方 SVN 服务器上获得源代码:


  清单 1. 使用 SVN 客户端从官方 SVN 服务器上获得源代码


  svn checkout https://svn.apache.org/repos/asf/portals/pluto/trunk/ pluto2


  使用 Maven 2 构建 Pluto 2.0


  编辑 ${M2_HOME}\conf 目录下的 settings.xml 文件,增加 <pluginGroups> 元素:


  清单 2. settings.xml 文件


<settings> 
 ... 
 <pluginGroups> 
  <pluginGroup>org.apache.pluto</pluginGroup> 
 </pluginGroups> 
 ... 
</settings> 

 


  打开 pluto2 目录下的 pom.xml 文件,找到


  清单 3. pom.xml 文件


... 
<jaxb-impl.version>2.1.2</jaxb-impl.version> 
... 

 


  改为


  清单 4. pom.xml 文件


  <jaxb-impl.version>2.1.3</jaxb-impl.version> 

 


  命令行模式下进入 pluto2 目录,执行以下命令:


  清单 5.


D:\>cd pluto2 
D:\pluto2>mvn install 
D:\pluto2>mvn pluto:install -DinstallDir=${TOMCAT_HOME} 

 


  如果您的 Tomcat 安装路径中存在空格,则需要用双引号把路径引起来:


  清单 6.


    mvn pluto:install 
  -DinstallDir="C:\Program Files\Apache Software Foundation\Tomcat 6.0" 


  从网上寻找 commons-logging-api-1.1.jar 文件,拷贝到 ${TOMCAT_HOME}\lib\ 目录下。


  至此,pluto2.0 的相关文件就被安装到 tomcat 相应目录下。


  编辑 ${TOMCAT_HOME}\conf\tomcat-users.xml 文件,添加角色 pluto,并在该角色下新增一个用户,以下为示例文件:


  清单 7. tomcat-users.xml 文件


<?xml version="1.0" encoding="UTF-8"?> 
<tomcat-users> 
 <role rolename="role1"/> 
 <role rolename="pluto"/> 
 <role rolename="tomcat"/> 
 <role rolename="manager"/> 
 <user password="pluto" roles="pluto,manager" username="pluto"/> 
 <user password="tomcat" roles="role1" username="role1"/> 
 <user password="tomcat" roles="tomcat,role1" username="both"/> 
 <user password="tomcat" roles="tomcat,pluto,manager" username="tomcat"/> 
</tomcat-users> 

 


  验证安装


  运行 ${TOMCAT_HOME}\bin\startup.bat,启动 tomcat 服务器。浏览器访问 URL http://localhost:8080/pluto/portal,如图 1 所示:


  图 1. Pluto 登录界面




  输入添加到 pluto 角色的用户名和密码,进入 Pluto 的 Portal 页面:


  图 2. Pluto Portal界面




  至此,JSR 286 Portlet 运行环境 Apache Pluto 2.0 搭建成功。


  2. 使用 Eclipse Europa 建立开发环境


   首先,需要从 Eclipse 官方网站 http://www.eclipse.org 下载 Eclipse Europa,针对不同的开发需求,有几种包可供下载。我们进行的是 J2EE Web 开发,所以注意要下载 Eclipse IDE for Java EE Developers。


  启动 Eclipse,对 Eclipse 进行配置:


  执行菜单项目 Window -> Preferences,打开 Preferences 对话框,选择 Server -> Installed Runtimes 项,如 图 3 所示:


  图 3. Preferences 对话框



 

  点击 Add 按钮,将 Tomcat 6 添加为运行时,如 图 4、图 5 所示:


  图 4. 选择运行时类型



  图 5. 设定 Tomcat 安装路径



  单击 Finish 结束配置,单击 OK 关闭 Preferences 对话框。


  在 Eclipse 的 Servers 视图中单击鼠标右键,选择 New -> Server。如 图 6 所示:


  图 6. 新建服务器



  在弹出的窗口中选择目标运行服务器 Apache Tomcat 6.0 Server,运行时呈现 Apache Tomcat v6.0,如图7所示,点击 Finish。


  图 7. 选择目标运行服务器



 

  在 Servers 视图中双击刚刚新建的 Tomcat 服务器,打开服务器配置页面,如图 8 所示:


  图 8. Tomcat 服务器配置页面



 

  在 Server Locations 中选择 Use Tomcat Installation,Deploy Path选择 ${TOMCAT_HOME}\webapps,如图 9 所示。至此开发环境设置完毕。


  必须设定 Deploy Path 为 Tomcat 安装目录下的 webapps 目录,否则使用 Eclipse 启动 Tomcat 后,Pluto 不能加载进来。


  图 9. Tomcat 服务器配置



  创建 JSR 286 Portlet 应用


  下面,我们开始创建一系列程序来演示 JSR 286 Portlet 的新特性。主要分为以下六个部分:


  使用 Eclipse 创建 Portlet Web 项目


  资源服务


  事件


  Portlet 过滤器


  共享呈现参数


  Portlet 窗口


  1. 使用 Eclipse 创建 Portlet Web 项目


  新建项目,项目类型选择 Web->Dynamic Web Project,如图 10 所示:


  图 10. 新建动态 Web 项目



  接下来,设置项目属性,项目名称 jsr286portlets, 目标运行时 Apache Tomcat V6.0,保留默认设置,点击 Finish,如 图 11 所示:


  图 11. 设置项目属性



 

  生成项目结构如图 12:


  图 12. 项目结构



  在 META-INF 下新建 context.xml 文件,内容如下:


  清单 8. context.xml 文件


  <Context crossContext="true" /> 

 

  该文件为 Tomcat 的特有配置文件,根据 Pluto 的要求,该 Web 工程的上下文应该可以被其它 JavaEE 程序访问,所以 crossContext 参数设置为 true。


  在 WEB-INF 下新建 portlet.xml 文件,内容如下:


  清单 9. portlet.xml 文件


<?xml version="1.0" encoding="UTF-8"?> 
<portlet-app 
  xmlns="http://java.sun.com/xml/ns/portlet/portlet-app_2_0.xsd" 
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
  xsi:schemaLocation="http://java.sun.com/xml/ns/portlet/portlet-app_2_0.xsd 
      http://java.sun.com/xml/ns/portlet/portlet-app_2_0.xsd" 
  version="2.0"> 
  <!-- 在该位置填写portlet描述内容 --> 
</portlet-app> 

 

  下面我们将在黑体部分填写 portlet 定义。


  2. 资源服务


  新增 Java 类 TestPortlet,实现了 javax.portlet.Portlet 和 javax.portlet.ResourceServingPortlet 接口:


  清单 10. TestPortlet.java 文件


package com.ibm.samples.jsr286.portlets; 
 
import ... 
 
public class TestPortlet implements Portlet, ResourceServingPortlet { 
 
  private PortletConfig portletConfig; 
 
  public void init(PortletConfig portletConfig) throws PortletException { 
    this.portletConfig = portletConfig; 
  } 
 
  public void destroy() { 
  } 
 
  public void processAction(ActionRequest actionRequest, 
    ActionResponse actionResponse) throws PortletException, IOException { 
  } 
 
  public void render(RenderRequest renderRequest, 
    RenderResponse renderResponse) throws PortletException, IOException { 
    PortletRequestDispatcher portletRequestDispatcher = portletConfig 
      .getPortletContext().getRequestDispatcher( 
        "/WEB-INF/jsp/TestPortletView.jsp"); 
    portletRequestDispatcher.include(renderRequest, renderResponse); 
  } 
 
  public void serveResource(ResourceRequest resourceRequest, 
    ResourceResponse resourceResponse) throws PortletException, 
    IOException { 
    PortletRequestDispatcher portletRequestDispatcher = portletConfig 
      .getPortletContext().getRequestDispatcher( 
        "/WEB-INF/jsp/TestPortletResource.jsp"); 
    portletRequestDispatcher.include(resourceRequest, resourceResponse); 
  } 
} 

 

  在 WEB-INF 目录下新建 jsp 目录,在 jsp 目录下新建 portlet 呈现阶段所显示的 jsp 文件

TestPortletView.jsp。


  清单 11. TestPortletView.jsp 文件


<%@ page language="java" contentType="text/html; charset=UTF-8"  pageEncoding="UTF-8"%> 
<%@taglib prefix="portlet" uri="http://java.sun.com/portlet_2_0"%> 
<portlet:defineObjects /> 
<table> 
  <tr> 
    <td><h1>Test portlet page.</h1></td> 
  </tr> 
  <tr> 
    <td><a href="<portlet:resourceURL/>">Click me to request Resource URL</a></td> 
  </tr> 
</table> 

 


  在 jsp 目录下新建 portlet 资源服务所请求的 jsp 文件 TestPortletResource.jsp。


  清单 12. TestPortletResource.jsp 文件


<%@ page language="java" contentType="text/html; charset=UTF-8"  pageEncoding="UTF-8"%> 
<%@taglib prefix="portlet" uri="http://java.sun.com/portlet_2_0"%> 
<portlet:defineObjects /> 
<table> 
  <tr> 
    <td><h1>Test portlet resource page.</h1></td> 
  </tr> 
</table> 

 


  编辑 portlet.xml 文件, 为 TestPortlet 增加一个 portlet 定义片断,该 TestPortlet 仅支持 View 模式。


  清单 13. TestPortlet 定义片断


<portlet> 
  <portlet-name>TestPortlet</portlet-name> 
  <display-name>TestPortlet</display-name> 
  <portlet-class>com.ibm.samples.jsr286.portlets.TestPortlet</portlet-class> 
  <supports> 
    <mime-type>text/html</mime-type> 
    <portlet-mode>VIEW</portlet-mode> 
  </supports> 
  <portlet-info> 
    <title>TestPortlet</title> 
  </portlet-info> 
</portlet>

 

 


  编辑 web.xml 文件,增加 Pluto 所需的 servlet 定义及映射。读者请注意,该定义为 Pluto 2.0 Portlet 容器所需,不属于 JSR 286 标准的要求。


  清单 14. Pluto 所需的 servlet 定义及映射片断


<servlet> 
  <servlet-name>TestPortlet</servlet-name> 
  <servlet-class> 
    org.apache.pluto.core.PortletServlet 
  </servlet-class> 
  <init-param> 
    <param-name>portlet-name</param-name> 
    <param-value>TestPortlet</param-value> 
  </init-param> 
  <load-on-startup>1</load-on-startup> 
</servlet> 
 
<servlet-mapping> 
  <servlet-name>TestPortlet</servlet-name> 
  <url-pattern>/PlutoInvoker/TestPortlet</url-pattern> 
</servlet-mapping> 

 

  在 Eclipse 的 Servers 视图中,右键单击 Tomcat 服务器,点击 Add and Remove Projects,在弹出的对话框中将 jsr286portlets 项目添加到右侧栏目中,点击 Finish 确认,如图13:


  图 13. 部署项目到服务器



  在 Servers 视图中启动服务器,Console 视图中输出 Tomcat 启动信息。


  浏览器中输入相应 url 访问 pluto 的 portal 页面,登录,点击 Pluto Admin 导航栏,如图14:

  图 14. Pluto 管理界面



 

  使用该工具新建一个页面,如 "Test JSR 286 Portlet Page"。导航栏中马上新增一项 "Test JSR 286 Portlet Page",点击进入该页面可以见到目前该页面没有内容。


   选择 jsr286portlets 应用程序中的 Portlet TestPortlet,选择上一步新建的页面,点击 Add Portlet 按钮,将 TestPortlet 布局到 "Test JSR 286 Portlet Page"页面。如图 15:


  图 15. 布局 Portlet 到 Portal 页面



  进入"Test JSR 286 Portlet Page"页面,该页面新增了一个 Portlet TestPortlet,如图16:


  图 16. TestPortlet 界面



  注意到上图 portlet 的标题显示为 null, 这是由于 pluto 2.0 目前处于开发阶段,存在一些 bug,读者可不必理会。


  点击超链接,进入所请求的资源页面,如图 17:


  图 17. TestPortlet 资源界面





   观察此页面,发现此页面只显示了 TestPortletResource.jsp 的内容,未经过 Portal 容器的修饰, 和直接请求一个 Servlet 或者 JSP 页面的效果是一样的。这就是 JSR 286 Portlet 资源服务的主要特性。对照此示例,读者可加深对 第 1 部分 相关内容的理解。


  3. 事件


  简单事件


  新建 Java 类 TestSimpleEventSenderPortlet, 在该 Portlet 类的 processAction 方法中,发送一个简单事件,事件内容为一个字符串。


  清单 15. TestSimpleEventSenderPortlet.java 文件


package com.ibm.samples.jsr286.portlets; 
 
import ... 
 
public class TestSimpleEventSenderPortlet implements Portlet { 
 
  ... 
 
  public void processAction(ActionRequest actionRequest, 
      ActionResponse actionResponse) throws PortletException, IOException { 
    actionResponse.setEvent("simple-event", "simple-event is sent by " 
        + portletConfig.getPortletName()); 
 
  } 
 
  public void render(RenderRequest renderRequest, 
      RenderResponse renderResponse) throws PortletException, IOException { 
    PortletRequestDispatcher portletRequestDispatcher = portletConfig 
        .getPortletContext().getRequestDispatcher( 
            "/WEB-INF/jsp/TestSimpleEventSenderPortletView.jsp"); 
    portletRequestDispatcher.include(renderRequest, renderResponse); 
  } 
} 

 

  在 jsp 目录下新建 jsp 文件 TestSimpleEventSenderPortletView.jsp


  清单 16. TestSimpleEventSenderPortletView.jsp 文件


<%@ page language="java" contentType="text/html; charset=UTF-8"  pageEncoding="UTF-8"%> 
<%@taglib prefix="portlet" uri="http://java.sun.com/portlet_2_0"%> 
<portlet:defineObjects /> 
<form action="<portlet:actionURL/>"> 
<table> 
  <tr> 
    <td><h1>Test simple event sender portlet page.</h1></td> 
  </tr> 
  <tr> 
    <td> 
     <input type="submit" value="Click me to send simple event to other portlets"> 
    </td> 
  </tr> 
</table> 
</form> 

 


  新建 Java 类 TestSimpleEventReceiverPortlet, 在该 Portlet 实现了 javax.portlet.EventPortlet 接口,可以响应事件。


  清单 17. TestSimpleEventReceiverPortlet.java 文件


package com.ibm.samples.jsr286.portlets; 
 
import ... 
 
public class TestSimpleEventReceiverPortlet implements Portlet, EventPortlet { 
 
  ... 
 
  public void processAction(ActionRequest actionRequest, 
      ActionResponse actionResponse) throws PortletException, IOException { 
  } 
 
  public void render(RenderRequest renderRequest, 
      RenderResponse renderResponse) throws PortletException, IOException { 
    PortletRequestDispatcher portletRequestDispatcher = portletConfig 
        .getPortletContext().getRequestDispatcher( 
            "/WEB-INF/jsp/TestSimpleEventReceiverPortletView.jsp"); 
    portletRequestDispatcher.include(renderRequest, renderResponse); 
  } 
 
  public void processEvent(EventRequest eventRequest, 
      EventResponse eventResponse) throws PortletException, IOException { 
    Event event = eventRequest.getEvent(); 
    eventResponse.setRenderParameter("eventName", event.getName()); 
    eventResponse.setRenderParameter("eventValue", event.getValue().toString()); 
  } 
} 

 

  在 jsp 目录下新建 jsp 文件 TestSimpleEventReceiverPortletView.jsp


  清单 18. TestSimpleEventReceiverPortletView.jsp 文件


<%@ page language="java" contentType="text/html; charset=UTF-8"  pageEncoding="UTF-8"%> 
<%@taglib prefix="portlet" uri="http://java.sun.com/portlet_2_0"%> 
<portlet:defineObjects /> 
<table> 
  <tr> 
    <td><h1>Test simple event receiver portlet page.</h1></td> 
  </tr> 
  <tr> 
    <td><h2>Received simple event:</h2></td> 
  </tr> 
  <tr> 
    <td>Event name:<%=renderRequest.getParameter("eventName")%></td> 
  </tr> 
  <tr> 
    <td>Event value:<%=renderRequest.getParameter("eventValue")%></td> 
  </tr> 
</table> 

 


   在 portlet.xml 文件中新增 TestSimpleEventSenderPortlet 定义, 该 portlet 支持事件的发布,注意 supported-publishing-event 元素中定义所支持发布的事件名称为 simple-event。


  清单 19. TestSimpleEventSenderPortlet 定义


<portlet> 
  <portlet-name>TestSimpleEventSenderPortlet</portlet-name> 
  <display-name>TestSimpleEventSenderPortlet</display-name> 
  <portlet-class> 
    com.ibm.samples.jsr286.portlets.TestSimpleEventSenderPortlet 
  </portlet-class> 
  <supports> 
    <mime-type>text/html</mime-type> 
    <portlet-mode>VIEW</portlet-mode> 
  </supports> 
  <portlet-info> 
    <title>TestSimpleEventSenderPortlet</title> 
  </portlet-info> 
  <supported-publishing-event> 
    <name>simple-event</name> 
  </supported-publishing-event> 
</portlet>

 

 

  在 portlet.xml 文件中新增 TestSimpleEventReceiverPortlet 定义, 该 portlet 支持事件的响应处理,注意 supported-processing-event 元素中定义所支持处理的事件名称为 simple-event。


  清单 20. TestSimpleEventReceiverPortlet 定义


<portlet> 
  <portlet-name>TestSimpleEventReceiverPortlet</portlet-name> 
  <display-name>TestSimpleEventReceiverPortlet</display-name> 
  <portlet-class> 
    com.ibm.samples.jsr286.portlets.TestSimpleEventReceiverPortlet 
  </portlet-class> 
  <supports> 
    <mime-type>text/html</mime-type> 
    <portlet-mode>VIEW</portlet-mode> 
  </supports> 
  <portlet-info> 
    <title>TestSimpleEventReceiverPortlet</title> 
  </portlet-info> 
  <supported-processing-event> 
    <name>simple-event</name> 
  </supported-processing-event> 
</portlet> 

 


  您还需要在 portlet.xml 文件中添加以下声明,定义 QName 默认的命名空间和事件定义,该事件类型为 java.lang.String。


  清单 21. simple-event 定义


<default-namespace>http://cn.ibm.com/</default-namespace> 
<event-definition> 
  <name>simple-event</name> 
  <value-type>java.lang.String</value-type> 
</event-definition> 


  参照 TestPortlet 的定义,为 TestSimpleEventSenderPortlet 和 TestSimpleEventReceiverPortlet 在 web.xml 里添加 Pluto 所需的 servlet 定义及映射。


  将 TestSimpleEventSenderPortlet 和 TestSimpleEventReceiverPortlet 部署到"Test JSR 286 Portlet Page"页面,如图 18 和 图 19。


  图 18. 简单事件发布 portlet



  图 19. 简单事件响应 portlet



  点击 TestSimpleEventSenderPortlet 中的按钮,TestSimpleEventReceiverPortlet 如图 20 所示:


  图 20. 简单事件响应



  表明 TestSimpleEventReceiverPortlet 接收到了名为 simple-event 的事件,事件值为 "simple-event is sent by TestSimpleEventSenderPortlet"。


  复合事件


  定义一个 复合事件 Java 类 SampleComplexEvent, 该类是可序列化的,并且存在 int, String, Date 三种类型的属性。


  清单 22. SampleComplexEvent.java 文件

 

package com.ibm.samples.jsr286.events; 
 
import ... 
 
public class SampleComplexEvent implements Serializable { 
 
  private static final long serialVersionUID = -1447091586272283310L; 
 
  private int intItem; 
 
  private String strItem; 
 
  private Date dateItem; 
 
  //setters and getters 
  ... 
}


  新建 Java 类 TestComplexEventSenderPortlet, 在该 Portlet 类的 processAction 方法中,发送一个复合事件,事件类型为 com.ibm.samples.jsr286.events.SampleComplexEvent。


  清单 23. TestComplexEventSenderPortlet.java 文件


package com.ibm.samples.jsr286.portlets; 
 
import ... 
 
public class TestComplexEventSenderPortlet implements Portlet { 
 
  ... 
 
  public void processAction(ActionRequest actionRequest, 
      ActionResponse actionResponse) throws PortletException, IOException { 
    SampleComplexEvent event = new SampleComplexEvent(); 
    event.setIntItem(new Random().nextInt()); 
    event.setStrItem("complex-event is sent by " 
        + portletConfig.getPortletName()); 
    event.setDateItem(new Date()); 
    actionResponse.setEvent("complex-event", event); 
 
  } 
 
  public void render(RenderRequest renderRequest, 
      RenderResponse renderResponse) throws PortletException, IOException { 
    PortletRequestDispatcher portletRequestDispatcher = portletConfig 
        .getPortletContext().getRequestDispatcher( 
            "/WEB-INF/jsp/TestComplexEventSenderPortletView.jsp"); 
    portletRequestDispatcher.include(renderRequest, renderResponse); 
  } 
} 



  在 jsp 目录下新建 jsp 文件 TestComplexEventSenderPortletView.jsp, 内容同 清单 16.TestSimpleEventSenderPortletView.jsp 文件 类似。


  新建 Java 类 TestComplexEventReceiverPortlet, 在该 Portlet 实现了 javax.portlet.EventPortlet 接口,可以响应复合事件。


  清单 24. TestComplexEventReceiverPortlet.java 文件


package com.ibm.samples.jsr286.portlets; 
 
import ... 
 
public class TestComplexEventReceiverPortlet implements Portlet, EventPortlet { 
 
  ... 
 
  public void processAction(ActionRequest actionRequest, 
      ActionResponse actionResponse) throws PortletException, IOException { 
  } 
 
  public void render(RenderRequest renderRequest, 
      RenderResponse renderResponse) throws PortletException, IOException { 
    PortletRequestDispatcher portletRequestDispatcher = portletConfig 
        .getPortletContext().getRequestDispatcher( 
            "/WEB-INF/jsp/TestComplexEventReceiverPortletView.jsp"); 
    portletRequestDispatcher.include(renderRequest, renderResponse); 
  } 
 
  public void processEvent(EventRequest eventRequest, 
      EventResponse eventResponse) throws PortletException, IOException { 
    Event event = eventRequest.getEvent(); 
    eventResponse.setRenderParameter("eventName", event.getName()); 
    SampleComplexEvent eventValue = (SampleComplexEvent) event.getValue(); 
    eventResponse.setRenderParameter("intItem", Integer.toString(eventValue 
        .getIntItem())); 
    eventResponse.setRenderParameter("strItem", eventValue.getStrItem()); 
    eventResponse.setRenderParameter("dateItem", eventValue.getDateItem().toString()); 
  } 
} 




  在 jsp 目录下新建 jsp 文件 TestComplexEventReceiverPortletView.jsp


  清单 25. TestComplexEventReceiverPortletView.jsp 文件


<%@ page language="java" contentType="text/html; charset=UTF-8"  pageEncoding="UTF-8"%> 
<%@taglib prefix="portlet" uri="http://java.sun.com/portlet_2_0"%> 
<portlet:defineObjects /> 
<table> 
  <tr> 
    <td><h1>Test complex event receiver portlet page.</h1></td> 
  </tr> 
  <tr> 
    <td><h2>Received complex event:</h2></td> 
  </tr> 
  <tr> 
    <td>Event name:<%=renderRequest.getParameter("eventName")%></td> 
  </tr> 
  <tr><td>Event value</td></tr> 
  <tr> 
    <td>Integer item:<%=renderRequest.getParameter("intItem")%></td> 
  </tr> 
  <tr> 
    <td>String item:<%=renderRequest.getParameter("strItem")%></td> 
  </tr> 
  <tr> 
    <td>Date item:<%=renderRequest.getParameter("dateItem")%></td> 
  </tr> 
</table> 

 


   请读者自行参照清单 19 和 清单 20 在 portlet.xml 文件中定义两个portlet TestComplexEventSenderPortlet 和 TestComplexEventReceiverPortlet, 使其分别支持发布和响应事件 complex-event。


  在 portlet.xml 文件中添加以下声明,定义事件名称和类型,该事件类型为com.ibm.samples.jsr286.events.SampleComplexEvent,如清单 26 所示:


  清单 26.


<event-definition> 
  <name>complex-event</name> 
  <value-type>com.ibm.samples.jsr286.events.SampleComplexEvent</value-type> 
</event-definition> 

 


  参照 TestPortlet 的定义, 为 TestComplexEventSenderPortlet 和 TestComplexEventReceiverPortlet 在 web.xml 里添加 Pluto 所需的 servlet 定义及映射。


  将 TestComplexEventSenderPortlet 和 TestComplexEventSenderPortlet 部署到"Test JSR 286 Portlet Page"页面,如图 21 和 图 22。


  图 21. 复合事件发布 portlet



  图 22. 复合事件响应 portlet



  点击 TestComplexEventSenderPortlet 中的按钮,TestComplexEventReceiverPortlet 如图 23 所示:


  图 23. 复合事件响应



  表明 TestComplexEventReceiverPortlet 接收到了名为 complex-event 的事件,事件值如图 23 所示。


  4. 共享呈现参数


  更改 TestPortletView.jsp 文件,在文件末尾增加表单和输入框接收输入参数,如清单 26 所示:


  清单 26. 表单和共享呈现参数值输入框


... 
<form action="<portlet:actionURL/>"> 
<table> 
  <tr><td>Input public render parameter value:</td></tr> 
  <tr> 
    <td><input type="text" name="public-render-param"></td> 
  </tr> 
  <tr> 
    <td><input type="submit" value="Submit"></td> 
  </tr> 
</table> 
</form> 

 

  更改 TestPortlet 的 processAction 方法,将从输入框中得到的值传送到呈现阶段的请求参数中,如清单 27 所示:


  清单 27. TestPortlet 的 processAction 方法


... 
public void processAction(ActionRequest actionRequest, 
    ActionResponse actionResponse) throws PortletException, IOException { 
  String publicRenderParamValue = actionRequest.getParameter("public-render-param"); 
  actionResponse.setRenderParameter("public-render-param", publicRenderParamValue); 
} 
... 

 


  新建 portlet 类 TestPublicRenderParameterPortlet, 如清单 28 所示:


  清单 28. TestPublicRenderParameterPortlet.java 文件


package com.ibm.samples.jsr286.portlets; 
 
import ... 
 
public class TestPublicRenderParameterPortlet implements Portlet { 
 
  private PortletConfig portletConfig; 
 
  public void init(PortletConfig portletConfig) throws PortletException { 
    this.portletConfig = portletConfig; 
  } 
 
  public void destroy() { 
  } 
   
  public void processAction(ActionRequest actionRequest, 
      ActionResponse actionResponse) throws PortletException, IOException { 
  } 
 
  public void render(RenderRequest renderRequest, 
      RenderResponse renderResponse) throws PortletException, IOException { 
    PortletRequestDispatcher portletRequestDispatcher = portletConfig 
        .getPortletContext() 
        .getRequestDispatcher( 
            "/WEB-INF/jsp/TestPublicRenderParameterPortletView.jsp"); 
    portletRequestDispatcher.include(renderRequest, renderResponse); 
  } 
}

 

  TestPublicRenderParameterPortlet 呈现所需的 jsp 页面 TestPublicRenderParameterPortletView.jsp 如清单 29 所示:


  清单 29. TestPublicRenderParameterPortletView.jsp 文件

 

<%@ page language="java" contentType="text/html; charset=UTF-8"  pageEncoding="UTF-8"%> 
<%@taglib prefix="portlet" uri="http://java.sun.com/portlet_2_0"%> 
<portlet:defineObjects /> 
<table> 
  <tr><td><h1>Test public render parameter test page.</h1></td></tr> 
  <tr><td><h2>Received public render parameter value:</h2></td></tr> 
  <tr> 
    <td>Parameter value:<%=renderRequest.getParameter("public-render-param")%></td> 
  </tr> 
</table>




  编辑 portlet.xml 文件, 在 TestPortlet 定义的尾端加入 清单 30 中 的内容,使得 portlet TestPortlet 支持共享呈现参数 public-render-param。


  清单 30.


<portlet> 
... 
  <supported-public-render-parameter> 
    public-render-param 
  </supported-public-render-parameter> 
</portlet> 

 


  在 portlet.xml 中增加 TestPublicRenderParameterPortlet 的定义,并加入清单 30 中的内容。


  在 portlet.xml 末尾添加 清单 31 中的内容:


  清单 31.

... 
  <public-render-parameter> 
    <identifier>public-render-param</identifier> 
  </public-render-parameter> 
</portlet-app> 

 


  为 TestPublicRenderParameterPortlet 在 web.xml 里添加 Pluto 所需的 servlet 定义及映射。


  将 TestPortlet 和 TestPublicRenderParameterPortlet 部署到 "Test JSR 286 Portlet Page" 页面,如图 24 和 图 25。


  图 24. 输入共享呈现参数值




  图 25. 显示共享呈现参数值的 portlet



  在 TestPortlet 中输入参数值 testvalue, 提交表单,则在 TestPublicRenderParameterPortlet 呈现图 26 所示结果:


  图 26. 显示共享呈现参数值




  小结


   本部分介绍了 JSR 286 Portlet 容器的参考实现 Apache Pluto 2.0 的构建过程,以及使用 Eclipse 和 Apache Pluto 2.0 进行 Portlet 开发的方法流程,并且通过示例代码介绍了JSR 286 Portlet 资源服务、事件交互和共享呈现参数的实际开发步骤。JSR 286 规范目前还处于草案阶段,而且相应的 Portlet 容器还处于不稳定版本的开发阶段,在具体的实验性开发过程中需要读者对 Portelt 容器本身的 Bug 加以注意。

JSR 286 Portlet 的新特性,第 3 部分: Portlet 过滤器和 Portlet 窗口 NULL 博文链接:https://tyler-zhou.iteye.com/blog/680621 立即下载

相关推荐

JSR286规范与API手册

JSR286规范与API手册 JSR286 Portlet 门户 portal portlet2.0开发必备

JSR 286

 新规范的一些主要功能及特性:资源服务:一种新的通过 portlet 呈现资源的方式。事件:通过发送事件和接收事件来实现 portlet 之间的通信。Portlet 过滤器:与 servlet 过滤器类似,根据 Portlet 请求和响应动态的呈现内容的变换。存在以下四种类型的 portlet 过滤器: Action 过滤器Render 过滤器Res

yanghw0510的专栏 1103

JSR286 portlet新特性

文章专门针对具有 JSR 168 Portlet 开发基础,并且想了解 JSR 286 Portlet 新特性和开发流程的开发人员。在学习完本系列后,您将了解相对于 JSR 168 Portlet,JSR 286 Portlet 究竟提供了哪些增强功能, 以及这些新增特性在实际开发中的应用。

portlet 2.0_Java Portlet规范V2.0(JSR 286)中有哪些新功能?

Portlet是组件化的面向用户的应用程序,可创建某种标记。 该标记旨在与其他标记片段聚合到一个更大的应用程序中,例如,如图1所示的门户页面。 图1.一个样本门户页面 因此,可以将Portlet视为基于用户界面(UI)的服务,这些服务采用面向服务的体系结构(SOA)的方式一直到用户界面。 Java Portlet规范的第一个版本Java规范要求(JSR)168在2003年的Java...

cusi77914的博客 709

【Docker】搭建一个媒体服务器插件后端API服务 - MetaTube

本教程基于群晖的NAS设备DS423+的docker功能进行搭建,DSM版为 7.2.1-69057 Update 5。MetaTube是一个媒体服务器插件,主要用于Emby和Jellyfin媒体服务器。它的主要功能是从互联网上抓取内容并响应 JSON 数据,然后通过预安装的 MetaTube 插件请求服务器并下载相应的元数据,以与 Jellyfin/Emby 服务器配合使用。使用 MetaTube 的步骤大致如下:部署后端:首先,需要部署一个名为​ 的后端 API 服务器来抓取内容。

小小笔记大大用处 1万+

车辆动力学仿真模型的可信度评估方法

以转向工况测试为例,实车采集的方向盘转角作为车辆动力学模型的输入,记录车辆动力学模型的横摆角速度的输出结果,计算横摆角速度的幅频特性,根据《GB/T 6323-2014 转向盘角脉冲试验》的方法,获取横摆角速度峰值、横摆角速度谐振峰频率、横摆角速度谐振峰水平,与采集的实车结果对比,并计算车辆动力学模型和实车对于关键对比参数的相对误差。由公式(2)计算可得,在制动工况和转向工况测试下,车辆动力学模型和实车的纵向车速、制动减速度、制动距离、横摆角速度基本一致,精度> 85%,具有较好的精度。

wangchen900705的博客 1958

JSR286 Portlet开发:Portlet之间的Events通信

开发工具:Jdeveloper 11.1.1.7 1.创建Portlet Application a.选择File->New,在新建向导中选择WebCenter Portal - Portlet Producer Application,如下图: b.在向导中输入Application Name,如下图所示: c.其他配置默认即可,点击【Finish】完成。 2.

CQMKING的专栏 973

用示波器抓一次MIPI D-PHY的波形,手把手教你读懂HS模式和LP模式的切换时序

本文详细解析了MIPI D-PHY信号的双模切换机制,包括高速模式(HS)和低功耗模式(LP)的波形捕获与诊断技巧。通过示波器设置、关键状态分析和实战案例,帮助工程师快速定位信号完整性问题,提升调试效率。

weixin_30696427的博客 453

JSR 286 Portlet 的新特性,第 1 部分: Portlet 2.0 新特性介绍

关于本文本文假定读者熟知 JSR 168 Portlet,并对 J2EE 基本常识有一定了解。本文主要以理论的方式向读者介绍 JSR 286 Portlet 的以下新增特性: 资源服务 事件 共享呈现参数 Portlet 过滤器 Portlet 窗口 Portlet 和 JSR 168Portlet 是部署在容器内用来生

762

S32DS IDE调试技巧:如何用Attach功能高效定位汽车电子MCU的Bootloader问题

本文详细介绍了在汽车电子MCU开发中,如何利用S32DS IDE的Attach调试模式高效定位Bootloader与应用程序的协同问题。通过对比常规调试与Attach模式的本质差异,并深入讲解工程配置、镜像合并及实战调试流程,帮助开发者在不复位、不重新下载程序的前提下,实时分析系统状态,快速解决内存映射冲突、中断向量表重定向等疑难杂症。

weixin_29168393的博客 265

物联网技术(AIR780E cat1-4G模块+小程序+腾讯云MQTT)驱动的智能井盖系统设计(连载01)

终端设备采用AIR780E模块作为主控器,电子模块有三轴加速度传感器、可燃气体传感器,AIR780E模块(4G模块)通过MQTT通信协议进行数据打包上传至EMQX服务器,在EMQX服务器中,用户可以自行订阅主题和发布主题,小程序通过MQTT通信协议订阅EMQX服务器的主题,服务器通过接收到硬件发布的数据,转发到微信小程序。

leida_3669的博客 2214

JSR 286 Portlet 的新特性: Portlet 2.0 新特性介绍(portlet协作、事件机制、数据共享)

  本文假定读者熟知 JSR 168 Portlet,并对 J2EE 基本常识有一定了解。本文主要以理论的方式向读者介绍 JSR 286 Portlet 的以下新增特性:  资源服务  事件  共享呈现参数  Portlet 过滤器  Portlet 窗口  Portlet 和 JSR 168  Portlet 是部署在容器内用来生成动态内容的 Web 组件,与 ser

jianpingdu2009的专栏 1078

openEuler 欧拉 安装Oracle19c数据库RPM包安装

欧拉系统安装部署oracle 19c rpm方式

陈苏漾的IT生涯 6891

JSR 286 Portlet 的新特性: Portlet 2.0 新特性介绍

关于本文本文假定读者熟知 JSR 168 Portlet,并对 J2EE 基本常识有一定了解。本文主要以理论的方式向读者介绍 JSR 286 Portlet 的以下新增特性:资源服务事件共享呈现参数Portlet 过滤器Portlet 窗口回页首Portlet

jianpingdu2009的专栏 1217

10、进化动力学谱分析中的开放性问题

本文探讨了进化动力学谱分析中的若干开放性问题,重点围绕进化算法的性能与设计理论展开。文章首先介绍了规范模型及其线性动力学特性,随后深入分析了在实际应用中偏离理想情况的两个关键因素:有限种群和双亲重组。在此基础上提出了三个核心开放性问题:寻找最优传输矩阵以实现全局最优解的高效搜索、无限与有限种群模型谱之间的关系、以及卡林定理在多遗传算子下的推广可能性。通过谱条件、快速混合性与首次命中时间的关系分析,文章进一步讨论了全局吸引与快速收敛的理论基础,并提出了未来的研究方向,包括理论深化、实验拓展与跨学科融合,旨在为

cuda7parallel的博客 80

华为嵌入式面试题及参考答案(持续更新)

异步是指在程序执行过程中,某些任务不需要等待立即完成就可以继续执行其他任务的过程。在计算机编程中,异步通常用于处理长时间运行的操作,如文件读写、网络通信等,以避免阻塞主线程。异步处理通常涉及到回调函数、事件循环、协程或未来的概念。使用宏定义来避免命名冲突。#else#endif堆和栈是计算机程序中用于存储数据的两种不同类型的内存区域。

大模型大数据攻城狮的专栏 2480

Portlet 2.0 新特性介绍(全)

第一部分 Portlet 2.0 新特性介绍======================================================================  关于本系列  本系列文章专门针对具有 JSR 168 Portlet 开发基础,并且想了解 JSR 286 Portlet 新特性和开发流程的开发人员。在学习完本系列后,您将了解相对于JSR 168 Portle...

caoming51021的专栏 1417

LinePhone3.2.7(android端最新版本) sip客户端

SIP客户端For android:LinePhone3.2.7(最新版本),官网地址:http://www.linphone.org/

JSR 286 Portlet 的新特性 第 1 部分: Portlet 2.0 新特性介绍

关于本系列 本系列文章专门针对具有 JSR 168 Portlet 开发基础,并且想了解 JSR 286 Portlet 新特性和开发流程的开发人员。在学习完本系列后,您将了解相对于 JSR 168 Portlet,JSR 286 Portlet 究竟提供了哪些增强功能, 以及这些新增特性在实际开发中的应用。 第 1 部分将简单回顾 JSR 168 Portlet, 并列出了 JSR 286

墨者侠客 657

efm32 入门.pdf

本PDF共计22页,介绍的是操作驱动API,下载与否自己斟酌。

STM32F407中文手册

STM32f407中文手册 本参考手册面向应用开发人员,提供有关使用 STM32F405xx/07xx、STM32F415xx/17xx、 STM32F42xxx 和 STM32F43xxx 微控制器存储器与外设的完整信息。STM32F405xx/07xx、STM32F415xx/17xx、STM32F42xxx 和 STM32F43xxx 构成一个微 控制器系列,各产品具有不同的存储器大小、封装和外设。有关订购信息以及器件的机械与电气特性,请参见数据手册。有关 ARM Cortex™-M4F 内核的信息,请参见《Cortex™-M4F 技术参考手册》。

Portlet开发指南

一、 Portlet简介 Portlet与servlet一样,都是jcr的规范api定义,不同的portlet还比较“年轻”,目前版本还只到2.0,而servlet规范已经相当成熟,发布了多个版本。如果不是十分准确的说,portlet只是另一种开发web程序的api,从这个方面说,开发portlet并没有什么神秘的地方,但是之所以有portlet这个规范,portlet适用的场景肯定与servl

xywlzd的专栏 3291

C# WinForm 基于DirectShow.dll编写的程序,可边预览边保存视频,音频和图片

基于微软的DirectShow.dll的二次开发1.自动识别连接的摄像头跟麦克风且可以对其进行选择(默认选中第一个)2.可录制wmv和avi两种格式的视频并且都带有音频,avi可以录制的分辨率和帧数进行选择,wmv默认进行了淸晰度优化如不喜欢可去除代码中有相关提示3.可在预览点开之后进行拍照,也可边录制视频边拍照4.添加了视频和音频的压缩功能(酌情使用)这次二次开发发现C#对DirectShow的相关信息太少,这次做完也不敢藏私共享出来,还望大家指正

《portal开发指南》第一章

一、 Portlet简介 Portlet与servlet一样,都是jcr的规范api定义,不同的portlet还比较“年轻”,目前版本还只到2.0,而servlet规范已经相当成熟,发布了多个版本。如果不是十分准确的说,portlet只是另一种开发web程序的api,从这个方面说,开发portlet并没有什么神秘的地方,但是之所以有portlet这个规范,portlet适用的场景肯定与ser

689
上一篇: JSR 286 Portlet 的新特性,第 1 部分: Portlet 2.0 新特性介绍
下一篇: JSR 286 Portlet 的新特性,第 3 部分: Portlet 过滤器和 Portlet 窗口
iteye_4621
博客等级 码龄8年 1粉丝 6原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值