1.1  概念与前提 

要读懂这节内容,并学会使用状态模式开发Portlet,你必须具备这里提到的几种设计思路,并具备基本的Java开发技能。这里我们选用的开发工具是 IBM Rational Application Developer以及Portlet Toolkit,你需要熟悉该工具,并懂得如何创建PortletPortlet所需的包、类、页面,以及运行环境所需的.jar

1.1.1  状态模式应用于Portlet

StateManagerPortlet是主要的Portlet并且是Portlet无关的。它用作分派器以支持驻留着Portlet代码的操作和状态类特定于Portlet的控制器代码就存在于该类中。扩展Action抽象类的类实现了actionPerformed方法该类执行实现特定的操作请求行为所必需的任何控制器功能。

实现状态接口的类将实现一个performView方法该方法是由 StateManagerPortlet service 方法调用的。该方法还包含通常驻留在这些方法中的代码。同样这段代码也是特定于它所驻留的状态类的因此就避免了确定请求的操作带来的所有额外的控制逻辑混乱。

应用状态模式会使实现变得简洁。而且当在Portlet的各模式之间切换时状态总是被记住的。有了这种模式,你就可以轻松地确定想要何时以及在何处从源检索数据还可以确定何时应该从高速缓存检索数据。由于在门户页面刷新时不调用actionPerformed方法所以可以将数据访问代码放在操作状态中并在那里高速缓存它们。状态类可以使用高速缓存中的数据以避免刷新门户页面时多次存取数据。

1.1.2  Portlet为什么使用状态模式

考虑简单的基于 MVC Portlet它从远程机器上将包含一个产品下载配置参数列表的XML文件拷贝到本地(Portal系统所在的主机),检索各项参数,并把列表呈现给用户。在用户选择了某一项后将显示详细的视图该视图显示的是被选项的详细信息。这个详细视图可能涉及向数据库再次发出请求。有编辑权限的用户可以进入到Portlet的编辑模式,查看并修改XML文件的内容,保存后如果发现XML文件已经做了修改,则传回远程机器;否则,仍将文件包存在Portal本地,以免占用系统资源。

第一步控制器必须调用业务对象来创建合适的Bean,该Bean被传递给JSP以用于主视图中的显示。第二步控制器在用户的请求中检索被选项的指示器然后调用业务对象来创建合适的Bean,该Bean被传递给不同的 JSP以用于详细视图中的显示。

MVC实现中视图组件显然是不同的这两种视图需要有两种不同的JSP可能需要访问不同的业务模型组件来生成每个请求所需的Bean。控制器函数需要知道:

— 调用哪些业务方法

— 生成哪些Bean

— 把这些请求对象上的Bean放在哪里

— 如何调用合适的JSP

这就是代码变得复杂的地方。如果使用Servlet编程那么可能选择把它们实现为不同的Servlet以使每个合适的Servlet 类的服务方法自然地分隔每个请求的控制器函数。如果更喜欢使用分派器方式而不是不同的Servlet实现那么必须使用框架例如Struts来实现类似的MVC设计。

这是复杂的任务因为不能选择使用多个Portlet 类来实现一个 Portlet不能直接处理 Portlet类。相同的Portlet的服务方法用来处理返回给Portlet的所有HTTP请求因此需要实现控制代码类具有如下功能。

— 确定正在请求哪个操作

— 需要进行哪些处理

— 使Portlet 处于哪状态

— 显示什么内容返回给用户

1.2  需求分析

1.2.1  Portlet功能需求

我们在Linux主机 test.cn.ibm.com上运行着一个自动下载的程序,要下载的产品列表及各产品的参数保存在 /home/isc/downLoadConfig/下,文件名为AutodownConfig.xml。我们在Windows 2000 Server 主机Netecauto01上运行着IBM WebSphere Portal 5.1,普通用户只能查看产品列表及配置权限,当该用户要查看配置信息时,Portlet 能从服务器上将文件AutodownConfig.xml拷贝到本地服务器,并读出XML文件中的内容,显示在列表中。具有管理权限的用户还有修改各配置信息的权限,能对产品配置信息的各项参数进行修改。修改完成后,要使该配置有效,必须将该XML文件回传到pvcent07的存放目录。

