﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>BlogJava-世事如棋-文章分类-Web Service</title><link>http://www.blogjava.net/kingwell/category/8834.html</link><description>Aspire to Professionalism</description><language>zh-cn</language><lastBuildDate>Tue, 27 Feb 2007 12:56:54 GMT</lastBuildDate><pubDate>Tue, 27 Feb 2007 12:56:54 GMT</pubDate><ttl>60</ttl><item><title>使用 Apache Pluto 构建和测试 JSR 168 兼容的 portlets </title><link>http://www.blogjava.net/kingwell/articles/48560.html</link><dc:creator>KingWell</dc:creator><author>KingWell</author><pubDate>Sun, 28 May 2006 01:03:00 GMT</pubDate><guid>http://www.blogjava.net/kingwell/articles/48560.html</guid><wfw:comment>http://www.blogjava.net/kingwell/comments/48560.html</wfw:comment><comments>http://www.blogjava.net/kingwell/articles/48560.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/kingwell/comments/commentRss/48560.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/kingwell/services/trackbacks/48560.html</trackback:ping><description><![CDATA[
		<blockquote>Apache Pluto 是 Java™ 开发人员可以自由使用的工具，用来测试他们的 portlets 是否遵循 JSR 168 Portlet 规范。开发人员 Mark Talbot 和 Kulvir Singh Bhogal 带领您学习 portlet 测试。您将安装 Pluto，构建、编译和打包一个简单的 portlet，并将它部署到 Pluto 以测试它的 JSR 168 兼容性。您还将了解到 Portlet 规范的下一个版本将保留哪些内容。</blockquote>
		<!--START RESERVED FOR FUTURE USE INCLUDE FILES-->
		<!-- include java script once we verify teams wants to use this and it will work on dbcs and cyrillic characters -->
		<!--END RESERVED FOR FUTURE USE INCLUDE FILES-->
		<p>2003 年 10 月，Java Community Process 发布了 Java Specification Request (JSR) 168的最终版本：Portlet Specification（参见 <a href="http://www-128.ibm.com/developerworks/cn/java/j-pluto/#resources"><font color="#996699">参考资料</font></a>）。JSR 168 阐述的是第一个 Java portlet 开发的编程标准。以前，为 WebSphere Portal Server 开发的 portlet 不能在另外的 portlet 容器（例如 BEA WebLogic Portal）中运行。Portlet 容器不是 J2EE 应用服务器所必需的组件。然而，这种可移植性的缺少是与标准 J2EE 企业级应用程序相背离的，标准 J2EE 企业级应用程序（当根据规范构建时）可以部署到任何与 J2EE 兼容的应用服务器中。缺少 portlet 可移植性和相关厂商的锁定阻止企业购买门户服务器。通过结束 portlet 开发的混乱状态，JSR 168 平息了那些企业的担忧。</p>
		<table cellspacing="0" cellpadding="0" width="40%" align="right" border="0">
				<tbody>
						<tr>
								<td width="10">
										<img height="1" alt="" src="http://www.ibm.com/i/c.gif" width="10" />
								</td>
								<td>
										<table cellspacing="0" cellpadding="5" width="70%" border="1">
												<tbody>
														<tr>
																<td bgcolor="#eeeeee">JSR 168 Portlet API 是相当广泛的。本文不打算成为 JSR 168 的教程，因此我们将不去深入钻研这些 API。如果您不熟悉 JSR 168 API， 建议您花一些时间去熟悉 <a href="http://www-128.ibm.com/developerworks/cn/java/j-pluto/#resources"><font color="#996699">参考资料</font></a> 中的一些材料。 </td>
														</tr>
												</tbody>
										</table>
								</td>
						</tr>
				</tbody>
		</table>
		<p>Java 开发人员具有一个可以自由获得的工具，用来测试他们编写的 portlets 是否与 Portlet 规范相一致。Apache Pluto 是 JSR 168 的参考实现，是实现了 Portlet API 的 portlet 容器。像 Pluto 和 IBM WebSphere Portal Server 这样的 portlet 容器充当 portlets 的运行时环境，与 web 应用服务器的 servlet 容器的运行时环境支持 servlet 的情形非常相似。但是，portlet 容器不是独立的，它存在于 servlet 容器的顶部并依赖于它的服务。在本文中，我们将为您演示如何编写简单的 portlet 并使用 Pluto portlet 容器测试它。 </p>
		<p>
				<a name="IDAYDGFD">
						<span class="atitle">
								<font face="Arial" size="4">安装 Pluto</font>
						</span>
				</a>
		</p>
		<p>Apache Pluto 需要 Java SE 5。如果您还没有安装此版本的 JDK，下载并安装它以继续进行本文的练习（参见 <a href="http://www-128.ibm.com/developerworks/cn/java/j-pluto/#resources"><font color="#996699">参考资料</font></a>）。</p>
		<table cellspacing="0" cellpadding="0" width="40%" align="right" border="0">
				<tbody>
						<tr>
								<td width="10">
										<img height="1" alt="" src="http://www.ibm.com/i/c.gif" width="10" />
								</td>
								<td>
										<table cellspacing="0" cellpadding="5" width="70%" border="1">
												<tbody>
														<tr>
																<td bgcolor="#eeeeee">
																		<p>如果 <code>JAVA_HOME</code> 已经设置为在您的系统上安装的先前版本的 JVM， 更改它会使已有的依赖 JVM 的应用程序崩溃。如果已经安装了老版本的 JVM，您应该直接在 Pluto 启动脚本中更新 <code>JAVA_HOME</code> 变量： Windows 系统上的 startup.bat 或者 Linux 上的 startup.sh。</p>
																</td>
														</tr>
												</tbody>
										</table>
								</td>
						</tr>
				</tbody>
		</table>
		<p>接下来，需要设置和更改 <code>JAVA_HOME</code> 环境变量，Pluto 引用它来查找 JVM（默认情况下，Sun 的安装程序不设置 <code>JAVA_HOME</code> 的值）。如果在系统上没有安装以前版本的 JVM，则执行以下步骤（这些说明假定您运行的是 windows）：</p>
		<ol>
				<li>右击<b>我的电脑</b>，并从上下文菜单选择<b>属性</b>。 
