开发和部署一个作为 WebSphere Portal V5 Portlet 的 Struts 应用程序

本文描述并举例说明了如何利用 Jakarta Struts Framework(已并入 IBM Struts Portlet Framework)来开发和部署一个作为 Portlet 运行在 IBM WebSphere Portal V5 中的的应用程序。

引言
本文讨论了如何利用 Struts Portlet Framework 来实现一个为 IBM WebSphere Portal Version 5(以下称为 WebSphere Portal)编写的 Portlet。Struts 是一个  Apache Jakarta 项目,它为创建 Web 应用程序提供了一个非常流行的开放源码框架。WebSphere Portal V5.0 提供了 Struts Portlet Framework 来支持把 Struts 应用程序作为 Portlet 部署。Struts Portlet Framework 还支持 Struts 应用程序中的 Portal 模式和设备。

如果您阅读了前面我们描述利用状态模式来实现 Portlet 的文章,您将熟悉本文使用的示例应用程序。它遵循相同的设计原理,不过这里是使用 Struts 来进行开发和部署。这个应用程序维护一个特定于登录到 Portal 的用户的联系人列表(地址本条目)。联系人列表存储在数据库或内存中。用户可以个别地查看列表中的联系人以了解更详细的信息。Portlet 的编辑模式允许用户添加、删除或修改联系人信息。

本文的重点不在于开发一个 Struts Web 应用程序;而在于开发一个作为 Portlet 的 Struts 应用程序所需的的实现和配置。您可以了解到如何利用 Jakarta Struts Framework(已并入 IBM Struts Portlet Framework)来创建一个 Portlet。在  WebSphere Portal V5 中,Struts Portlet Framework 附带了 Jakarta Struts 1.1.0。

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

  • IBM WebSphere Portal Server Version 5.0
  • IBM WebSphere Application Server Version 5
  • 一个用于保存联系人条目的数据库(可选) 
  • IBM WebSphere Studio Version 5 (可选)

关于示例 Portlet 应用程序
示例应用程序实现了对一组持久性数据的 Create/Read/Update/Delete(CRUD) 操作。它维护了特定用户的联系人列表(例如简单的地址本)。这个应用程序允许用户个别地查看联系人条目或查看一个列表中的联系人条目。

从视觉的角度来看,联系人列表应用程序的实现包括如下视图(页面):

  • 登录视图(Login view)—— 显示用户登录的视图。
  • 主视图(Main view)—— 显示联系人列表并带有选项来选择联系人以查看更多的信息。
  • 详细视图(Detail view)—— 显示选定的联系人的详细信息。
  • 主编辑视图(Main edit view)—— 显示联系人列表并带有选项来添加、删除和修改联系人信息。
  • 添加联系人视图(Add contact view)—— 显示表单视图来输入新联系人的信息。
  • 修改联系人视图(Modify contact view)—— 显示表单视图来展示现有的联系人的元素数据并允许更新。

这个应用程序并未提供一个显式的页面来删除条目。取而代之的是,要删除一个条目,用户需要从主编辑页面选择一个联系人条目,然后进行条目删除处理并刷新主编辑页面。如果有错误发生,系统就会显示适当的消息。没有确认页面和成功执行页面。

1. 主视图
主视图

设计 Portlet 应用程序

前面关于利用状态模式实现 Portlet 的系列文章与下面的讨论是类似的,因为 Struts 实现和状态模式是基本相似的。

考虑组成这个应用程序的操作和视图。可以把操作看作是您想要为 Portlet 实现的用户级功能或行为。例如,您可能需要一种操作来添加联系人或显示特定的视图。视图是完成用户操作之后应用程序的表现。例如,添加一个新联系人的操作可能产生的结果是,编辑模式下 Portlet 的视图显示联系人主列表。

接下来考虑您想要该应用程序在视觉上如何表现。在本例中,您需要一个主视图页面来列出已创建的联系人的。这个页面应该可以让用户选择一个联系人并获得关于此人的其他详细信息。

您想要联系人列表对每个用户是惟一的;因此,这个 Portlet 需要位于一个已验证的页面上,这样,用户(User)对象就可以与登录的用户相关联。

您想允许用户在列表中添加、删除和修改联系人。您可以提供一个主编辑页面来列出联系人并支持对所选条目的删除和修改操作。您不需要为用户删除一个所选条目实现另外一个视图;您只需要允许用户删除一个选定条目,然后用已修改的联系人列表来刷新主编辑页面。