AutoDownLoadConfig Portlet 维护一个自动下载的产品配置列表在编辑模式下用户可以浏览下载产品列表查看一个选定的下载产品的详细信息也可以修改一个产品的配置信息。在配置模式下用户可以设置数据访问信息。虽然可用的数据源提供了包括配置模式在内的完整的实现但为了满足设计目的,我们只需注意查看和编辑模式的实现即可自动下载Portlet状态模式示意图如图1-1所示。

基于事件侦听与状态模式转换的Portlet开发

1-1  自动下载Portlet状态模式示意图

1.2.2  基于MVC模型的角度架构逻辑

1.以基于MVC架构的思路整理Portlet的逻辑

从可视的角度看,图1-1所示的场景功能的实现至少需要如下页面

— 主视图页面Main View Page显示所有正在下载的产品列表和用来选择一个产品以获取更多详细信息的选项

— 详细信息视图页面Detail View Page显示被选择产品的详细配置信息

— 主编辑页面Main Edit Page显示用户有权限编辑的产品列表和用于修改更多信息的选项

— 修改条目页面Modify Entry Page显示相似的表单其中插入了现有的数据用于修改,包括修改单项参数,以及给某一参数增删条目列表。 

在这种情况下用户可以从主编辑页面中选择需编辑产品条目。修改后,没有确认页面或成功执行的页面。进行条目修改处理并刷新主编辑页面若出错则显示适当的消息但在正常处理时没有与该操作关联的视图。

如何来改进这个实现呢?首先请记住这个应用程序表示一组应用程序操作和状态;其次操作是实现操作接口的类这个类实际完成某个应用程序任务或操作处理。这就是目前存在于 actionListener 类的 actionPerformed 方法中的应用程序代码的一部分只有这部分特定于单个操作事件。

状态是实现状态接口的类这个类表示由于应用了操作而产生的 Portlet 的效果。一般来说这个类有可视组件。

2Portlet所包含的内容

根据以上分析,我们将有下面这些操作 

— 所有产品配置信息的主列表视图

— 显示选定产品的配置详细信息视图

— 显示所有可编辑产品的编辑视图列表

— 显示视图来修改一个产品的配置信息。

— 为产品添加一个可选的下载项或邮件。

— 为产品删除一个可选的下载项或邮件。

执行这些操作会产生下列状态之一

— 主视图

— 详细信息视图

— 主编辑视图

— 添加下载产品视图

— 修改下载产品视图

从可视角度看下载产品列表 Portlet 的实现包括如下视图页面)。

1主视图Main View显示下载产品列表并带有选项来选择下载产品以查看更多的信息。

2详细信息视图Detail View显示选定的下载产品的详细信息。

3主编辑视图Main Edit View显示下载产品列表并带有选项来添加、删除和修改下载产品信息。

4添加下载产品视图Add Contact View显示表单视图来输入新下载产品的信息。

5修改下载产品视图Modify Contact View显示相似的表单视图来添加现有的下载产品的元素数据以供修改。

1.3  Portlet详细设计

1.3.1  程序流程设计

下面以图示的方式来介绍程序的数据流转。

基于事件侦听与状态模式转换的Portlet开发 在显示模式下,Portlet会从远程pvcent07.cn.ibm.com拷回XML文件,读出并显示所有正在下载的产品列表。单击列表中的任意项,将显示该项的详细视图。我们先来看产品下载列表,如图1-2所示。

基于事件侦听与状态模式转换的Portlet开发

1-2  产品下载列表

单击任意产品的链接后,将显示该产品的具体配置参数,如图1-3所示。

基于事件侦听与状态模式转换的Portlet开发

1-3  产品的具体配置参数

在编辑模式下,首先显示的是用户有权限编辑的产品配置列表,如图1-4所示。

基于事件侦听与状态模式转换的Portlet开发

1-4  用户有权限编辑的产品配置列表

单击任意产品的链接,进入到该产品的编辑界面,如图1-5所示


基于事件侦听与状态模式转换的Portlet开发