</li>
				<li>单击<b>高级</b>选项卡。 
</li>
				<li>在窗口的底部，单击<b>环境变量</b>按钮。 
</li>
				<li>在<b>系统变量</b>窗格中，单击<b>新建</b>。 
</li>
				<li>为变量名输入 <code>JAVA_HOME</code>。为变量值输入 Sun JVM 的安装目录。 </li>
		</ol>
		<p>图 1 展示了选择把 Java 5.0 SDK 安装到 C:\Program Files\IBM\Java50 目录下时 <code>JAVA_HOME</code> 的值：</p>
		<br />
		<a name="fig1">
				<b>图 1. 更改 JAVA_HOME 环境变量</b>
		</a>
		<br />
		<img height="147" alt="" src="http://www-128.ibm.com/developerworks/cn/java/j-pluto/environment.jpg" width="347" />
		<br />
		<p>现在已经正确地设置了 Java 环境，就来从 Apache 的 Web 站点（参见 <a href="http://www-128.ibm.com/developerworks/cn/java/j-pluto/#resources"><font color="#996699">参考资料</font></a>）下载包含 Pluto 的二进制内容的 ZIPet 文件（pluto-current.zip）。</p>
		<p>
				<a name="IDAPGGFD">
						<span class="smalltitle">
								<strong>
										<font face="Arial">验证下载文件</font>
								</strong>
						</span>
				</a>
		</p>
		<p>假定您和我们的安全意识一样强，就会希望保证下载的 ZIP 文件确实来自 Apache Software Foundation。文件使用 PGP 和 MD5 进行了数字签名。使用 GnuPG（参见 <a href="http://www-128.ibm.com/developerworks/cn/java/j-pluto/#resources"><font color="#996699">参考资料</font></a>）和 ASCII armor 文件（pluto-current.zip.asc），可以验证此下载文件的真实性。</p>
		<p>首先，通过输入清单 1 顶部一行所示的命令，把 Apache Pluto 的公共密钥添加到您的公共密钥环。在 Pluto 下载页面可以获得 KEYS 文件。</p>
		<br />
		<a name="IDA4GGFD">
				<b>清单 1. 导入 KEYS 文件</b>
		</a>
		<br />
		<table cellspacing="0" cellpadding="5" width="70%" bgcolor="#eeeeee" border="1">
				<tbody>
						<tr>
								<td>
										<pre>
												<code class="section">
														<font face="Lucida Console">C:\&gt;gpg --import KEYS
gpg: key E41EDC7E: public key "Carsten Ziegeler &lt;cziegeler@apache.org&gt;" importe

gpg: key 320B4FB4: public key "Nick Lothian (Apache) &lt;nlothian@apache.org&gt;" imp
rted
gpg: key DD4200EA: public key "David H. DeWolf &lt;david@daviddewolf.com&gt;" importe

gpg: Total number processed: 3
gpg:               imported: 3
gpg: 3 marginal(s) needed, 1 complete(s) needed, PGP trust model
gpg: depth: 0  valid:   1  signed:   0  trust: 0-, 0q, 0n, 0m, 0f, 1u
gpg: next trustdb check due at 2011-03-08
</font>
												</code>
										</pre>
								</td>
						</tr>
				</tbody>
		</table>
		<br />
		<p>接下来，输入清单 2 顶部一行所示的命令来验证您从 Apache 接收的已签名的 ZIP 文件：</p>
		<br />
		<a name="IDAIHGFD">
				<b>清单 2. 验证 pluto-1.0.1.zip.asc </b>
		</a>
		<br />
		<table cellspacing="0" cellpadding="5" width="70%" bgcolor="#eeeeee" border="1">
				<tbody>
						<tr>
								<td>
										<pre>
												<code class="section">
														<font face="Lucida Console">C:\&gt;gpg --verify pluto-1.0.1.zip.asc
gpg: Signature made 10/19/05 09:11:31 using DSA key ID DD4200EA
gpg: Good signature from "David H. DeWolf &lt;david@daviddewolf.com&gt;"
gpg:               aka "David H. DeWolf &lt;ddewolf@apache.org&gt;"
gpg:               aka "David H. DeWolf &lt;ddewolf@rocketmail.com&gt;"
gpg:               aka "David H. DeWolf &lt;ddewolf@gmail.com&gt;"
gpg:               aka "David H. DeWolf &lt;david.dewolf@digitalfocus.com&gt;"
gpg: WARNING: This key is not certified with a trusted signature!
gpg:          There is no indication that the signature belongs to the owner.
Primary key fingerprint: 6AA5 5850 9A7B 275C E0BC  2851 B217 63FA DD42 00EA
</font>
												</code>
										</pre>
								</td>
						</tr>
				</tbody>
		</table>
		<br />
		<p>如果 <code>gpg --verify</code> 命令生成的输出与清单 2 显示的相似，就可以确信 Pluto 归档文件确实来自 Apache。可以忽略表明签名不可信的警告。保证公共密钥签名来自所有者的惟一方法是，密钥的所有者亲自把磁盘上的密钥交给您。但是，采取这些步骤以后，可以在某种程度上确定从 Apache 下载的 ZIP 文件是不用怀疑的。（有关验证 Apache 下载文件的更多信息，请参见 <a href="http://www-128.ibm.com/developerworks/cn/java/j-pluto/resources.html"><font color="#5c81a7">参考资料</font></a> 。）</p>
		<p>
				<a name="IDAYHGFD">
						<span class="smalltitle">
								<strong>
										<font face="Arial">解压 Pluto 下载文件</font>
								</strong>
						</span>
				</a>
		</p>
		<p>现在准备把 ZIP 文件解压到您的机器上。我们假定您把 Pluto 解压到 C:\ 盘的根目录上：</p>
		<table cellspacing="0" cellpadding="5" width="70%" bgcolor="#eeeeee" border="1">
				<tbody>
						<tr>
								<td>
										<pre>
												<code class="section">
														<font face="Lucida Console">C:\&gt;unzip pluto-current.zip