如果用户选择一个联系人进行修改,您可以显示一个详细页面,用户可以在其中更新此联系人条目的任意属性。在用户完成了修改之后,您就可以重新显示主编辑页面。

同样地,您可以让用户从主编辑页面添加一个新的联系人。您可以显示另一个详细页面,用户可以在其中输入并保存联系人条目的属性。在用户保存之后,您可以重新显示带有已更新列表的主编辑页面。

现在,您可以确定可用于这个应用程序的状态转移。通过应用适当的操作来使应用程序生成特定的视图,您可以管理转移。在下图中,用椭圆表示视图(JSP),用矩形表示操作。

2. 状态转移图
状态转移图

利用 Struts 实现 Portlet

本设计需要您实现 7 个操作类。在本文所提供的实现中,这些操作定义为:

  • MainViewAction
  • DetailViewAction
  • MainEditAction
  • AddContactAction
  • DeleteContactAction
  • ModifyAction
  • ModifyContactAction

从状态图中您可以看出,Add contact 视图实际上就是从主视图到 Add contact JSP 的直接转向(direct forward)。因为在呈现 Add contact 视图之前不需要也无逻辑,所以您可以简单地直接调用 Add contact JSP,然后将其配置为全局转向(global forward)而不是操作。

建立开发环境

要在 WebSphere Studio 中启动一个基于 Struts 的 Portle 项目,您需要遵循下列步骤:

  1. 创建一个新的 J2EE level 1.3 Enterprise Application 工程。
  2. 把 Struts Portlet Framework 导入项目。
    在标准 WebSphere Portal V5.0 安装程序中,您将会在 <portal_root>/dev/struts/StrutsPortlet/PortalStrutsBlank.war 目录中找到 PortalStrutsBlank.war 文件。导入这个 war 文件会为 Jakarta Struts 和 IBM 的 Struts Portlet Framework 把 Struts jar 文件添加到项目 lib 目录中。

    3. 导入 Struts Portlet Framework
    导入 Struts Portlet Framework

  3. 在导入完成之后,您可能会在项目的 WebSphere Studio 任务列表中看到一些验证警告和一个错误。
    • XML 验证错误:Attribute "bundle" must be declared for element type "field" in validation.xml
    • 警告:Target welcome does not exist in the following modules: /
    • 警告:Target /Welcome.do does not exist in the following modules: / in index.jsp and struts-config.xml.

    您现在可以忽略这些消息。在您更新了缺省的 validation.xml 之后,就可以解决验证错误。WebSphere Studio 中的验证器给出了关于不能在基本模块里面找到的资源的警告。您现在同样可以忽略这些消息。

    这就完成了在 Studio 中开发 Struts 应用程序的基本设置。

如果您没有使用 Studio,请确保下列 jar 文件(以及您导入的 Struts jar 文件)在构建路径中是可用的。您可以在如下 WebSphere Application Server 和  WebSphere Portal 目录中找到这些文件。

  • <was-root>/lib/ivjejb35.jar
  • <was-root>/lib/j2ee.jar
  • <was-root>/lib/runtime.jar
  • <was-root>/lib/servletevent.jar
  • <was-root>/java/jre/lib/rt.jar
  • <wp-root>/shared/app/portlet-api.jar

在考虑操作类、Bean、表单和支持的类的实现细节之前,请确定应用程序配置文件的实现。这些文件包括:

  • Web 应用程序部署描述符,web.xml
  • Struts 表单验证 xml 文件,validation.xml
  • Portlet 部署描述符,portlet.xml
  • Struts 配置文件,struts-config.xml

您需要更新所有这些文件。

Web 部署描述符 —— web.xml
缺省的 web.xml 文件是作为 Portal Struts Framework 的一部分提供的。您需要根据特定的应用程序来更改部署描述符。首先,把 <display-name> 更改为对应用程序有意义的名称,比如 Contacts List<servlet id="Unique_Servlet_Name"> id 在已部署的 Portal 环境中必须是惟一的。把此值更改为惟一的字符串。

构建在该框架中的 Struts 1.1 支持把应用程序划分成模块。当使用模块时,一个程序的配置信息和目录结构按模块划分。因此,代替应用程序的单个 struts-config.xml 文件,您有多个具有独立目录结构的控制文件,它们由应用程序 URI 中与模块有关的部分来识别。Struts Portlet Framework 利用模块支持来提供 Struts 配置模式和设备(标记)区别。搜索路径用于确定要用到的模块和 struts-config.xml 文件。它还确定了用于定位 JSP 的基本目录。当搜索模块时,添加以下初始参数会将搜索路径设置为在搜索模块时考虑标记名称和模式。