1-5  产品的编辑界面

用户可以为该产品添加CD介质,或者添加一个E-mail,如图1-6所示。


基于事件侦听与状态模式转换的Portlet开发

1-6  为产品添加要下载的CD介质

当然,用户也可以删除要下载的CD介质或者E-mail,如图1-7所示。

基于事件侦听与状态模式转换的Portlet开发

1-7  删除要下载的CD介质

用户可以修改任意参数,然后单击Save To XML”按钮,Portlet将把这些参数保存到XML文件,并传回到pvcent机器,如图1-8所示。

基于事件侦听与状态模式转换的Portlet开发

1-8  将修改保存到Portlet配置文件

 确认修改保存成功,如图1-9 所示。


基于事件侦听与状态模式转换的Portlet开发

1-9  确认修改保存成功

1.3.2  Actions States总体设计

1StateManagerPortlet

StateManagerPortlet是主要的PortletPortlet无关的一般包括所有特定于 Portlet 的代码。该类被用作分派器以支持驻留着Portlet 代码的操作和状态类。StateManagerPortlet实现了actionPerformeddoViewdoEditdoHelpdoConfigure方法。

actionPerformed方法只是获取操作类的当前实例然后分派到它的actionPerformed方法。类似地do方法获取当前的状态对象然后分派到它的perform方法。所以StateManagerPortlet 不需要知道当前Portlet实现的任何细节也没有大量用来确定下一步处理的if和检查。只要熟悉状态与操作之间的流程处理就能正确地进行而不必编写太多的、多余的控制逻辑代码。

2ActionClassManager

WebSphere PortalActionClassManager方法把Action类实例添加到已弃用的PortelURI中。这个API是有用的因为可以从PortletEvent对象中检索Action子类实例并把该实例作为状态转换的一部分分派到它的actionPerformed方法中。推荐的API将使用字符串而不是Action来添加到PortletURI并且从Portlet Event 中进行检索。ActionClassManager类提供了从给定的字符串到Action 类的实例映射。

— Action

实现这个接口的类将实现actionPerformed方法该方法执行任何操作以实现操作请求所需的函数。但是实现的函数特定于正被调用的操作事件。某个操作类的个别的actionPerformed方法仅包含该操作的代码该方法还为进一步的处理设置当前状态。在这个流程中操作被调用后它进行特定于函数的工作然后为下一次转换设置状态。

— InitialStateManager

该类为支持的每个 Portlet方式提供初始状态。

— State

一般来说Stateperform方法将调用JSP来显示它的结果。用户接口可能让用户来设置Portlet中的其他操作。JSP使操作类与页面上的每个操作关联。在用户调用其中的一个操作时StateManagerPortletactionPerformed方法将调用合适的操作类实例接着发生了状态转换。状态类并不负责状态管理和转换。

实现这个接口的类需实现perform方法该方法可被StateManagerPortletdo方法调用它包含一般驻留在这些方法中的代码。同样这些代码特定于它们所在类的状态从而降低了复杂性。

1.3.3  代码类设计、操作类清单

我们所创建的各个类的功能分别简单介绍如下。

基于事件侦听与状态模式转换的Portlet开发

1State类功能逻辑介绍

子类1ActionClassManager

ActionClassManager负责返回一个操作子类实例该实例给出一个类标识符这个标识符是通过 addAction字符串方法添加到 PortletURI中的。我们遵循如下约定使类标识符为全限定类名这样我们就能够很容易地创建一个类的实例。然而我们可以通过单独处理操作子类实例来避免不必要的对象创建然后需要ActionClassManager为所引用的操作子类返回单一的实例。

子类2ActionPerformed

抽象的操作类定义了两个抽象的方法因此它的子类必须实现 actionPerformed 方法和 setState 方法。当 StateManagerPortlet 类从它的 actionPerformed 方法分派处理时操作子类的 actionPerformed 方法得到调用。

setState方法也可由 StateManagerPortlet调用确保操作子类的实现在该用户请求的操作处理完成之后设置下一个状态。操作类实现它自己的setState方法子类必须调用该方法来真正设置下一个状态。这确保了操作类和状态类知道在哪类设置和恢复下一个状态而不需要子类知道这些机制。这些状态跨HTTP请求并维持在每Portlet模式下。所以当用户改变模式时控制返回到最近一次访问的状态。