</font>
												</code>
										</pre>
								</td>
						</tr>
				</tbody>
		</table>
		<br />
		<p>这就创建了一个包含 bin 子目录的 C:\pluto-1.0.1 目录。导航到 bin 子目录并在命令提示符下输入 <code>startup.bat</code> 以启动 Pluto 服务器。 </p>
		<p>如图 2 所示，您可以从 Pluto 主页管理和查看 portlets。启动 Web 浏览器并导航到 http://localhost:8080/pluto/portal。 </p>
		<br />
		<a name="fig2">
				<b>图 2. Pluto 主页</b>
		</a>
		<br />
		<img height="474" alt="Pluto 主页" src="http://www-128.ibm.com/developerworks/cn/java/j-pluto/plutostart.jpg" width="592" />
		<br />
		<p>
				<i>
						<b>注意：</b>如果 Pluto 主页没有出现，请确保防火墙没有阻止 Pluto 接受连接。</i>
		</p>
		<p>现在已经启动和运行 Pluto，您将创建一个简单的 portlet，然后使用 Pluto 测试它的 JSR 168 兼容性。</p>
		<br />
		<table cellspacing="0" cellpadding="0" width="70%" border="0">
				<tbody>
						<tr>
								<td>
										<img height="1" alt="" src="http://www.ibm.com/i/v14/rules/blue_rule.gif" width="70%" />
										<br />
										<img height="6" alt="" src="http://www.ibm.com/i/c.gif" width="8" border="0" />
								</td>
						</tr>
				</tbody>
		</table>
		<table class="no-print" cellspacing="0" cellpadding="0" align="right">
				<tbody>
						<tr align="right">
								<td>
										<img height="4" alt="" src="http://www.ibm.com/i/c.gif" width="70%" />
										<br />
										<table cellspacing="0" cellpadding="0" border="0">
												<tbody>
														<tr>
																<td valign="center">
																		<img height="16" alt="" src="http://www.ibm.com/i/v14/icons/u_bold.gif" width="16" border="0" />
																		<br />
																</td>
																<td valign="top" align="right">
																		<a class="fbox" href="http://www-128.ibm.com/developerworks/cn/java/j-pluto/#main">
																				<b>
																						<font color="#996699">回页首</font>
																				</b>
																		</a>
																</td>
														</tr>
												</tbody>
										</table>
								</td>
						</tr>
				</tbody>
		</table>
		<br />
		<br />
		<p>
				<a name="IDA2QQGD">
						<span class="atitle">
								<font face="Arial" size="4">开发 JSR 168 portlet</font>
						</span>
				</a>
		</p>
		<p>为了查看如何使用 Pluto 作为 portlet 的 JSR 168 兼容性测试平台，需要一个 portlet 来进行测试。在此练习中，您将创建一个简单的 portlet，它根据用户的输入，把文本框中的内容转换为全是大写字符或全是小写字符（见图 3）：</p>
		<br />
		<a name="fig3">
				<b>图 3. Change Case portlet</b>
		</a>
		<br />
		<img height="237" alt="" src="http://www-128.ibm.com/developerworks/cn/java/j-pluto/portal.jpg" width="572" />
		<br />
		<p>我们从查看清单 3 所示的 portlet.xml 文件开始。portlet.xml 文件是包含关于 WAR 文件中捆绑的 portlet 的配置细节的描述符文件。</p>
		<br />
		<a name="listing3">
				<b>清单 3. portlet.xml 文件</b>
		</a>
		<br />
		<table cellspacing="0" cellpadding="5" width="70%" bgcolor="#eeeeee" border="1">
				<tbody>
						<tr>
								<td>
										<pre>
												<code class="section">
														<font face="Lucida Console">&lt;?xml version="1.0" encoding="UTF-8"?&gt;
&lt;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"&gt;
   &lt;portlet&gt;
      &lt;portlet-name&gt;ChangeCase&lt;/portlet-name&gt;
      &lt;display-name&gt;Change Case Portlet&lt;/display-name&gt;
      &lt;portlet-class&gt;com.ibm.changecase.ChangeCasePortlet&lt;/portlet-class&gt;
      &lt;supports&gt;
         &lt;mime-type&gt;text/html&lt;/mime-type&gt;
         &lt;portlet-mode&gt;view&lt;/portlet-mode&gt;
      &lt;/supports&gt;
      &lt;portlet-info&gt;
         &lt;title&gt;ChangeCasePortlet&lt;/title&gt;
      &lt;/portlet-info&gt;
   &lt;/portlet&gt;
&lt;/portlet-app&gt;
</font>
												</code>
										</pre>
								</td>
						</tr>
				</tbody>
		</table>
		<br />
		<p>清单 3 中的 <code>&lt;portlet-app&gt;</code> 标记定义了 XML 模式定义和 <i>portlet 应用程序</i> 的 ID。一个 portlet 应用程序可以包含零个或多个 portlet。使用 <code>&lt;portlet&gt;</code> 标记来定义 portlet 应用程序中的单个 portlet：</p>
		<ul>
				<li>
						<b>
								<code>&lt;portlet-name&gt;</code>
						</b>—— 提供一个名称，在内部或由程序使用该名称来引用 portlet。 
</li>
				<li>
						<b>
								<code>&lt;display-name&gt;</code>
						</b>—— portlet 的缩写名，用来在 GUI 工具中显示 portlet 名称，它随 portlet 容器的不同而不同。 
</li>
				<li>
						<b>
								<code>&lt;portlet-class&gt;</code>
						</b>—— 充当 portlet 控制器的类。 
</li>
				<li>
						<b>
								<code>&lt;supports&gt;</code>
						</b>—— 这些标记定义 portlet 支持的 portlet 模式和 mime 类型。 