<init-param>
  <param-name>ModuleSearchPath</param-name>
  <param-value>markupName, mode</param-value>
</init-param>

您为这个应用程序创建了两个模块,一个用于编辑模式,而另一个用于帮助模式。视图模式是通过基本 Struts 配置来配置的。这两个模块以这样的形式作为初始参数进行配置:/config/<device>/<mode>。 因此,您有 config/html/editconfig/html/help。添加与这些模块定义相关的参数值来指示在哪里开始搜索 Struts 配置文件。


    <init-param>
      <param-name>config/html/help</param-name>
      <param-value>/WEB-INF/html/help/struts-config.xml</param-value>
    </init-param>
    <init-param>
      <param-name>config/html/edit</param-name>
      <param-value>/WEB-INF/html/edit/struts-config.xml</param-value>
    </init-param>
 

添加两个特定于应用程序的初始参数 persist_to_dbdatasource 来支持持久化类,它是下载的一部分。将此值设置为 true 会导致部署数据库代理。如果您使用数据库代理,您就还需要设置数据源。将数据源的值设置为此数据源的名称。如果您使用的是内存中的持久性,您可以忽略数据源的值。

最后,更改欢迎文件列表。Struts Portlet Framework 允许您指定设备/模式的初始视图。这可以通过欢迎文件列表来指定。


  <welcome-file-list>
    <welcome-file>index.jsp</welcome-file>
    <welcome-file>html/help/index.jsp</welcome-file>
    <welcome-file>html/edit/index.jsp</welcome-file>
  </welcome-file-list>

Portlet 部署描述符 —— portlet.xml

您还必须更改缺省的 portlet.xml 文件,该文件由空白的  Struts Portlet 提供。

  1. <portlet-app-name><portlet-name> 更改为有意义的名字。
  2. <portlet-app uid> 更改为惟一的标识符。
  3. 将 href 更改为相关的 Servlet id,它是作为 web.xml <servlet id> 值指定的。例如,如果您在 web.xml 中为 Servlet id 指定  ContactsListPortlet,您就可以在 portlet.xml 中为 Portlet href 指定 WEB-INF/web.xml#ContactsListPortlet
  4. 指定 html 设备的编辑和帮助模式支持、以及视图模式。
  5. 对于具体的 Portlet 应用程序,为 portlet-app-nameportlet-name 两者指定惟一的 uid 和有意义的名称。
  6. 更该 concrete-portlet href 的值以与 Portlet 应用程序 <portlet id> 的值相匹配。
  7. 最后,为标题(title)、短标题(title-short)、描述(description)和关键字(keywords)的特定于语言的属性指定有意义的值。

清单 1. portlet.xml


<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE portlet-app-def PUBLIC
     "-//IBM//DTD Portlet Application 1.1//EN" "portlet_1.1.dtd">
<portlet-app-def>
  <portlet-app uid="contacts_list_portlet.ContactsListPortlet.b067c2c0"
             major-version="1" minor-version="0">
    <portlet-app-name>Contacts List application</portlet-app-name>
    <portlet id="contacts_list_portlet.ContactsListPortlet"
              href="WEB-INF/web.xml#contacts_list_portlet.ContactsListPortlet"
              major-version="1" minor-version="0">
      <portlet-name>Contacts List portlet</portlet-name>
      <cache>
        <expires>0</expires>
        <shared>NO</shared>
      </cache>
      <allows>
        <maximized/>
        <minimized/>
      </allows>
      <supports>
        <markup name="html">
          <view/>
          <edit/>
          <help/>
        </markup>
      </supports>
    </portlet>
    </portlet-app>
    <concrete-portlet-app uid="contacts_list_portlet.ContactsListPortlet.b067c2c0">
      <portlet-app-name>Contacts List application</portlet-app-name>
      <concrete-portlet href="#contacts_list_portlet.ContactsListPortlet">
        <portlet-name>Contacts List portlet</portlet-name>
        <default-locale>en</default-locale>
        <language locale="en">
          <title>Contacts List portlet</title>
          <title-short>Contacts List</title-short>
          <description>Contacts List portlet</description>
          <keywords>WPS, Struts</keywords>
        </language>
        <config-param>
          <param-name>FilterChain</param-name>
          <param-value>StrutsTranscoding</param-value>
        </config-param>
      </concrete-portlet>
    </concrete-portlet-app>
</portlet-app-def>

Struts 配置文件 —— struts-config.xml
struts-config.xml
文件包含 Struts Framework 用于控制、导航和配置设置(包括所需的表单 Bean)的应用程序定义。