子类3MainViewAction操作类

MainViewAction 类并不需要任何特定的操作处理。事实上我们需要将下载产品列表显示在主视图上。我们能够实现在actionPerformed方法中创建恰当的下载产品列表Bean的代码将该代码设置在会话或请求对象里然后将下一个状态设置到MainViewState里。 performView implementation继承MainViewAction操作类,能够简单地调用JSP并提交来自会话或请求的Bean里的列表内容。然而我们必须注意门户页面更新以防更新时调用的是PortletMainViewStateperformView方法,而非MainViewActionactionPerformed方法。所以我们不能只是将Bean放置于请求对象里而没有让 performView 方法重新创建该Bean并将新的Bean放在该请求对象里。我们可以在会话里再次使用该Bean。但如果那样做的话数据将会过时。如果我们在编辑模式下做了变动就需要通知该变化并在 State 方法里刷新数据Bean。为了简化这种处理我们会只为 MainViewState State 方法里得到数据 Bean

所以 MainViewState 类里actionPerformed方法并没有另外处理只是简单设置了MainViewState而已。

子类4StateManagerPortlet

actionPerformed 完成处理时控制返回到门户容器以便其他的侦听器通知处理程序执行。然后门户容器通过调用 StateManagerPortlet service 方法继续 Portlet 请求处理。

StateManagerPortlet service 方法首先试图检索以前执行的操作类设置的状态类如果没有发现状态类引用例如最初的 Portlet 调用),那么就使用一个助手类 InitialStateManager 来为每Portlet 模式确定初始的状态类。InitialStateManager 有一个一的方法叫做 getInitialState它根据 Portlet 的当前模式返回状态对象的一个实例。对于下载产品列表 Portlet这个类将为视图模式返回 MainViewState 的一个实例。

State接口有一个一的方法 performView所有的状态类都必须实现它。StateManagerPortlet service 方法调用这个方法。

子类5MainViewState

MainViewState performView 方法负责在 Contacts Bean 的列表表单中获取下载产品列表下载产品列表保存在数据库里然后传递到 JSP 以便在主视图中呈现出来。

子类6MainViewState

这个子类允许用户单击一个下载产品条目然后显示该下载产品的详细信息视图。

用于这个标记的 href 使用来自Portlet标记库中的createURI标记。该标记在URIAction中获得参数URIAction被我们设置为操作类中用于用户单击操作的事件处理方法的名称。

子类7actionPerformed

actionPerformed类用来查看JSP上显示的主要清单。用户可以从主视图页面选择特定的下载产品条目来获得详细信息。我们还添加了一个锚标记将下载产品条目的名称作为可点击的链接显示出来击时StateManagerPortletactionPerformed 方法被DetailViewAction 类调用。

actionPerformed方法得到所选择的下载产品条目的对象id并调用持久性类的代理为该id获取实例化的下载产品对象。这个下载产品对象放在State类的会话中用来呈现详细信息视图。如果该页面由于门户页面刷新而得以刷新那么该Bean就将在会话中可用既然该对象只会通过用户使用 Portlet 来获得更新我们就不必担心数据过时了。

门户页面刷新的另一个关键之处是表单数据没有被重新初始化。如果我们试图获得所选下载产品的对象id作为状态类的请求参数它在门户页面刷新时将不可用。因此为了使 Portlet 能正常运行必须在刚开始时就检索数据元素然后将其存储在某个地方这样在随后的页面刷新时它才可以被引用。由于 actionPerformed 方法曾被调用所以这就是存放这段代码的好地方。

actionPerformed方法中保留后端数据访问可以确保我们在页面刷新时对于同一数据不需要多次访问数据库。当然返回到数据源进行数据刷新的时间和频率取决于Portlet的需求以及数据本身的因素。在这种情况下数据不是动态的 Portlet 页面被刷新时应该对其进行高速缓存。