</li>
				<li>
						<b>
								<code>&lt;title&gt;</code>
						</b>—— 可以在 portlet.xml 中定义 portlet 的首选标题。但是，如何使用该标题取决于 portlet 容器。 </li>
		</ul>
		<p>清单 4 显示的是 portlet.xml 中引用的 <code>com.ibm.changecase.ChangeCasePortlet</code> portlet 类。此类必须实现 <code>javax.portlet.Portlet</code> 接口，但幸运的是，您不必直接实现 <code>Portlet</code> 接口。JSR 168 为 <code>javax.portlet.Portlet</code> 接口定义了一个称为 <code>javax.portlet.GenericPortlet</code> 类的默认实现。<code>com.ibm.changecase.ChangeCasePortlet</code> 类继承 <code>GenericPortlet</code> 类。</p>
		<br />
		<a name="IDADUQGD">
				<b>清单 4. ChangeCasePortlet 类</b>
		</a>
		<br />
		<table cellspacing="0" cellpadding="5" width="70%" bgcolor="#eeeeee" border="1">
				<tbody>
						<tr>
								<td>
										<pre>
												<code class="section">
														<font face="Lucida Console">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.

}

}
</font>
												</code>
										</pre>
								</td>
						</tr>
				</tbody>
		</table>
		<br />
		<p>注意重写 <code>doView()</code> 和 <code>processAction()</code> 方法的选择。每当出现 portlet 操作时都会调用 <code>processAction()</code> 方法。当用户处于 portlet 的视图模式时调用 <code>doView()</code> 方法。JSR 168 支持其他的模式，例如帮助模式和编辑模式。但是，如果回过头看一下 <a href="http://www-128.ibm.com/developerworks/cn/java/j-pluto/#listing3"><font color="#996699">清单 3</font></a>，在 <code>&lt;supports&gt;</code> 部分可以看到 portlet 只支持视图模式。 </p>
		<p>现在仔细地看一下清单 4 中的 <code>doView()</code> 方法。与 Java servlet 编码中一样，portlet 编码中也经常使用模型-视图-控制器 (MVC) 设计模式。因此，在 portlet 中，把表示的职责转交给了 view.jsp。或者，也可以使用 <code>prinltn</code> 逻辑在 <code>doView()</code> 方法中实现视图。</p>
		<table cellspacing="0" cellpadding="5" width="70%" bgcolor="#eeeeee" border="1">
				<tbody>
						<tr>
								<td>
										<pre>
												<code class="section">
														<font face="Lucida Console">response.getWriter().println("&lt;p&gt;Hello World&lt;/p&gt;()");
</font>
												</code>
										</pre>
								</td>
						</tr>
				</tbody>
		</table>
		<br />
		<p>这种方法的问题是，图形用户界面的设计者需要具有 portlet 技术的知识来编写 <code>doView()</code> 方法。JSP 开发人员从复杂的 Java 开发中解放出来，能够集中精力开发前端界面。清单 5 显示的是 view.jsp：</p>
		<br />
		<a name="IDA4VQGD">
				<b>清单 5. view.jsp</b>
		</a>
		<br />
		<table cellspacing="0" cellpadding="5" width="70%" bgcolor="#eeeeee" border="1">
				<tbody>
						<tr>
								<td>
										<pre>
												<code class="section">
														<font face="Lucida Console">&lt;%@ taglib uri="http://java.sun.com/portlet" prefix="portlet"%&gt;
&lt;%@ page language="java" contentType="text/html; charset=ISO-8859-1"
	pageEncoding="ISO-8859-1" session="false"%&gt;
&lt;portlet:defineObjects /&gt;

&lt;%String textBox = renderRequest.getParameter("textBox");
		if (textBox == null)
			textBox = "";
		String caseString = renderRequest.getParameter("case");
		boolean isUpperCase = true;
		if ((caseString != null) &amp;&amp; (caseString.equals("false"))) {
			isUpperCase = false;
		}
		String errorMessage = renderRequest.getParameter("errorMessage");%&gt;

&lt;%if (errorMessage != null) {%&gt;
&lt;p&gt;&lt;%=errorMessage%&gt;&lt;/p&gt;
&lt;%}%&gt;

&lt;FORM name="&lt;portlet:namespace/&gt;caseform" action="&lt;portlet:actionURL/&gt;"&gt;
&lt;INPUT type="text" name="textBox" size="20" value="&lt;%=textBox%&gt;"&gt;
&lt;p&gt;&lt;INPUT type="radio" name="case" value="lowercase"
	&lt;%if (!isUpperCase) {%&gt; checked="checked" &lt;%}%&gt;&gt;To Lowercase&lt;/p&gt;
&lt;p&gt;&lt;INPUT type="radio" name="case" value="uppercase"
	&lt;%if (isUpperCase) {%&gt; checked="checked" &lt;%}%&gt;&gt;To Uppercase&lt;/p&gt;
&lt;INPUT type="submit" name="&lt;portlet:namespace/&gt;submitCase"
	value="Change Case"&gt;&lt;/FORM&gt;
</font>
												</code>
										</pre>
								</td>
						</tr>
				</tbody>
		</table>
		<br />
		<p>首先，注意在 view.jsp 中定义 portlet 标记库。这是 JSP 解析器识别 portlet 标记所必需的。您使用的第一个 portlet 标记是 <code>&lt;portlet:defineObjects/&gt;</code>。此标记允许访问 <code>renderRequest</code>、<code>renderResponse</code> 和 <code>portletConfig</code> 对象。使用 <code>renderRequest</code> 对象使您具有访问 <code>requestParameters</code> 的权利。portlet 类通过 request 参数向 view JSP 传递值。 </p>
		<p>接下来，在 view.jsp 中创建一个向 portlet 类发送表单数据的表单。为了发送表单数据，必须创建一个 <code>actionURL</code>，它使 <code>ChangeCasePortlet</code> portlet 类的 <code>processAction()</code> 方法被调用。使用 <code>&lt;portlet:actionURL/&gt;</code> 标记创建 <code>actionURL</code>。 注意，在 view.jsp 中将文本框和单选按钮的值设置为服务器传回 JSP 的值。因此，view.jsp 负责处理请求输入和显示 portlet 的响应。</p>
		<p>单击表单的 <b>Submit</b> 按钮会调用 portlet 的 <code>processAction()</code> 方法，如清单 6 所示。<code>processAction()</code> 从 view.jsp 接收一个 <code>ActionRequest</code> 对象作为输入。</p>
		<br />
		<a name="IDAKYQGD">
				<b>清单 6. processAction 方法</b>
		</a>
		<br />
		<table cellspacing="0" cellpadding="5" width="70%" bgcolor="#eeeeee" border="1">
				<tbody>
						<tr>
								<td>
										<pre>
												<code class="section">
														<font face="Lucida Console"> 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) &amp;&amp; (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);
    }
   
 }