如上所述,在更改 web.xml 文件时,与两个应用程序模块定义中每一个都相关的参数值指示了从哪里开始搜索特定于模块的 Struts 配置文件。因此,您需要创建新的 struts-config.xml 文件,它将驻留在 /WEB-INF/html/edit//WEB-INF/html/help/ 中。这些文件将包含特定于其模块的 Struts 配置信息。

首先,将 /WEB-INF 目录中的 struts-config.xml 文件更改为视图模式的 Structs 配置。您需要在 xml 中创建操作元素来支持在转移图中标识的操作。指定的操作有 7 种。这些操作可以如下定义,并且将使用在示例实现中所定义的类名来显示。您还为每个操作指定适当的转向设置,以便指示用于呈现请求视图的 JSP。同样在状态转移图中指定了这些呈现状态。您可以把这些适当的操作和转向包含在特定于模块的配置文件中。

接下来,在上面指定的目录中创建新的 struts-config.xml 文件。

struts-config.xml


  <form-beans>
    <form-bean name="contactForm"
        type="com.ibm.sample.contacts.struts.beans.Contact"/>
  </form-beans>

您还可以指定全局转向、消息源文件和验证 xml 文件引用。全局转向使逻辑名称与指向 JSP 或操作的引用的 URI 相关联。

清单 2. VIEW - /WEB-INF/struts-config.xml


<?xml version="1.0" encoding="ISO-8859-1" ?>

<!DOCTYPE struts-config PUBLIC
          "-//Apache Software Foundation//DTD Struts Configuration 1.1//EN"
          "http://jakarta.apache.org/struts/dtds/struts-config_1_1.dtd">

<struts-config>

  <form-beans>
    <form-bean name="contactForm"
        type="com.ibm.sample.contacts.struts.beans.Contact"/>
  </form-beans>

  <global-forwards>
   <forward   name="mainview" path="/mainview.do" />
   <forward   name="notauthenticated" path="/not_authenticated.jsp"/>
   <forward   name="exception" path="/exception.jsp"/>
  </global-forwards>

  <action-mappings>
    <action
      path="/mainview"
    type="com.ibm.sample.contacts.struts.action.MainViewAction"
    name="contactForm"
    scope="request"
    validate="false">
        <forward
          name="mainviewpage"
          path="/main_view.jsp"/>
    </action>

    <action
      path="/detailview"
    type="com.ibm.sample.contacts.struts.action.DetailViewAction"
    name="contactForm"
    scope="request"
    validate="false" >
    <forward
      name="detailviewpage"
      path="/detail_view.jsp"/>
    </action>
  </action-mappings>

  <controller
      processorClass="com.ibm.wps.portlets.struts.WpsRequestProcessor">
  </controller>

  <message-resources
      parameter="com.ibm.sample.contacts.struts.nls.ApplicationResources"/>

  <plug-in className="org.apache.struts.validator.ValidatorPlugIn">
    <set-property property="pathnames"
                     value="/WEB-INF/validator-rules.xml,
                            /WEB-INF/validation.xml"/>
  </plug-in>

</struts-config>

清单 3. EDIT - /WEB-INF/html/edit/struts-config.xml


<?xml version="1.0" encoding="ISO-8859-1" ?>

<!DOCTYPE struts-config PUBLIC
          "-//Apache Software Foundation//DTD Struts Configuration 1.1//EN"
          "http://jakarta.apache.org/struts/dtds/struts-config_1_1.dtd">

<struts-config>

  <form-beans>
    <form-bean name="contactForm"
        type="com.ibm.sample.contacts.struts.beans.Contact"/>
  </form-beans>

  <global-forwards>
   <forward   name="addcontactpage" path="/add_contact.jsp"/>
   <forward   name="mainedit" path="/mainedit.do" />
  </global-forwards>

  <action-mappings>

    <action
      path="/mainedit"
    type="com.ibm.sample.contacts.struts.action.MainEditAction"
    name="contactForm"
    scope="request"
    validate="false" >
    <forward
      name="maineditpage"
      path="/main_edit.jsp"/>
    </action>

    <action
      path="/modify"
    type="com.ibm.sample.contacts.struts.action.ModifyAction"
    name="contactForm"
    scope="request"
    validate="false" >
    <forward
      name="editcontactpage"
      path="/edit_contact.jsp"/>
    <forward
      name="deletecontact"
      path="/deletecontact.do"/>
    </action>

    <action
      path="/modifycontact"
    type="com.ibm.sample.contacts.struts.action.ModifyContactAction"
    name="contactForm"
    scope="request"
    validate="false" >
    <forward
      name="mainedit"
      path="/mainedit.do"/>
    </action>

    <action
      path="/deletecontact"
    type="com.ibm.sample.contacts.struts.action.DeleteContactAction"
    name="contactForm"
    scope="request"
    validate="false" >
    <forward
      name="maineditpage"
      path="/main_edit.jsp"/>
    </action>

    <action
      path="/addcontact"
    type="com.ibm.sample.contacts.struts.action.AddContactAction"
    name="contactForm"
    scope="request"
    validate="false" >
    <forward
      name="addcontactpage"
      path="/add_contact.jsp"/>
    </action>

  </action-mappings>

  <controller
      processorClass="com.ibm.wps.portlets.struts.WpsRequestProcessor">
  </controller>

  <message-resources
     parameter="com.ibm.sample.contacts.struts.nls.ApplicationResources"/>
