为了查看如何使用 Pluto 作为 portlet 的 JSR 168 兼容性测试平台,需要一个 portlet 来进行测试。在此练习中,您将创建一个简单的 portlet,它根据用户的输入,把文本框中的内容转换为全是大写字符或全是小写字符
我们从查看清单 3 所示的 portlet.xml 文件开始。portlet.xml 文件是包含关于 WAR 文件中捆绑的 portlet 的配置细节的描述符文件。
清单 3. portlet.xml 文件
<?xml version="1.0" encoding="UTF-8"?>
<portlet-app xmlns="http://java.sun.com/xml/ns/portlet/portlet-app_1_0.xsd"
version="1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/portlet/portlet-app_1_0.xsd
http://java.sun.com/xml/ns/portlet/portlet-app_1_0.xsd"
id="com.ibm.changecase.ChangeCasePortlet">
<portlet>
<portlet-name>ChangeCase</portlet-name>
<display-name>Change Case Portlet</display-name>
<portlet-class>com.ibm.changecase.ChangeCasePortlet</portlet-class>
<supports>
<mime-type>text/html</mime-type>
<portlet-mode>view</portlet-mode>
</supports>
<portlet-info>
<title>ChangeCasePortlet</title>
</portlet-info>
</portlet>
</portlet-app>
清单 3 中的 <portlet-app> 标记定义了 XML 模式定义和 portlet 应用程序 的 ID。一个 portlet 应用程序可以包含零个或多个 portlet。使用 <portlet> 标记来定义 portlet 应用程序中的单个 portlet:
<portlet-name> —— 提供一个名称,在内部或由程序使用该名称来引用 portlet。
<display-name> —— portlet 的缩写名,用来在 GUI 工具中显示 portlet 名称,它随 portlet 容器的不同而不同。
<portlet-class> —— 充当 portlet 控制器的类。
<supports> —— 这些标记定义 portlet 支持的 portlet 模式和 mime 类型。
<title> —— 可以在 portlet.xml 中定义 portlet 的首选标题。但是,如何使用该标题取决于 portlet 容器。
清单 4 显示的是 portlet.xml 中引用的 com.ibm.changecase.ChangeCasePortlet portlet 类。此类必须实现 javax.portlet.Portlet 接口,但幸运的是,您不必直接实现 Portlet 接口。JSR 168 为 javax.portlet.Portlet 接口定义了一个称为 javax.portlet.GenericPortlet 类的默认实现。com.ibm.changecase.ChangeCasePortlet 类继承 GenericPortlet 类。
清单 4. ChangeCasePortlet 类
package com.ibm.changecase;
import java.io.*;
import javax.portlet.*;
/**
*
* A sample portlet based on GenericPortlet
*
*/
public class ChangeCasePortlet extends GenericPortlet {
private static String VIEW_JSP = "/view.jsp";
protected void doView(RenderRequest request, RenderResponse response)
throws PortletException, IOException {
response.setContentType(request.getResponseContentType());
PortletContext context = getPortletConfig().getPortletContext();
context.getRequestDispatcher(VIEW_JSP).include(request, response);
}
public void processAction(ActionRequest request, ActionResponse response)
throws PortletException, java.io.IOException {
//Do Action Handling here.
}
}
注意重写 doView() 和 processAction() 方法的选择。每当出现 portlet 操作时都会调用 processAction() 方法。当用户处于 portlet 的视图模式时调用 doView() 方法。JSR 168 支持其他的模式,例如帮助模式和编辑模式。但是,如果回过头看一下 清单 3,在 <supports> 部分可以看到 portlet 只支持视图模式。
现在仔细地看一下清单 4 中的 doView() 方法。与 Java servlet 编码中一样,portlet 编码中也经常使用模型-视图-控制器 (MVC) 设计模式。因此,在 portlet 中,把表示的职责转交给了 view.jsp。或者,也可以使用 prinltn 逻辑在 doView() 方法中实现视图。
response.getWriter().println("<p>Hello World</p>()");
这种方法的问题是,图形用户界面的设计者需要具有 portlet 技术的知识来编写 doView() 方法。JSP 开发人员从复杂的 Java 开发中解放出来,能够集中精力开发前端界面。清单 5 显示的是 view.jsp:
清单 5. view.jsp
<%@ taglib uri="http://java.sun.com/portlet" prefix="portlet"%>
<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
pageEncoding="ISO-8859-1" session="false"%>
<portlet:defineObjects />
<%String textBox = renderRequest.getParameter("textBox");
if (textBox == null)
textBox = "";
String caseString = renderRequest.getParameter("case");
boolean isUpperCase = true;
if ((caseString != null) && (caseString.equals("false"))) {
isUpperCase = false;
}
String errorMessage = renderRequest.getParameter("errorMessage");%>
<%if (errorMessage != null) {%>
<p><%=errorMessage%></p>
<%}%>
<FORM name="<portlet:namespace/>caseform" action="<portlet:actionURL/>">
<INPUT type="text" name="textBox" size="20" value="<%=textBox%>">
<p><INPUT type="radio" name="case" value="lowercase"
<%if (!isUpperCase) {%> checked="checked" <%}%>>To Lowercase</p>
<p><INPUT type="radio" name="case" value="uppercase"
<%if (isUpperCase) {%> checked="checked" <%}%>>To Uppercase</p>
<INPUT type="submit" name="<portlet:namespace/>submitCase"
value="Change Case"></FORM>
首先,注意在 view.jsp 中定义 portlet 标记库。这是 JSP 解析器识别 portlet 标记所必需的。您使用的第一个 portlet 标记是 <portlet:defineObjects/>。此标记允许访问 renderRequest、renderResponse 和 portletConfig 对象。使用 renderRequest 对象使您具有访问 requestParameters 的权利。portlet 类通过 request 参数向 view JSP 传递值。
接下来,在 view.jsp 中创建一个向 portlet 类发送表单数据的表单。为了发送表单数据,必须创建一个 actionURL,它使 ChangeCasePortlet portlet 类的 processAction() 方法被调用。使用 <portlet:actionURL/> 标记创建 actionURL。 注意,在 view.jsp 中将文本框和单选按钮的值设置为服务器传回 JSP 的值。因此,view.jsp 负责处理请求输入和显示 portlet 的响应。
单击表单的 Submit 按钮会调用 portlet 的 processAction() 方法,如清单 6 所示。processAction() 从 view.jsp 接收一个 ActionRequest 对象作为输入。
清单 6. processAction 方法
public void processAction(ActionRequest request, ActionResponse response)
throws PortletException, java.io.IOException {
String newCase = request.getParameter("case");
String textBox = request.getParameter("textBox");
String errorMessage = null;
boolean isUpperCase = true;
if ((newCase!=null) && (newCase.equals(ChangeCaseConstants.LOWER_CASE)))
isUpperCase = false;
else if ((newCase == null) || (newCase==ChangeCaseConstants.UPPER_CASE))
errorMessage = "Error no case selected! Select a case.";
if (textBox !=null) {
if (isUpperCase)
textBox = textBox.toUpperCase();
else
textBox = textBox.toLowerCase();
response.setRenderParameter("textBox", textBox);
} else
errorMessage = "Error, text in the text box is invalid";
response.setRenderParameter("case", Boolean.toString(isUpperCase));
if (errorMessage != null) {
response.setRenderParameter("errorMessage",errorMessage);
}
}
ActionRequest 对象包含输入到表单中的数据。为了检索表单数据,可使用 getParameter() 方法。在 processAction() 方法中,也要执行业务逻辑,确定用户是想要大写形式还是小写形式的输出。根据该逻辑,把输入的文本转换成想要的大小写形式并发送给用户。使用 setRenderParameter() 方法把数据发送给视图。
编译并打包 JSR 168 portlet
现在已经开发了 portlet,需要把它转换成已编译的形式,并为了部署到 Pluto 将它打包。首先,确保 portlet-api-1.0.jar 在 CLASSPATH 中。然后使用 javac 编译器编译 ChangeCaseConstants.java 和 ChangeCasePortlet.java:
javac ChangeCaseConstants.java
javac ChangeCasePortlet.java
接着需要为 WAR 文件创建所需要的文件夹结构,WAR 文件是归档文件,通过它把 portlet 部署到 portlet 容器。把刚才编译的两个类放在 classes\com\ibm\changecase 目录中。
为了构建 WAR 文件,需要以下的目录结构,如清单 7 所示:
清单 7. 用于部署的目录结构
changeCaseWAR\
META-INF
MANIFEST.MF
WEB-INF
classes
com
ibm
changecase
ChangeCaseConstants.class
ChangeCasePortlet.class
lib
tld
portlet.tld
portlet.xml
web.xml
index.html
view.jsp
注意,清单 7 引入了 4 个我们还没有讨论过的文件:
portlet.tld:这是 portlet 标记库。如果回想一下,您曾经用 <portlet:defineObjects /> 之类的引用在整个 JSP 中都用到过 portlet 标记库。portlet 标记库在 Apache-SVN 代码库中可以得到(参见 参考资料)。
MANIFEST.MF:因为这里不存在外部依赖,所以这个清单文件除了 Manifest-Version: 1.0 之外什么也不包含。
index.html:如果由于某些原因上下文根被直接访问,则会显示 index.html。在 index.html 中可以有任何正确格式的 HTML。
web.xml(如清单 8 所示):它定义包含单个 portlet 的 Web 应用程序。
清单 8. web.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/dtd/web-app_2_3.dtd">
<web-app id="WebApp_ID">
<display-name>CasePortlet</display-name>
<welcome-file-list>
<welcome-file>index.html</welcome-file>
</welcome-file-list>
<taglib>
<taglib-uri>http://java.sun.com/portlet</taglib-uri>
<taglib-location>tld/portlet.tld</taglib-location>
</taglib>
<taglib id="PortletTLD">
<taglib-uri>http://java.sun.com/portlet</taglib-uri>
<taglib-location>/WEB-INF/tld/std-portlet.tld</taglib-location>
</taglib>
</web-app>
一旦生成了 MANIFEST.MF、portlet.tld、web.xml 和 index.html,就可以使用 JAR 实用工具将清单 7 所示的结构归档到一个 WAR 文件中:
C:\temp>jar -cvf changeCase.war
结果是一个叫做 changeCase.war 文件,用于部署到 JSR 168 兼容的门户。
确保 portlet 是 JSR 168 兼容的
现在使用 Apache Pluto 来查明 portlet 是否能通过 JSR168 兼容性的最终测试。
确保 Apache Pluto 启动并运行,然后导航到 Pluto 主页(http://localhost:8080/pluto/portal)。单击侧栏上的 Admin。应该看到 Deploy War portlet 显示在管理页面上,如图 4 所示。单击 Browse 并导航到在前一节中放置在一起的 changeCase.war 文件的位置,然后单击 Submit。
图 4. Pluto 的 Deploy War portlet
现在必须为 portlet 应用程序输入布局信息 —— 一个非常不重要的任务,因为在 portlet 应用程序中只有一个 portlet。正如在图 5 中可以看到的,您告知 Pluto portlet 有一行和一列,然后单击 Submit 向服务器提交此选择:
图 5.为 portlet 应用程序输入页面布局信息
接下来,必须定义 portlet 出现在 portlet 应用程序页面布局的何处。通过把 portlet 应用程序中的所有 portlet 映射到刚才定义的行和列来完成此任务。因为只有一个 portlet 需要部署并且您先前选择了一行和一列的页面布局,所以在该位置输入 ChangeCase portlet 并单击 Submit,如图 6 所示:
图 6. 映射 portlet 的位置
为了部署 portlet,您可以选择重新启动 Pluto 或者热部署 包含 portlet 的 portlet 应用程序,如图 7 所示:
图 7. 热部署 portlet
一个具有 portlet 应用程序名称(Change Case)的链接出现在侧栏。单击该超链接,现在将看到 portlet 应用程序,其中包含 portlet,如图 8 所示。这时应该与 Change Case portlet 交互并确保它的功能与预期的一样。如果与预期的一样,您就可以确定此 portlet 与 JSR 168 兼容。
图 8. 部署到 Pluto 的 Change Case portlet
Change Case Portlet 将能够运行在任何支持 JSR 168 portlet 标准的 Portlet 容器中。
参考资料
学习
您可以参阅本文在 developerWorks 全球站点上的 英文原文 。
“JSR 168 - An Introduction to the Portlet Specification”:更多地了解 JSR 168。
Apache Pluto:访问 Pluto Web 站点。
JSR 168: Portlet Specification 和 SR 286: Portlet Specification 2.0:由 Java Community Process 开发和维护的 portlet 规范。
“使用 WebSphere Portal V5.1 在 IBM Portlet 和 JSR 168 Portlet 间共享信息”(Stefan Hepper 和 Jerry Zheng,developerWorks,2006 年 2 月):编写一个自定义的 portlet 服务以允许 IBM portlet 和 JSR 168 portlet 共享作为属性的信息。
“使用 WebSphere Portal V5.1 在 JSR 168 Portlet 中缓存数据”(Stefan Hepper 和 Jerry Zheng,developerWorks,2005 年 8 月):学习如何在 JSR 168 portlet 中缓存数据以避免不必要的后端请求。
“将 WorldClock portlet 从 IBM Portlet API 转换到 JSR 168 portlet API”(Franziska Paeffgen 和 Birga Rick,developerWorks,2004 年 12 月):了解如何将最为 IBM WebSphere Portal 专有 Portlet API 开发的 portlet 转换为使用 JSR 168 标准 portlet API 的 portlet。
Verifying Apache HTTP Server Releases:有关验证来自 Apache Web 站点的下载文件的更多信息。
Java 技术专区:关于 Java 编程的各个方面的数百篇文章。
获得产品和技术
Apache Pluto:下载 Pluto。
portlet 标记库:从 Apache-SVN 代码库下载 portlet 标记。
Apache Jetspeed:一个开放源码的 portlet 容器。
Java 5.0 SDK:Pluto 需要 Java 5。
IBM 的 WebSphere Portal Server Version 5.1:支持 JSR 168 标准的商业解决方案。
GnuPG:一个免费的 PGP 工具。
分享到:
相关推荐
在RAD7中开发JSR168 Portlet
Struts2 JSR168 Portlet的开发
本压缩包里含有了开发一个jsr168 portlet所需要的软件 本想包含jetspeed2.0的安装程序的,可是最多智能上传10M <br>从环境配置讲到开发步骤。 并表明了很多注意的地方 本包适合初学portlet的人使用
JSR-168是适合于portlet开发人员的Java API集合。设计符合规范的JSR-168 portlet的原因有很多。可移植性就一个显而易见的好处。...本文将阐述开发JSR-168 portlet以便获得可移植性的最佳实践。
Eclipse 中 JSR 168 Portlet Project Creator 插件两个jar包 用于开发Portlet
许多大型企业的网站, 渐渐采用了 portal server 作为开发的基础. 至于什么是 portal 呢, 中文翻译为 "门户网站"。 有人可能想.. 天杀的.. 门户网站不是就像 yahoo, pchome, yam 等等。不过, 我们现在讨论的 portal ...
文章专门针对具有 JSR 168 Portlet 开发基础,并且想了解 JSR 286 Portlet 新特性和开发流程的开发人员。在学习完本系列后,您将了解相对于 JSR 168 Portlet,JSR 286 Portlet 究竟提供了哪些增强功能, 以及这些...
文章专门针对具有 JSR 168 Portlet 开发基础,并且想了解 JSR 286 Portlet 新特性和开发流程的开发人员。在学习完本系列后,您将了解相对于 JSR 168 Portlet,JSR 286 Portlet 究竟提供了哪些增强功能, 以及这些...
JSR-168 Portlet 开发 JSR-168 Portlet 开发
PORTAL开发相关标准:JSR168Introduction_to_JSR_168
使用jsr标准开发简单的portlet项目
开发portlet过程:包括:1.1 类名规范;1.2 RAD7开发JSR168 portlet规范;1.3编写代码 .......
JSR168规范与API手册 官方手册、标准 Portlet1.0开发必备
jsr168 portlet的开发 和 ibm portlet的开发
系列文章专门针对具有 JSR 168 Portlet 开发基础,并且想了解 JSR 286 Portlet 新特性和开发流程的开发人员。在学习完本系列后,您将了解相对于 JSR 168 Portlet,JSR 286 Portlet 究竟提供了哪些增强功能, 以及...
使用eclipse开发基于jsr168标准的portlet项目
开发Portlet的JSR-168标准手册跟帮助文档。
最近学习JSR168 portlet的开发,主要是为了让公司的产品集成到其他门户系统中
在 Portal 的开发过程中,Theme 与 ...根据 JSR 168 规范,Portlet 由容器管理,它们之间是相互独立的,并不共享 Session 对象。那么如何在 Portlet 之间传递参数呢?在本文中,将根据不同应用场景介绍参数传递的方式。