</font>
												</code>
										</pre>
								</td>
						</tr>
				</tbody>
		</table>
		<br />
		<p>
				<code>ActionRequest</code> 对象包含输入到表单中的数据。为了检索表单数据，可使用 <code>getParameter()</code> 方法。在 <code>processAction()</code> 方法中，也要执行业务逻辑，确定用户是想要大写形式还是小写形式的输出。根据该逻辑，把输入的文本转换成想要的大小写形式并发送给用户。使用 <code>setRenderParameter()</code> 方法把数据发送给视图。</p>
		<br />
		<table cellspacing="0" cellpadding="0" width="70%" border="0">
				<tbody>
						<tr>
								<td>
										<img height="1" alt="" src="http://www.ibm.com/i/v14/rules/blue_rule.gif" width="70%" />
										<br />
										<img height="6" alt="" src="http://www.ibm.com/i/c.gif" width="8" border="0" />
								</td>
						</tr>
				</tbody>
		</table>
		<table class="no-print" cellspacing="0" cellpadding="0" align="right">
				<tbody>
						<tr align="right">
								<td>
										<img height="4" alt="" src="http://www.ibm.com/i/c.gif" width="70%" />
										<br />
										<table cellspacing="0" cellpadding="0" border="0">
												<tbody>
														<tr>
																<td valign="center">
																		<img height="16" alt="" src="http://www.ibm.com/i/v14/icons/u_bold.gif" width="16" border="0" />
																		<br />
																</td>
																<td valign="top" align="right">
																		<a class="fbox" href="http://www-128.ibm.com/developerworks/cn/java/j-pluto/#main">
																				<b>
																						<font color="#996699">回页首</font>
																				</b>
																		</a>
																</td>
														</tr>
												</tbody>
										</table>
								</td>
						</tr>
				</tbody>
		</table>
		<br />
		<br />
		<p>
				<a name="IDABZQGD">
						<span class="atitle">
								<font face="Arial" size="4">编译并打包 JSR 168 portlet</font>
						</span>
				</a>
		</p>
		<p>现在已经开发了 portlet，需要把它转换成已编译的形式，并为了部署到 Pluto 将它打包。首先，确保 portlet-api-1.0.jar 在 <code>CLASSPATH</code> 中。然后使用 javac 编译器编译 ChangeCaseConstants.java 和 ChangeCasePortlet.java：</p>
		<table cellspacing="0" cellpadding="5" width="70%" bgcolor="#eeeeee" border="1">
				<tbody>
						<tr>
								<td>
										<pre>
												<code class="section">
														<font face="Lucida Console">javac ChangeCaseConstants.java
javac ChangeCasePortlet.java
</font>
												</code>
										</pre>
								</td>
						</tr>
				</tbody>
		</table>
		<br />
		<p>接着需要为 WAR 文件创建所需要的文件夹结构，WAR 文件是归档文件，通过它把 portlet 部署到 portlet 容器。把刚才编译的两个类放在 classes\com\ibm\changecase 目录中。</p>
		<p>为了构建 WAR 文件，需要以下的目录结构，如清单 7 所示：</p>
		<br />
		<a name="IDAVZQGD">
				<b>清单 7. 用于部署的目录结构</b>
		</a>
		<br />
		<table cellspacing="0" cellpadding="5" width="70%" bgcolor="#eeeeee" border="1">
				<tbody>
						<tr>
								<td>
										<pre>
												<code class="section">
														<font face="Lucida Console">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
</font>
												</code>
										</pre>
								</td>
						</tr>
				</tbody>
		</table>
		<br />
		<p>注意，清单 7 引入了 4 个我们还没有讨论过的文件： </p>
		<ul>
				<li>
						<b>portlet.tld</b>：这是 portlet 标记库。如果回想一下，您曾经用 <code>&lt;portlet:defineObjects /&gt;</code> 之类的引用在整个 JSP 中都用到过 portlet 标记库。portlet 标记库在 Apache-SVN 代码库中可以得到（参见 <a href="http://www-128.ibm.com/developerworks/cn/java/j-pluto/#resources"><font color="#996699">参考资料</font></a>）。 <br /><br /></li>
				<li>
						<b>MANIFEST.MF</b>：因为这里不存在外部依赖，所以这个清单文件除了 <i>Manifest-Version: 1.0</i> 之外什么也不包含。<br /><br /></li>
				<li>
						<b>index.html</b>：如果由于某些原因上下文根被直接访问，则会显示 index.html。在 index.html 中可以有任何正确格式的 HTML。 <br /><br /></li>
				<li>
						<b>web.xml</b>（如清单 8 所示）：它定义包含单个 portlet 的 Web 应用程序。 </li>
		</ul>
		<br />
		<a name="IDA20QGD">
				<b>清单 8. web.xml</b>
		</a>
		<br />
		<table cellspacing="0" cellpadding="5" width="70%" bgcolor="#eeeeee" border="1">
				<tbody>
						<tr>
								<td>
										<pre>
												<code class="section">
														<font face="Lucida Console">&lt;?xml version="1.0" encoding="UTF-8"?&gt;