</struts-config>

清单 4. HELP - /WEB-INF/html/help/struts-config.xml


<?xml version="1.0" encoding="ISO-8859-1" ?>
<!DOCTYPE struts-config PUBLIC
          "-//Apache Software Foundation//DTD Struts Configuration 1.1//EN"
          "http://jakarta.apache.org/struts/dtds/struts-config_1_1.dtd">
<struts-config>
  <action-mappings>
  </action-mappings>
  <controller
      processorClass="com.ibm.wps.portlets.struts.WpsRequestProcessor">
  </controller>
  <message-resources
      parameter="com.ibm.sample.contacts.struts.nls.ApplicationResources"/>
</struts-config>

Struts 验证 —— validation.xml
您在这个应用程序中没有用到 Struts 输入验证。您可以删除 validation.xml 中的缺省验证规范。


<form-validation>
</form-validation>

目录结构更改
回顾一下,您更改了 web.xml 文件中的欢迎文件列表。这个列表用于指示已定义的模块的起点。根据 web 应用程序的根上下文,您需要为编辑和帮助模式创建目录,并且把每个模式的 index.jsp 放在这些目录中。

每个模块的 struts-config.xml 文件(表示 Portal 模式)都没有显示 JSP 文件的附加路径信息;因此,在这些相同的目录的每一个中您都需要为该模块添加适当的 JSP。在 /html/edit 目录中,您有 add_contact.jspedit_contact.jspmain_edit.jsp 以及 index.jsp 文件。在根目录中,您有 detail_view.jspmain_view.jsp。在 /html/help 目录中,我们只有 index.jsp 文件。

操作类的实现
接下来,您将实现这个应用程序所需的操作类。这里不讨论每个类的细节,因为在下载部分中提供了这些类的完整实现。 您需要实现类来扩展在状态转移图中标识的且在 struts-config.xml 文件中定义的每个操作的 org.apache.struts.action.Action

请查看 DeleteContactAction 类的代码,它实现了删除联系人的功能。您也可以看到我们的操作类扩展的抽象类,因此,您可以把用于实现所有的操作类的通用代码放入其中。例如,您可以在此添加代码来验证用户在执行该功能之前是否等录。

清单 5. DeleteContactAction 类


public class DeleteContactAction extends PostLoginAbstractAction {
  public ActionForward performAction(ActionMapping mapping, ActionForm form,
    User user, HttpServletRequest request, HttpServletResponse response)
    throws Exception {

    //  Get the userid and selected oid
    String userid = user.getUserID();
    Contact contact = (Contact) form;
    String oid = contact.getSelectedContact();

    //  Delete the contact
    ContactHelper contactHelper = ContactHelper.getInstance();
    contactHelper.deleteContact(broker, userid, oid);

    //  Render the main edit page
    return (mapping.findForward(MAIN_EDIT));
  }
}

抽象操作类扩展 org.apache.struts.action.Action 并实现 execute 方法。此实现确保用户已登录,然后调用已调用的操作类中的 performAction 方法,传送与已传送到 execute 方法以及在登录验证时检索到的用户 Bean 的参数相同的参数。当您把应用程序迁移到 Portal 环境中时,您将只需删除登录操作,并且将此代码更改为从 portletRequest 对象中检索用户对象。然后,您就可以更改访问用户对象的任何应用程序代码来以使用 wps 用户对象 API。

清单 6. PostLoginAbstractAction 类


public abstract class AbstractAction extends Action implements Constants {