DetailViewState 被设置为这个Portlet的下一个状态对于Portlet其中的处理将继续。

子类8DetailViewState

DetailViewState 简单地调用JSP来呈现详细信息视图JSP 从会话中获取下载产品 Bean。在UI交互界面中当用户单击OK按钮时处理返回到主视图继续进行。MainViewActionactionPerformed 方法通过删除我们在 DetailViewAction 类中设置的下载产品对象 id 来简单地删除会话数据。

子类9ViewProductAction

ViewProductAction类用来显示下载产品详细信息视图JSP页面。流逻辑以一种组织良好的方式进行,你不需要在Portlet使用冗的控制代码。Portlet 的编辑和配置模式也以同样的方法实现。

2完成Portlet实现

该应用程序的其余部分仍遵循以上所述的开发模式。编辑模式的处理控制逻辑流和视图模式的完全一样。我们实现一配置模式它允许用户指定数据源来保存下载产品数据。它将以同样的方式实现。配置模式只有一个视图来让用户访问数据源另外有两个类来检验数据源和保存数据源为配置数据。

下面是实现状态模式的基本步骤。

  所执行的特定模式的初始状态类由 InitialStateManager 类提供。

状态类的 performView方法其调用是由 StateManagerPortlet 分派的进行任何必要的应用程序逻辑处理然后调用它的 JSP

通过PortletURI上的一个参数将每个用户的操作与在其中进行事件处理的操作子类的名称相关联。每个用户操作一般都指定一个不同的操作子类该子类实现一个单一的、特定的功能。

用户单击一个链接时操作类的 actionPerformed 方法被调用由于通过 StateManagerPortlet 分派而被再次调用。执行操作逻辑并设置适当的状态类以使处理继续进行。

当事件处理完成后StateManagerPortletservice方法被调用并再次分派给在Action事件处理阶段设置的状态类该状态类执行应用程序逻辑并调用它的 JSP 来呈现结果。

当用户浏览整个 Portlet 操作以这种方式继续。

3持久性代理

访问数据库中的持久性数据需要额外的 Portlet 组件。AbstractBroker 类提供一般的JDBC数据库访问功能。它能够用来获取数据库的DataSourceConnection它在高速缓存中缓存DataSource从而避免重复的、高代价的JNDI查找它也提供通用代码来执行 PreparedStatement并关闭ConnectionStatementResultSet

ContactListBroker 类继承了 AbstractBroker它实现特定于 Portlet 需要的数据访问方法 getContact 方法和 getContactList 方法用于保存删除一个列表中的条目。同时它还有检验表 Schema 的功能这样我们就可以检验用户在配置模式下指定的数据源。

4异常处理

我们已经为Portlet 实现了大量的异常类基本类AIMExceptionAIMWrapperExceptionAIMException 的子类。可以用 AIMWrapperException 封装其他抛出的异常以便在 StateManagerPortletservice 方法中高效地修改显示行为和管理异常处理。

AIMMessageException 是一个特殊的异常它允许在终止处理时向 Portlet 生成一条报告性消息或错误消息。例如可以抛出一个 AIMMessage 异常用一条消息指出用户必须先登录。

actionPerformed方法或setState方法中抛出的异常被捕获并且被延迟到 service 方法。管理延迟的方法是捕获这些方法中抛出的所有异常并将异常通常封装在一个AIMWrapperException放在请求对象上。当调用StateManagerPortletservice方法时它首先查找有没有延迟异常如果找到了就从此处重新抛出并处理这些异常。

因此所有的Portlet应用程序异常都是在 StateManagerPortletservice方法中处理的。如果发现了异常,则在以下两种情况中调用异常方法异常消息将在Portlet中被显示异常消息以及相关联的堆栈跟踪信息将被显示。将堆栈跟踪信息放在 Portlet 外有助于在开发时进行调试。由于不想向实际应用的用户显示这种级别的详细信息所以该行为是可配置的。这是在部署描述符里定义的 debugTrace参数。

5建立开发环境