&lt;!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN" 
   "http://java.sun.com/dtd/web-app_2_3.dtd"&gt;
&lt;web-app id="WebApp_ID"&gt;
   &lt;display-name&gt;CasePortlet&lt;/display-name&gt;
   &lt;welcome-file-list&gt;
      &lt;welcome-file&gt;index.html&lt;/welcome-file&gt;
   &lt;/welcome-file-list&gt;
   &lt;taglib&gt;
      &lt;taglib-uri&gt;http://java.sun.com/portlet&lt;/taglib-uri&gt;
      &lt;taglib-location&gt;tld/portlet.tld&lt;/taglib-location&gt;
   &lt;/taglib&gt;
   &lt;taglib id="PortletTLD"&gt;
      &lt;taglib-uri&gt;http://java.sun.com/portlet&lt;/taglib-uri&gt;
      &lt;taglib-location&gt;/WEB-INF/tld/std-portlet.tld&lt;/taglib-location&gt;
   &lt;/taglib&gt;
&lt;/web-app&gt;
</font>
												</code>
										</pre>
								</td>
						</tr>
				</tbody>
		</table>
		<br />
		<p>一旦生成了 MANIFEST.MF、portlet.tld、web.xml 和 index.html，就可以使用 JAR 实用工具将清单 7 所示的结构归档到一个 WAR 文件中：</p>
		<table cellspacing="0" cellpadding="5" width="70%" bgcolor="#eeeeee" border="1">
				<tbody>
						<tr>
								<td>
										<pre>
												<code class="section">
														<font face="Lucida Console">C:\temp&gt;jar -cvf changeCase.war