  public ActionForward execute(ActionMapping mapping, ActionForm form,
    HttpServletRequest request, HttpServletResponse response)
    throws Exception {

    try {
      // Initializations
      log = LogFactory.getLog("com.ibm.sample.contacts.struts.action");
      bundle = ResourceBundle.getBundle(RESOURCE, request.getLocale());

      // Initialize the persistence broker
      broker = ContactListBroker.getInstance();
      if (broker == null) {
        String persistToDB = getServlet().getInitParameter(DB);
        String datasource = getServlet().getInitParameter(DATASOURCE);
        if (TRUE.equalsIgnoreCase(persistToDB))
          ContactListDBBroker.initialize(datasource);
       else
          ContactListMemBroker.initialize();
        broker = ContactListBroker.getInstance();
       if (log.isDebugEnabled())
          log.debug("Broker initialized: "+broker);
      }

      // Check for existing session with logged-in user
      HttpSession session = request.getSession();
      PortletRequest portletRequest = (PortletRequest) request;
      User user = portletRequest.getUser();
      if (session==null || user==null)
        throw new AIMMessageException(bundle.getString(UNAUTHENTICATED));

      // Invoke the action class performAction method
      return performAction(mapping, form, user, request, response);

    } catch (Exception e) {
      HttpSession session = request.getSession();
      session.setAttribute(EXCEPTION,e);
      return (mapping.findForward("exception"));
    }
  }

  public abstract ActionForward performAction(ActionMapping mapping,
     ActionForm form, User user, HttpServletRequest request,
     HttpServletResponse response)  throws Exception;

}

其余的操作类的实现是非常类似的,而且如果假定这个应用程序有最低限度的逻辑处理,那么它们根本就不是复杂的实现。

DeleteContactAction 类中所示,一些操作类使用持久化类的服务。Persistence 方法是作为下载实现的一部分提供的。现在,可以查看 ContactListBroker 接口,它定义了联系人列表处理所需的函数。代理类的实现管理数据存储(在本例中,或者为数据在数据库中的表示,或者为数据在内存中的表示)的数据访问。这个函数是该 Portlet 所需要的,但是它与与本文的要点无甚关系,您可以在下载部分中查看特定代理的实现。

清单 7. ContactListBroker 接口


public interface ContactListBroker {

  /**
   * Get the Contact information given a contact number
   * @param owner java.lang.String
   * @param contactOID java.lang.String
   * @return ContactForm
   */
  public ContactForm getContact(String owner, String contactOID)
    throws AIMException;

  /**
   * Create a Contact
   * @param ContactForm
   */
  public void saveContact(Contact contact)
    throws AIMException;

  /**
   * Delete a Contact
   * @param owner java.lang.String
   * @param contactOID java.lang.String
   */
  public void deleteContact(String owner, String oid)
    throws AIMException;

  /**
   * Get the contact list.
   * @param owner java.lang.String
   * @return List of ContactForm objects
   */
  public List getContactList(String owner)
    throws AIMException;

}

应用程序 Bean
我们为这个应用程序定义了两个 Bean。我们在 struts-config.xml 文件中定义了一个联系人表单 Bean。它扩展了 org.apache.struts.validator.ValidatorForm,并且包含映射到联系人数据库表的列的特性(带有存取器)。请参阅为我们的示例表定义设置数据库的部分。另一个 Bean 是一个助手类,它提供了通用函数来添加和删除联系人。同样在下载中提供了这些代码,这里不再显示。

应用程序资源
在 struts-config.xml 文件中定义了消息特性文件。我们的文件命名为 ApplicationResources.properties,它位于一个资源文件夹中。这个资源包提供了封装在包中的可显示字符串,这样使应用程序更易于转换。

Java Server Page(JSP)文件
其余的应用程序组件是 JavaTM Server Page(JSP)文件。正如您在 struts-config.xml 文件中定义的,基于状态转移图,您需要实现 5 个 JSP 来呈现一个页面,用于以下目的:

  1. 添加联系人信息
  2. 编辑联系人信息
  3. 主视图页面(Main view page)
  4. 主编辑页面(Main edit page)
  5. 联系人详细信息视图页面(Detail contact view page)

您同样需要更新 index.jsp 文件来为每种模式调用初始化操作。

考察这个 JSP 文件的一些关键部分,即用于呈现主视图的部分以及此 JSP 呈现的内容的示例。这个 JSP 需要一个在会话期间存在的 Bean 来包含联系人列表。您定义了几个在 JSP 中使用的标准 Struts 标签库。当用户在呈现的列表中选择了一个联系人时,您想要继续进行 detailview 操作,将所选联系人 oid 作为参数与请求表单数据一起传送。