如果使用WebSphere Studio来创建这个Portlet请确保下列JAR文件构建路径是可用的以便Portlet代码可以顺利编译。如果Studio中使用Portal Toolkit并创建Portlet应用项目那么类路径会自动创建。不管哪种情况,你都可以创建一个Web项目或Portlet应用项目然后导入下载中的WAR文件从而将这个Portlet应用程序载入Studio

SERVERJDK_50_PLUGINDIR/jre/lib/rt.jar

WAS_50_PLUGINDIR/lib/dynacache.jar

WAS_50_PLUGINDIR/lib/j2ee.jar

WAS_50_PLUGINDIR/lib/servletevent.jar

WAS_50_PLUGINDIR/lib/ivjejb35.jar

WAS_50_PLUGINDIR/lib/runtime.jar

WAS_50_PLUGINDIR/lib/ras.jar

WAS_50_PLUGINDIR/lib/naming.jar

WAS_50_PLUGINDIR/lib/utils.jar

WPS_V5_PLUGINDIR/portlet-api.jar

WPS_V5_PLUGINDIR/wpsportlets.jar

WPS_V5_PLUGINDIR/wps.jar

如果没有使用 Portal Toolkit或者Studio,那么可以在 <WAS_ROOT>/lib <WPS_ROOT>/shared/app 中找到这些文件。

Portlet部署到WebSphere Portal 环境中时所有必需的JAR文件都要同时打包进去可以不修改 Portal 中安装 Portlet WAR 文件。

1.3.5  RAD实现Portlet

针对入门者,我们以图示的方式,向大家介绍使用IBM提供的开发工具RADRational Application Developer)来创建、开发、调试、打包Portlet

原则上我是按照安装从始至终的次序来截图的,但为了使层次更清晰,我们还是分为以下7个步骤来分别介绍。

1.安装RAD,创建portlet

Windows 2003 Server系统的“控制面板”高级”选项中设置”按钮,在出现的对话框中选择数据执行保存面板,添加...按钮,把安装后的rationalsdp.exeenroll.exe 添加到列表中。

打开RAD,单击“新建”按钮,选择“项目”→“Portlet项目”,然后依次输入各项参数,包括Portlet的名称、包名、是否使用凭证保险库等。

参数                           

Portlet 名称                                   DownLoadConfig

Portlet 类型                                   基本Portlet

Web功能部件                使用Web图与JSP标记库

是否需要添加操作侦听实例              不需要

是否需要添加凭证保险库                 不需要

使用模式               显示模式、编辑模式、培植模式、帮助模式

单击“完成”按钮,Rational开始自动创建这个Portlet,创建完成后自动打开“DownLoadConfigView.jsp”文件,如图1-10所示。


基于事件侦听与状态模式转换的Portlet开发

1-10  RAD中开发Portle