</font>
												</code>
										</pre>
								</td>
						</tr>
				</tbody>
		</table>
		<br />
		<p>结果是一个叫做 changeCase.war 文件，用于部署到 JSR 168 兼容的门户。 </p>
		<br />
		<table cellspacing="0" cellpadding="0" width="70%" border="0">
				<tbody>
						<tr>
								<td>
										<img height="1" alt="" src="http://www.ibm.com/i/v14/rules/blue_rule.gif" width="70%" />
										<br />
										<img height="6" alt="" src="http://www.ibm.com/i/c.gif" width="8" border="0" />
								</td>
						</tr>
				</tbody>
		</table>
		<table class="no-print" cellspacing="0" cellpadding="0" align="right">
				<tbody>
						<tr align="right">
								<td>
										<img height="4" alt="" src="http://www.ibm.com/i/c.gif" width="70%" />
										<br />
										<table cellspacing="0" cellpadding="0" border="0">
												<tbody>
														<tr>
																<td valign="center">
																		<img height="16" alt="" src="http://www.ibm.com/i/v14/icons/u_bold.gif" width="16" border="0" />
																		<br />
																</td>
																<td valign="top" align="right">
																		<a class="fbox" href="http://www-128.ibm.com/developerworks/cn/java/j-pluto/#main">
																				<b>
																						<font color="#996699">回页首</font>
																				</b>
																		</a>
																</td>
														</tr>
												</tbody>
										</table>
								</td>
						</tr>
				</tbody>
		</table>
		<br />
		<br />
		<p>
				<a name="IDAI1QGD">
						<span class="atitle">
								<font face="Arial" size="4">确保 portlet 是 JSR 168 兼容的</font>
						</span>
				</a>
		</p>
		<p>现在使用 Apache Pluto 来查明 portlet 是否能通过 JSR168 兼容性的最终测试。</p>
		<p>确保 Apache Pluto 启动并运行，然后导航到 Pluto 主页（http://localhost:8080/pluto/portal）。单击侧栏上的 <b>Admin</b>。应该看到 Deploy War portlet 显示在管理页面上，如图 4 所示。单击 <b>Browse</b> 并导航到在前一节中放置在一起的 changeCase.war 文件的位置，然后单击 <b>Submit</b>。</p>
		<br />
		<a name="fig4">
				<b>图 4. Pluto 的 Deploy War portlet</b>
		</a>
		<br />
		<img height="428" alt="" src="http://www-128.ibm.com/developerworks/cn/java/j-pluto/deploywar.jpg" width="572" />
		<br />
		<p>现在必须为 portlet 应用程序输入布局信息 —— 一个非常不重要的任务，因为在 portlet 应用程序中只有一个 portlet。正如在图 5 中可以看到的，您告知 Pluto portlet 有一行和一列，然后单击 <b>Submit</b> 向服务器提交此选择：</p>
		<br />
		<a name="fig5">
				<b>图 5.为 portlet 应用程序输入页面布局信息</b>
		</a>
		<br />
		<img height="317" alt="" src="http://www-128.ibm.com/developerworks/cn/java/j-pluto/enterlayoutinfo.jpg" width="572" />
		<br />
		<p>接下来，必须定义 portlet 出现在 portlet 应用程序页面布局的何处。通过把 portlet 应用程序中的所有 portlet 映射到刚才定义的行和列来完成此任务。因为只有一个 portlet 需要部署并且您先前选择了一行和一列的页面布局，所以在该位置输入 ChangeCase portlet 并单击 <b>Submit</b>，如图 6 所示：</p>
		<br />
		<a name="fig6">
				<b>图 6. 映射 portlet 的位置</b>
		</a>
		<br />
		<img height="318" alt="" src="http://www-128.ibm.com/developerworks/cn/java/j-pluto/submitlayout.jpg" width="572" />
		<br />
		<p>为了部署 portlet，您可以选择重新启动 Pluto 或者<i>热部署</i> 包含 portlet 的 portlet 应用程序，如图 7 所示： </p>
		<br />
		<a name="fig7">
				<b>图 7. 热部署 portlet</b>
		</a>
		<br />
		<img height="318" alt="" src="http://www-128.ibm.com/developerworks/cn/java/j-pluto/hotdeploy.jpg" width="572" />
		<br />
		<p>一个具有 portlet 应用程序名称（<b>Change Case</b>）的链接出现在侧栏。单击该超链接，现在将看到 portlet 应用程序，其中包含 portlet，如图 8 所示。这时应该与 Change Case portlet 交互并确保它的功能与预期的一样。如果与预期的一样，您就可以确定此 portlet 与 JSR 168 兼容。</p>
		<br />
		<a name="fig8">
				<b>图 8. 部署到 Pluto 的 Change Case portlet </b>
		</a>
		<br />
		<img height="324" alt="" src="http://www-128.ibm.com/developerworks/cn/java/j-pluto/plutoportlet.jpg" width="572" />
		<br />
		<p>Change Case Portlet 将能够运行在任何支持 JSR 168 portlet 标准的 Portlet 容器中。 </p>
		<br />
		<table cellspacing="0" cellpadding="0" width="70%" border="0">
				<tbody>
						<tr>
								<td>
										<img height="1" alt="" src="http://www.ibm.com/i/v14/rules/blue_rule.gif" width="70%" />
										<br />
										<img height="6" alt="" src="http://www.ibm.com/i/c.gif" width="8" border="0" />
								</td>
						</tr>
				</tbody>
		</table>
		<table class="no-print" cellspacing="0" cellpadding="0" align="right">
				<tbody>
						<tr align="right">
								<td>
										<img height="4" alt="" src="http://www.ibm.com/i/c.gif" width="70%" />
										<br />
										<table cellspacing="0" cellpadding="0" border="0">
												<tbody>
														<tr>
																<td valign="center">
																		<img height="16" alt="" src="http://www.ibm.com/i/v14/icons/u_bold.gif" width="16" border="0" />
																		<br />
																</td>
																<td valign="top" align="right">
																		<a class="fbox" href="http://www-128.ibm.com/developerworks/cn/java/j-pluto/#main">
																				<b>
																						<font color="#996699">回页首</font>
																				</b>
																		</a>
																</td>
														</tr>
												</tbody>
										</table>
								</td>
						</tr>
				</tbody>
		</table>
		<br />
		<br />
		<p>
				<a name="IDA43QGD">
						<span class="atitle">
								<font face="Arial" size="4">结束语</font>
						</span>
				</a>
		</p>
		<table cellspacing="0" cellpadding="0" width="40%" align="right" border="0">
				<tbody>
						<tr>
								<td width="10">
										<font face="Arial" size="4">
												<img height="1" alt="" src="http://www.ibm.com/i/c.gif" width="10" />
										</font>
								</td>
								<td>
										<table cellspacing="0" cellpadding="5" width="70%" border="1">
												<tbody>
														<tr>
																<td bgcolor="#eeeeee">
																		<a name="IDAF4QGD">
																				<b>我可以在生产环境中使用 Pluto 吗？</b>
																		</a>
																		<br />
																		<p>Apache Pluto 只适合作为 JSR 168 兼容性的测试平台，不推荐在生产环境中使用。对于生产来说，您应该考虑使用更加可伸缩的容器。您可以考虑使用 Apache Software Foundation 的名为 Jetspeed 的开放源码 portlet 容器（参见 <a href="http://www-128.ibm.com/developerworks/cn/java/j-pluto/#resources"><font color="#996699">参考资料</font></a>）。IBM 的 WebSphere Portal Server Version 5.1 也是一个支持 JSR 168 标准的商业解决方案（参见 <a href="http://www-128.ibm.com/developerworks/cn/java/j-pluto/#resources"><font color="#996699">参考资料</font></a>）。 </p>
																</td>
														</tr>
												</tbody>
										</table>
								</td>
						</tr>
				</tbody>
		</table>
		<p>Apache Pluto 使 portlet 开发人员能够确定他们的 portlet 能够运行在任何 JSR 168 兼容的 portlet 容器中。大多数 portlet 容器（包括 WebSphere Portal Server）都包括 Portlet 规范未提及的扩展。例如，IBM WebSphere Portal Server 提供非标准的一点即动（click-to-action）扩展（即协作 portlet）。是否使用扩展由使用 portal 技术的企业来决定。作为开发人员，您应该牢记的是支持这种技术会损害 portlet 的可移植性 —— 但是有时这么做能满足业务需要。Apache Pluto 使那些使用 portlet 的组织能够知道他们偏离了 Portlet 规范有多远，并决定是否采取一些措施来调整那些 portlet 符合标准。</p>
		<p>
				<a name="IDAV4QGD">
						<span class="smalltitle">
								<strong>
										<font face="Arial">展望未来：JSR 286</font>
								</strong>
						</span>
				</a>
		</p>
		<p>JSR 168 在走向使 portal 领域有序的过程经过了很长的路。但是，portlet 的标准化工作并没有停止。当写作本文的时候，Java Portlet API version 2.0 规范 (JSR 286) 仍旧在开发中，打算把对 J2EE 1.4 的支持引入到 portlet 规范中（参见 <a href="http://www-128.ibm.com/developerworks/cn/java/j-pluto/#resources"><font color="#996699">参考资料</font></a>）。许多曾由供应商利用其自有实现通过非标准方式处理的 Portlet 技术（提一下其中的两个，portlet 过滤器和形式化的 portlet 间通信）现将采纳 2.0 规范。Apache Pluto 的将来版本将充当 JSR 286 规范的参考实现。当 JSR 286 成为事实上的 portlet 标准时，您将仍旧能够使用 Pluto 测试兼容性。</p>
		<p>在我们写作本文时，还不能得到 Pluto 1.1 的 alpha 版本。Pluto 1.1 将具有一个新的容器架构，并包含一些使 portlet 开发更容易的更改。但是，Pluto 1.0.1 仍然是一个很好的用于验证 portlet 是否 JSR 168 兼容的工具。</p>
		<br />
		<table cellspacing="0" cellpadding="0" width="70%" border="0">
				<tbody>
						<tr>
								<td>
										<img height="1" alt="" src="http://www.ibm.com/i/v14/rules/blue_rule.gif" width="70%" />
										<br />
										<img height="6" alt="" src="http://www.ibm.com/i/c.gif" width="8" border="0" />
								</td>
						</tr>
				</tbody>
		</table>
		<table class="no-print" cellspacing="0" cellpadding="0" align="right">
				<tbody>
						<tr align="right">
								<td>
										<img height="4" alt="" src="http://www.ibm.com/i/c.gif" width="70%" />
										<br />
										<table cellspacing="0" cellpadding="0" border="0">
												<tbody>
														<tr>
																<td valign="center">
																		<img height="16" alt="" src="http://www.ibm.com/i/v14/icons/u_bold.gif" width="16" border="0" />
																		<br />
																</td>
																<td valign="top" align="right">
																		<a class="fbox" href="http://www-128.ibm.com/developerworks/cn/java/j-pluto/#main">
																				<b>
																						<font color="#996699">回页首</font>
																				</b>
																		</a>
																</td>
														</tr>
												</tbody>
										</table>
								</td>
						</tr>
				</tbody>
		</table>
		<br />
		<br />
		<p>
				<a name="resources">
						<span class="atitle">
								<font face="Arial" size="4">参考资料 </font>
						</span>
				</a>
		</p>
		<b>学习</b>
		<br />
		<ul>
				<li>您可以参阅本文在 developerWorks 全球站点上的 <a href="http://www.ibm.com/developerworks/java/library/j-pluto/" target="_blank"><font color="#5c81a7">英文原文</font></a> 。 <br /><br /></li>
				<li>“<a href="http://websphere.sys-con.com/read/44720.htm"><font color="#5c81a7">JSR 168 - An Introduction to the Portlet Specification</font></a>”：更多地了解 JSR 168。 <br /><br /></li>
				<li>
						<a href="http://portals.apache.org/pluto/">
								<font color="#5c81a7">Apache Pluto</font>
						</a>：访问 Pluto Web 站点。 <br /><br /></li>
				<li>
						<a href="http://www.jcp.org/en/jsr/detail?id=168">
								<font color="#5c81a7">JSR 168: Portlet Specification</font>
						</a>和 <a href="http://www.jcp.org/en/jsr/detail?id=286"><font color="#5c81a7">SR 286: Portlet Specification 2.0</font></a>：由 Java Community Process 开发和维护的 portlet 规范。 <br /><br /></li>
				<li>“<a href="http://www.ibm.com/developerworks/cn/websphere/library/techarticles/0602_hepper/0602_hepper.html"><font color="#5c81a7">使用 WebSphere Portal V5.1 在 IBM Portlet 和 JSR 168 Portlet 间共享信息</font></a>”（Stefan Hepper 和 Jerry Zheng，developerWorks，2006 年 2 月）：编写一个自定义的 portlet 服务以允许 IBM portlet 和 JSR 168 portlet 共享作为属性的信息。 <br /><br /></li>
				<li>“<a href="http://www.ibm.com/developerworks/cn/websphere/library/techarticles/0508_hepper/0508_hepper.html"><font color="#5c81a7">使用 WebSphere Portal V5.1 在 JSR 168 Portlet 中缓存数据</font></a>”（Stefan Hepper 和 Jerry Zheng，developerWorks，2005 年 8 月）：学习如何在 JSR 168 portlet 中缓存数据以避免不必要的后端请求。 <br /><br /></li>
				<li>“<a href="http://www-128.ibm.com/developerworks/cn/websphere/library/techarticles/0412_paeffgen/0412_paeffgen.html"><font color="#5c81a7">将 WorldClock portlet 从 IBM Portlet API 转换到 JSR 168 portlet API</font></a>”（Franziska Paeffgen 和 Birga Rick，developerWorks，2004 年 12 月）：了解如何将最为 IBM WebSphere Portal 专有 Portlet API 开发的 portlet 转换为使用 JSR 168 标准 portlet API 的 portlet。 <br /><br /></li>
				<li>
						<a href="http://httpd.apache.org/dev/verification.html">
								<font color="#5c81a7">Verifying Apache HTTP Server Releases</font>
						</a>：有关验证来自 Apache Web 站点的下载文件的更多信息。 <br /><br /></li>
				<li>
						<a href="http://www.ibm.com/developerworks/cn/java/">
								<font color="#996699">Java 技术专区</font>
						</a>：关于 Java 编程的各个方面的数百篇文章。 <br /><br /></li>
		</ul>
		<br />
		<b>获得产品和技术</b>
		<br />
		<ul>
				<li>
						<a href="http://portals.apache.org/pluto/download.html">
								<font color="#5c81a7">Apache Pluto</font>
						</a>：下载 Pluto。 <br /><br /></li>
				<li>
						<a href="http://svn.apache.org/viewcvs.cgi/portals/pluto/branches/pluto-1.0.2/container/src/tld/">
								<font color="#5c81a7">portlet 标记库</font>
						</a>：从 Apache-SVN 代码库下载 portlet 标记。 <br /><br /></li>
				<li>
						<a href="http://portals.apache.org/jetspeed-1/">
								<font color="#5c81a7">Apache Jetspeed</font>
						</a>：一个开放源码的 portlet 容器。 <br /><br /></li>
				<li>
						<a href="http://java.sun.com/j2se/1.5.0/download.jsp">
								<font color="#996699">Java 5.0 SDK</font>
						</a>：Pluto 需要 Java 5。 <br /><br /></li>
				<li>
						<a href="http://www-306.ibm.com/software/genservers/portal/">
								<font color="#5c81a7">IBM 的 WebSphere Portal Server Version 5.1</font>
						</a>：支持 JSR 168 标准的商业解决方案。<br /><br /></li>
				<li>
						<a href="http://www.gnupg.org/">
								<font color="#5c81a7">GnuPG</font>
						</a>：一个免费的 PGP 工具。 </li>
		</ul>
<img src ="http://www.blogjava.net/kingwell/aggbug/48560.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/kingwell/" target="_blank">KingWell</a> 2006-05-28 09:03 <a href="http://www.blogjava.net/kingwell/articles/48560.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>