清单 8. 主视图 JSP


<%@ taglib uri="/tags/struts-bean" prefix="bean" %>
<%@ taglib uri="/tags/struts-html" prefix="html" %>
<%@ taglib uri="/tags/struts-logic" prefix="logic" %>
<%@ taglib uri="/tags/struts-portal-html" prefix="portalhtml" %>
<%@ taglib uri="/WEB-INF/tld/portlet.tld" prefix="portletAPI" %>

<jsp:useBean id="contactList" class="java.util.List" scope="session" />

<html:html locale="true">
<table border="0" width="95%" align="center" cellspacing="0" cellpadding="0" >

  <thead>
  <tr>
    <td class="wpsTableHead"><bean:message key="contact.name"/></td>
    <td class="wpsTableHead"><bean:message key="contact.company"/></td>
    <td class="wpsTableHead"><bean:message key="contact.email"/></td>
    <td class="wpsTableHead"><bean:message key="contact.mobile"/></td>
  </tr>
  </thead>

  <html:form method="post" action="/detailview" >
  <html:hidden property="selectedContact"/>

    <logic:iterate
        name="contactList" id="aContact"
        type="com.ibm.sample.contacts.struts.beans.Contact">
  <tr>
    <td class="wpsPortletSmText" valign="top" align="left">
        <a   style="text-decoration: none; color:black;"
          onMouseOver="this.style.color='red'"
          onMouseOut="this.style.color='#000000'"
          href="javascript:document.<portletAPI:encodeNamespace
              value='ContactForm'/>.selectedContact.value=
              '<bean:write name="aContact" property="oid"/>';
              document.<portletAPI:encodeNamespace value=
              'ContactForm'/>.submit()">
        <bean:write name="aContact" property="firstName"/>
        <bean:write name="aContact" property="lastName"/>
        </a>
    </td>
    <td class="wpsPortletSmText" valign="top" align="left">
      <bean:write name="aContact" property="company"/>
    </td>
    <td class="wpsPortletSmText" valign="top" align="left">
      <bean:write name="aContact" property="email"/>
    </td>
    <td class="wpsPortletSmText" valign="top" align="left">
      <bean:write name="aContact" property="mobilePhone"/>
    </td>
  </tr>

  </logic:iterate>

  </html:form>
</table>
</html:html>

4. 主列表视图
主列表视图

设置数据库
您可以为此应用程序创建两个用于数据持久化的选项:一个带有数据库代理实现,另一个带有内存中的实现。为了快速开发和测试的目的,您可能只想使用内存中的形式,因为它不需要后续数据库设置的步骤。当然,每当应用程序服务器重启时数据都会丢失。下载部分提供了这两种代理类型的代码(与这个示例应用程序的余下部分一起提供),代理类型是通过 Web 部署描述符文件 web.xml 中设置的配置参数来选择的。

然而,如果您选择把应用程序数据保存到数据库中,您就需要首先创建数据库表来存放联系人列表数据。要创建该表,需要从命令行运行下列 SQL 命令,用您选择的名称来替代 Schema 名称,但请保留指定的表名。您可以为该表创建一个新的数据库(数据空间)或者把它添加到现有的数据库中。如果使用 DB2,则在命令中心(Command Center)建立一个到适当数据库的连接,再复制下列命令,然后运行它。


CREATE TABLE "DB2ADMIN"."CONTACTS" ("OWNER" VARCHAR(64) NOT NULL,
"OID" VARCHAR(64) NOT NULL PRIMARY KEY, "FIRST_NAME" VARCHAR(32) NOT NULL,
"LAST_NAME" VARCHAR(32) NOT NULL , "EMAIL" VARCHAR(128) NOT NULL,
"TITLE" VARCHAR(64), "COMPANY" VARCHAR(64), "BUS_PHONE" VARCHAR(32),
"MOBILE_PHONE" VARCHAR(32), "FAX_PHONE" VARCHAR(32), "WEB" VARCHAR(128),
"ADDRESS1" VARCHAR(32), "ADDRESS2" VARCHAR(32), "CITY" VARCHAR(32),
"STATE" VARCHAR(2), "ZIP" VARCHAR(10), "COUNTRY" VARCHAR(32) )

现在,您可以把一个条目添加到联系人列表数据库表中,这样您就可以在开发 Portlet 时更容易地对其进行测试。您可以执行下列 SQL 命令来创建一个新的条目。如果您出于测试的目的想用不同于 wpsadmin 的 userID 登录到 Portal,就请用这个用户 ID 来代替下面 SQL 声明中的 wpsadmin