2.创建并设计所需的操作类(Actions


创建一个Action包:com.ibm.csdl.portal.download.config.actions,在这个包里分别创建以下类,如图1-11所示。

基于事件侦听与状态模式转换的Portlet开发

1-11  创建的操作类

这些类实现了Portlet的所有操作,我们以“为产品配置删去一个CD或者E-mail”为例,看一下Action实现了哪些功能。

actionPerformed方法里,程序接收从editAProduct.jsp传过来的参数,也就是CDsEmails两个选择框传过来的值,看要删除的是一个CD还是一个E-mail,然后从产品配置对象里面将对应的CD或者E-mail删除,最后写回到XML文件中。

setState()方法里,程序实例化一个RemoveOneCDsOrEmailState,将逻辑交给State来处理。那么,State又如何流转呢?看下面的State类。

3.创建并开发所需的状态类 (States)

  创建一个State包:com.ibm.csdl.portal.download.config.actions,在这个包里分别创建以下类,如图1-12所示。

基于事件侦听与状态模式转换的Portlet开发

1-12  创建的状态类

这些类实现了Portlet的所有状态模式转换,我们以“为产品配置删去一个CD或者E-mail”为例,看一下State实现了哪些功能。

RemoveOneCDsOrEmailState.java代码清单如下:

基于事件侦听与状态模式转换的Portlet开发

State类里面只有两个方法,其中一个方法用于获得实例,我们就不管了;另一个方法是performView,它负责读出XML文件里的内容(现在已经是修改后的了),然后放入Session,调用并初始化一个新的指定的JSP文件。这个JSPSession里面取出数据,然后初始化。

4.创建并开发所需的数据结构(Data)以及Portlet

Data类主要定义了一些数据结构,用来存放XML文件中的数据,与Portlet的开发基本上无关。

Portlet类主要用来初始化一些数据,以及根据Portlet的状态调用相应的JSP页面。


nls下的资源文件与浏览器的多语言支持相关,可以根据客户端浏览器的设置,从相应的资源里取出静态描述文件Portlet.xml,然后在JSP文件中完成初始化的过程。

com.ibm.csdl.portal.download.config.utilities包主要处理一些异常(见图1-13),这里不再赘述。

基于事件侦听与状态模式转换的Portlet开发

1-13  com.ibm.csdl.portal.download.config.utilities中默认带有常见的异常处理逻辑

5.创建并开发所需的页面(Pages

根据上面的详细设计,我们需要创建一些页面,如图1-14所示。

基于事件侦听与状态模式转换的Portlet开发

1-14  创建的页面

这些页面的功能如下。

基于事件侦听与状态模式转换的Portlet开发

页面的显示逻辑略。我们以ViewAllTheProduct.jsp为例,看一下Rational是怎样给一个链接添加操作事件侦听的。

ViewAllTheProduct.jsp源代码如下:


基于事件侦听与状态模式转换的Portlet开发

其实很简单,用一个超链接就能添加该链接的操作事件侦听,代码如下:

基于事件侦听与状态模式转换的Portlet开发

其他的类似,这里不再赘述。

6.调试 Portlet

 假设在9.181.66.250上运行着一个Portal系统,超级管理员的用户名和密码都是admin,我们可以创建一个服务器用来测试Portlet,如图1-15所示。

基于事件侦听与状态模式转换的Portlet开发

1-15  RAD中创建Portal服务器用于调试Portlet

选择服务器的类型为WebSphere Portal,并输入相关参数。

右击项目名,选择“运行”→“在服务器上运行”,如图1-16所示。

基于事件侦听与状态模式转换的Portlet开发

1-16  选择直接在RAD中运行Portlet

 几分钟后,会在工作区出现浏览页面,这样就可以调试该Portlet了。

7.打包,生成产品

打包Portlet也非常简单,右击项目名,选择“导出”→“WAR文件”,再选择好存储位置就可以了,如图1-17所示。

基于事件侦听与状态模式转换的Portlet开发

1-17  Portlet导出为WAR包部署到Portal服务器

拿这个WAR包,就可以发布或者更新到Portal系统上使用了。

1.4  Portlet 开发指导原则和示例实现

Portlet 开发指导原则和示例实现可以Portlet API很好的理解。然而实现复杂的流程控制超出了 API 的范围。如果没有定义完善的方法来解决如何最好地实现控制逻辑这一问题,你就不能够创建这样的Portlet它们包含有专门定位用户请求目的的简单合理的 代码。

除了重复之外该代码使Portlet更难以读懂因为需要进入控制逻辑以获取Portlet正在做的实际工作。控制逻辑也容易出错因为它依赖于多方面情况比如,使用字符串匹配用来连接事件和侦听器侦听器操作和 Portlet 方法中的Action。为了解决控制逻辑的这些问题,你可以将应用程序看Portlet的操作和状态的集合然后通过一个定义完善的方法来进行状态转换这样就可以将Portlet应用程序中冗的控制逻辑代码删除。

开发人员也可以选择采用Struts框架来实现PortletStruts是一个Jakarta项目它提供一个非常流行的开放源代码框架来建立 Web 应用程序。使用附带了 Portal Struts Portlet FrameworkStruts框架写成的Portlet就可以在WebSphere Portal上运行。Struts提供了值得考虑的Web应用程序其功能远远超过页面导航它是进行Portlet开发的一个很好的选择。对Struts不熟悉或者希望更直接访问 Portlet API 的开发人员会从用于页面导航的状态转换实现中获益。这种模式和Struts框架一样使面向MVC设计的应用程序框架得以改进。