insert into contacts (owner, oid, first_name, last_name, email, company,
mobile_phone) values ('wpsadmin', '01', 'Tim', 'Hanis', 'hanistt@us.ibm.com',
'IBM', '919-254-9072')

接下来,在 WebSphere Application Server 中为您创建的联系人表所在的数据库创建数据源。这个 Portlet 是作为 J2EE 1.3 应用程序打包的,因此您需要指定 Application Server V5 数据源。J2EE Level 1.3 包括 Servlet Specification Level 2.3 和 JSP Specification Level 1.2。

  1. 在 Application Server 中使用 DB2 Legacy CLI-based Type 2 JDBC Driver JDBC 驱动程序并指定 Data Sources 而不是 Data Sources(版本 4)
  2. 在 Application Server Administrative Console 上,选择 Resources =>JDBC Providers
  3. 如果您已经安装了 DB2 Legacy CLI-based Type 2 JDBC Driver,就选择它。否则,通过选取 New 命令并完成下一个页面来添加它。
  4. DB2 Legacy CLI-based Type 2 JDBC Driver 页面上,确保把类路径设置为 db2java.zip 文件的正确位置。
  5. 选择 Data Sources,接下来选取 New 以创建一个新的 V5 数据源。指定数据源的名称。对于 JNDI 名,用 jdbc/ 子上下文作为名称的前缀。
    例如,如果您想要一个数据源 jndi 名为 aim,就可以输入 jdbc/aim。Portlet 在进行 JNDI 名称查找时会预先考虑 jdbc/ 子上下文。
  6. 如果您的数据库需要用户 id 和密码用于身份验证,就请在 Component-managed Authentication Alias 中指定一个身份验证别名。
  7. 如果您还没有定义一个别名,您就可以在 Security => JAAS Configuration => J2C Authentication Data 中创建一个。
  8. 确保保存配置的更改,并测试数据源连接。

5. WebSphere Application Server Administrative Console
WebSphere Application Server Administrative Console

最后,在 Application Developer 中为这同一个数据库创建数据源。如果您想要利用 Application Developer 来测试和调试这个 Struts 应用程序,这也是需要的。从 Application Developer Server 透视图中编辑 WebSphere Portal Server V5 Test Environment 定义,在编辑窗格中选取数据源选项卡,添加 DB2 Legacy CLI-based Type 2 JDBC Driver 驱动程序,然后添加 V5 数据源。确保使用 jdbc/ 作为您的 JNDI 名的上下文前缀。与在 Application Server 中一样,您可能需要添加安全性验证别名(如果您还没有创建的话)。

6. 定义数据源
定义数据源

实现类摘要
下表列出了用于实现示例应用程序的 JAVA 类实现(可以在下载部分中找到)和对每个类的简要描述。

1. ConactsListPortlet 类

描述
com.ibm.sample.contacts.struts.beansContactHelper助手类,用于为联系人调用持久化管理函数
Contact表示联系人的 Struts 表单对象
com.ibm.sample.contacts.struts.actionAddContactAction处理添加联系人信息的请求
DeleteContactAction处理删除联系人信息的请求
DetailViewAction处理显示联系人详细情况视图的请求
ModifyAction处理修改联系人信息的请求
ModifyContactAction处理保存已编辑的联系人信息更改的请求
MainEditAction处理显示主编辑视图的请求
MainViewAction处理显示主联系人列表视图的请求
AbstractAction用于操作的抽象类
com.ibm.sample.contacts.struts.persistenceContactListBroker持久性类接口 
AbstractDBBroker用于数据库代理的通用函数的抽象类
ContactListDBBroker数据库代理实现,它扩展 DbAbstractBroker 并实现 ContactListBroker
ContactListMemBroker实现 ContactListBroker 的内存代理实现,
com.ibm.sample.contacts.struts.utilitiesAIMException基本异常类
AIMWrapperException包装另一个(基本)异常的 AIMException
AIMMessageException终止处理和发出用户消息的的异常
Constants定义应用程序常量的接口
com.ibm.sample.contacts.struts.nlsApplicationResources.properties包含可打印字符串的缺省资源包
ApplicationResources_en.properties包含可打印字符串的特定于地点的资源包

结束语
本文讨论了如何使用 Struts Portlet Framework 实现一个示例应用程序。您了解了如何使用 Struts 模块以及如何使用它们与 WebSphere Struts Portlet Framework 来支持多 Portal 模式。在下面的下载部分中提供了本例的完整实现。

参考资料

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值