分享

【使用 struts portlet 在门户应用程序中实现页面导航】

 smoking_boy 2005-08-24
网站目录: 网站首页 —> Java
转载自:www.csdn.net


引言
Struts 是一个很受欢迎的开放源代码平台基础,它是为了使复杂的 Web 应用程序的创建和维护更加容易而设计的。Struts 框架支持模型-视图-控制器(Model-View-Controller,MVC)模型,并且提出了许多重要的应用程序设计和实现需要注意的事项。为了能够在门户应用程序中实现页面导航,WebSphere? Portal V5 提供了一些标记,在开发典型 portlet 和 Struts portlet 时可将这些标记用于 JavaServer Pages(JSP)。本文重点讨论 Struts 框架创建多模块的能力,并通过一个样本 Struts portlet 应用程序为您介绍如何采用 JSP 实现页面导航方法。

我们将关注以下两种互补的方法:

  • 如何使用在 WebSphere Portal 中可用的某一 JSP 标记来从 JSP 实现页面导航
    我们将会看到一个样本应用程序,包括开发环境和门户资源的屏幕快照,以及页面导航方法的代码样本。
  • 如何使用 Struts portlet 框架中内置的多模块支持来组织 Web 导航方案
    我们将会看到一些代码样本,它们阐述了如何使用页面导航特征来执行在门户环境中转换的多个 Struts 模块。

本文假定您已基本了解 Struts 应用程序,包括如何在 WebSphere Studio Application Developer 中创建 Struts 应用程序、如何将 Struts 作为 portlet 进行部署,同时也了解 WebSphere Portal 中的门户资源。(要获得这些方面的更多信息,请参见参考资料。)

在开发和部署我们的样本应用程序时用到了以下产品:

  • WebSphere Portal V5.x
  • WebSphere Application Server v5.x
  • 支持 Struts Version 1.1 的 WebSphere Studio Application Developer v5.0.1 (下面称为 Application Developer)。

本文所讲解的用于实现页面导航的开发任务可同时用于标准 portlet 和 Struts portlet。

应用程序概述
在样本应用程序中,我们将会使用位于三个不同页面的三个 portlet。当用户选择其中某一 portlet 中的链接时,该用户会被定向到另一个页面,其中驻留着另一个 portlet。在整个文章中我们开发和提到的示例都会利用多 Struts 模块将 WebSphere Portal 页面导航标记并入门户环境中每个模块本身的 JSP 文件中。图 1 概括性地展示了样本应用程序将如何工作;为了把重点放在理解这些方法上,我们特意简化了样本应用程序。在本文的后面我们将会提供应用程序的细节。

图 1. 样本应用程序的高级视图
图 1. 样本应用程序的高级视图

构建导航结构
WebSphere Portal 提供了自己的 JSP 标记来供 portlet JSP 使用。其中的一个标记,<wps:URLGeneration attribute="value"/>,是用于创建到门户任何地方的页面链接的。我们使用该标记中一个属性,contentNode="id|name",来创建到不同页面的 URL,以便构建导航结构。该属性利用一个惟一的标识符(内容节点的名称)来指定可以从中找到该 portlet 的页面。(关于这一标记的更多信息请参见参考资料。)

在 WebSphere Portal 中选择 Administration => Portal Settings => Custom Unique Names。我们使用 Custom Unique Names 管理 portlet 来获取为 contentNode 属性指定的门户资源的惟一标识符。管理员可以使用 Custom Unique Names portlet 来查看惟一标识符并为门户资源分配(让人易读的)自定义名称。图 2 显示了这些已配置的样本页面的惟一标识符和自定义名称:

  • Struts_Test
  • Struts_Receiver
  • Struts_Receiver_2

图 2. Custom Unique Names portlet
图 2. Custom Unique Names portlet

在这个示例中,WebSphere Portal 分配给这些页面的惟一标识符分别为 6_0_LT6_0_P16_0_IP。(您的值可能会有所不同。)在驻留 WebSphere Portal 的另一台机器上也创建了同样的门户资源 Struts_TestStruts_Receiver Struts_Receiver_2 portlet 页面。为了阅读和工作的方便,我们也为这些样本页面配置自定义名称,并在 JSP 文件中使用这些自定义名称(而不是惟一标记符)。

<wps:URLGeneration attribute="value"/> portlet JSP 标记主体中,可以使用 <% wpsURL %> 脚本变量将 URL 直接写入输出流。在这个示例中,我们使用以下 JSP 代码来创建从某一 JSP 页面到 Struts Receiver 页面的链接:


<wps:urlGeneration contentNode="Struts_Receiver_Page">
         <A HREF="<%wpsURL.write(out);%>"style="text-decoration:none" >
         Any text</a>
</wps:urlGeneration>

<wps:URLGeneration attribute="value"/> portlet JSP 标记属于 engine.tld 标记库,这一标记库是由门户服务器引擎使用的。为了让该门户 JSP 标记可用于我们的 JSP 中,我们在 JSP 页面的最开始位置添加标记库指示 taglib。如以下代码所示,通过前缀 wps,我们样本中所有的 engine.tld 标记现在就都可用了:


<%@ taglib uri="/WEB-INF/tld/engine.tld" prefix="wps" %>

样本页面和 portlet 配置
该样本应用程序的页面导航条包括三个 portlet(这里提供的长名称有助于强调页面导航流程):

请记住,到目前为止所描述的全部任务均可用于常规 portlet 或 Struts portlet 开发。接下来我们将使用多 Struts 模块中的门户 JSP 标记来实现页面导航。

在 Struts 中使用多模块支持
Struts Version 1.1 可以让我们将单个 Struts 应用程序拆分为多个模块,每个模块都有自己的操作、JSP 页面和 Struts 配置文件(图 6)。在 Struts 应用程序中实现多 Struts 模块需要以下几个步骤:

  • 创建独立的 Struts 配置文件以及每个应用程序模块的 Struts 操作和 JSPs。
  • 配置 Web 部署描述符(web.xml)。
  • 从一个模块转换到另一个模块。

虽然 Struts 应用程序很容易应用,但要想在门户环境中运行 Struts 应用程序的话,您还需要执行其他的步骤。(参见参考资料)。

图 6. Struts 应用程序中的多模块支持
图 6. Struts 应用程序中的多模块支持

创建独立的 Struts 模块和文件
对于我们的样本应用程序,我们创建了四个 Struts 模块,以及它们自己的 Struts 配置文件、行为和 JSPs。这些 Struts 模块是:

  • address
  • phone-numbers
  • overview
  • default.

我们也配置了 web.xml portlet.xml 文件,并使用 default 模块执行从一个模块到另一个模块的转换。

接下来,我们将会根据实现的需要讲解我们的文件需要的改动。

在 Struts 模块中开发页面导航
我们在以下三个模块中实现页面导航:

  • overview
  • address
  • phone-numbers.

除了存在一些细微的差别以外,这些模块中每一个的页面导航开发任务几乎都是相同的。因此,我们将讲解实现 overview 模块的页面导航的任务,然后再描述一下其他模块的实现任务与此的差别。此外,我们还会讲解特定于 Struts 模块的开发过程,该模块是为 default 模块而转换的。在我们的实现中,default 模块用于将控制权交给下一个适当的模块;并不需要页面导航。然而,由于它启动其他模块来执行模块转换并且是导航结构的一个主要部分,所以我们这里也将它包括在内。

在 Application Developer 中,我们创建一个支持 Struts Version 1.1 的 Web 项目,然后为开发任务创建文件,如下面的表 1 所示。

表 1. 开发构件列表
表 1. 开发构件列表

以下是表 1 所示构件的简要描述:

  1. JSP 文件:
    我们开发了五个 JSP 文件:
    • 用于 default 模块的 index.jsp failure.jsp 文件;
    • 用于 address 模块的 address.jsp 文件;
    • 用于 phone-numbers 模块的 phone-numbers.jsp 文件;
    • 用于 overview 模块的 overview.jsp 文件。
  2. 操作:
    我们在 com.test.strutstest.actions 包中创建四个 Struts 操作。它们的类为:
    • DisplayAction
    • DisplayAddressInfoAction
    • DisplayPhoneInfoAction
    • OverviewAction.
  3. 表单 bean:
    我们在 com.test.strutstest.forms 包中创建两个表单 bean。它们的类为:
    • UserFormBean
    • OverviewFormBean.
  4. 后端 bean 和模型类:
    我们在包中使用一个后端 bean 类(UserBean )和一个模型类(UserBeanHelper)。(后端 bean 包含存根数据,并不与真正后端进行通信。)
  5. Struts 配置文件:
    我们开发了四个 struts-config.xml 文件,每个模块使用一个:
    • 用于 default 模块的 WEB-INF/struts-config.xml
    • 用于 address 模块的 WEB-INF/address/struts-config.xml
    • 用于 phone-numbers 模块的 WEB-INF/phone-numbers/struts-config.xml
    • 用于 overview 模块的 WEB-INF/overview/struts-config.xml
  6. 其他配置文件:
    在将 Struts 应用程序作为 portlet 进行部署时需要修改 web.xml portlet.xml 文件。

以上的每一个配置文件都包含下列请求处理器(Request Processor):


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

图 7 显示了在 Application Developer 开发环境中开发构件的位置:

图 7. WebSphere Studio Application Developer 中的开发构件的位置
图 7. WebSphere Studio Application Developer 中的开发构件的位置

配置 default 模块
要想启动 default 模块并查看它如何在 Struts 模块之间进行转换,需要执行以下步骤:

  1. Default 模块是在 WebSphere Portal 调用 index.jsp 文件时启动的,这是在 web.xml 文件中的 <welcome-file-list> 标记中指定的:

    
    <welcome-file-list>
         <welcome-file>index.jsp</welcome-file>
    </welcome-file-list>

  2. 调用 index.jsp 时,在 logic Struts 标记中指定逻辑转发名 Display

    
    <logic:forward name="Display"/>
    

  3. default 模块的 struts-config.xml 文件中的逻辑 forward name(在此为 Display)定义为全局转发:

    
    <global-forwards>
         <forward name="Display"    path="/display.do"/>
    </global-forwards>
    

  4. <global-forwards> 部分中,使逻辑全局转发上下文关系路径 path="/ display.do" <action-mappings> 部分中的操作元素的上下文关系路径 path="/display" 路径相匹配。这一匹配可以启动 DisplayAction 操作。操作映射部分(包括带有 path type 属性的 <action> 元素)如下所示:

    <action-mappings>
        <action path="/display"
    
               type="com.test.strutstest.actions.DisplayAction">
                   .................................................
        </action>
    </action-mappings>

为了启用模块转换,请为 remaining 模块配置 default 模块的 struts-config.xmlportlet.xml config.xml 文件:

  1. 配置 default 模块的 struts-config.xml 文件。我们使用 DisplayAction 作为我们的操作类和四个逻辑转发:

    
    <action-mappings>
         <action path="/display"
              type="com.test.strutstest.actions.DisplayAction">
                   <forward name="failure"
                        contextRelative="true"
                        path="/failure.jsp"/>
                   <forward name="address"
                        contextRelative="true"
                        path="/address/start.do"/>
                   <forward name="phone-numbers"
                        contextRelative="true"
                        path="/phone-numbers/start.do"/>
                   <forward name="overview"
                        contextRelative="true"
                        path="/overview/start.do"/>
         </action>
    </action-mappings>

  2. 配置 portlet.xml 文件,使之符合 default 模块的 struts-config.xml 文件中的配置。特别是,在 default 模块的 struts-config.xml 文件中的四个逻辑转发名称中的每一个均要与在 portlet.xml 文件中设置的 view.forward 配置参数值相匹配。表 2 显示了这一映射关系:

    表 2. view.forward 配置值对转发名称配置值
    >表 2. view.forward 配置值对转发名称配置值

  3. 配置 web.xml 文件来定义不同的模块。我们使用 config 初始化参数来将我们的 default 模块告知操作 servlet;然而,对于其他的每个模块,我们列出了一个名为 config/module 的初始化参数,其中 module 是我们的模块名称。例如:
    • 可以这样定义 default 模块:

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

    • 可以这样定义其他模块:

      
      <init-param>
           <param-name>config/address</param-name>
           <param-value>WEB-INF/address/struts-config.xml
           </param-value>
      </init-param>
      <init-param>
           <param-name>config/phone-numbers</param-name>
           <param-value>WEB-INF/phone-numbers/struts-config.xml
           </param-value>
      </init-param>
      <init-param>
           <param-name>config/overview</param-name>
           <param-value>WEB-INF/overview/struts-config.xml
            </param-value>
      </init-param>
      

    (其他模块配置和必要的 web.xml 配置设置请参见参考资料。)

  4. web.xml portlet.xml 文件执行标准更新来将 Struts 应用程序作为 portlet 进行部署。(要获得更多信息请参见参考资料下载部分的样本 web.xmlportlet.xml 文件。)

正如 default 模块的 struts-config.xml 文件中的 <action-mapping> 部分所配置的,模块转换是在 DisplayAction 类中进行的。要想确定 WebSphere Portal 调用的是哪个模块,可以执行以下的步骤:

  1. 调用 DisplayAction 类的 execute() 方法时,访问的是在 portlet.xml 文件中设置的 view.forward 参数:

    
    PortletSettings portletSettings = request.getPortletSettings();
    String viewForward = portletSettings.getAttribute("view.forward");

  2. 对于我们的 portlet 来说,view.forward 参数会有以下的值:

    表 3. 样本 portlet 的 view.forward 配置参数的值
    表 3. 样本 portlet 的 view.forward 配置参数的值

    • 如果 viewForward 为空,那么在 execute() 方法中会将这一变量设置为 failure
    • 已配置的 viewForward 值的转发映射是从 struts-config.xml 文件检索的:

      
      ActionForward forward = new ActionForward();
      try
      {
           forward = mapping.findForward(forwardName);
      }
      catch (Exception e)
      {
            ...........................................
      }

    • execute() 方法中的最后步骤返回 ActionForward(forward)的实例:

      
      return (forward);
      

配置其他 struts-config.xml 文件。根据 DisplayAction 类中的模块确定结果,如果 view.forward 参数值为:

  1. address:

    default 模块的 struts-config.xml 文件的 <action-mappings> 部分中匹配的 start 路径会使 DisplayAddressInfoAction 在 address 模块中调用。根据 web.xml 中的配置,这一过程需要使用到 address/struts-config.xml 文件。address/struts-config.xml 文件包含以下的设置:

    
    <!-- ===== Global Forward Definitions ===== -->
    <global-forwards>
         <forward name="start" path="/start.do"/>
    </global-forwards>
    <!-- ===== Action Mapping Definitions ===== -->
    <action-mappings>
         <action  path="/start"
                   type="com.test.strutstest.actions.DisplayAddressInfoAction"
                   name="userFormBean"
                   scope="request">
              <forward name="success" path="/address.jsp"/>
         </action
    </action-mappings>

  2. phone-numbers:

    default 模块的 struts-config.xml 文件的 <action-mappings> 部分中匹配的 start 路径会使 DisplayPhoneInfoAction 在 phone-numbers 模块中调用。根据 web.xml 文件中的配置,这一过程需要使用到 phone-numbers/struts-config.xml 文件。phone-numbers/struts-config.xml 文件包含以下的设置:

    
    <!-- ===== Global Forward Definitions ===== -->
    <global-forwards>
         <forward name="start" path="/start.do"/>
    </global-forwards>
    <!-- ===== Action Mapping Definitions ===== -->
    <action-mappings>
         <action  path="/start"
              type="com.test.strutstest.actions.DisplayPhoneInfoAction"
             name="userFormBean"
             scope="request">
             <forward name="success" path="/phone-numbers.jsp"/>
         </action
    </action-mappings>

  3. overview:

    default 模块的 struts-config.xml 文件的 <action-mappings> 部分中匹配的 start 路径会使 OverviewAction 在 overview 模块中调用。根据 web.xml 文件中的配置,这一过程需要使用到 overview/struts-config.xml 文件。overview/struts-config.xml 包含以下的设置:

    
    <!-- ===== Global Forward Definitions ===== -->
    <global-forwards>
         <forward name="start" path="/start.do"/>
    </global-forwards>
    <!-- ===== Action Mapping Definitions ===== -->
    <action-mappings>
         <action  path="/start"
              type="com.test.strutstest.actions.OverviewAction"
              name="overviewFormBean"
              scope="request">
              <forward name="success" path="/Overview.jsp"/>
         </action>
    </action-mappings>

  4. failure:

    根据 default 模块的 struts-config.xml 文件中的配置,这种参数值下会启动 failure.jsp

到目前为止,我们已经创建了表 1 中所列出的文件,并根据我们的示例需要,对其中的大部分做了修改。现在我们就可以开始编写代码来实现使用 overview 模块的页面导航。以下部分将通过具体步骤指导您完成这一过程。

开发 overview 模块
要想生成 Overview.jsp 文件、OverviewAction 类、OverviewFormBean 类和 overview/struts-config.xml 文件来开发 Overview Struts portlet,请在操作类和 JSP 文件中遵循这些开发任务:

  1. 一旦控制权从 default 模块转移到 Overview 模块,OverviewAction 类中的 execute() 方法会执行以下这些任务:
    • 访问 OverviewFormBean 表单 bean 并设置以下属性:

      
      try
      {
      String forwardName = null;
      if (form == null)
      {
           form = (ActionForm) request.getAttribute("overviewFormBean");
      }
      //Set-up form bean fields
      OverviewFormBean formBean = (OverviewFormBean) form;
      formBean.setPhoneNumbersLinkName("List Phone Numbers");
      formBean.setAddressLinkName("Address Information");
      ...................................................

    • 在正确的作用域内存储该表单 bean:

      
      try
      {
           //Store the bean in the correct scope
           if ("request".equals(mapping.getScope()))
                   request.setAttribute(mapping.getName(), formBean);
           else
                   session.setAttribute(mapping.getName(), formBean);
      }
      catch (Exception e)
      {
                   ..................................
      }

    • overview/struts-config.xml 中查找映射并返回一个 ActionForward 类型的对象:

      
      String forwardName = null;
      ActionForward forward = new ActionForward();
      .......................................
      //If no errors occur then look for "success"
      try
      {
           forward = mapping.findForward(forwardName);
           if (forward != null)
           {
           .....................................
           }
      else
           .....................................
      }
      catch(Exception e)
      {
           ...................................
      }
      return (forward);

    • 如果在操作类的处理过程中没有出现错误,那么根据我们在 overview/struts-config.xml 文件中的配置,转发名称 success 会允许启动 Overview.jsp
  2. Overview.jsp 显示两个链接,指向已开发的其他 portlet——Receive Phone Numbers Request Struts Portlet 和 Receive Address Request Struts Portlet。我们使用页面导航方法和 Struts 标记来实现这一特征:
    • 在 JSP 页面的最开始的地方使用 taglib 指示来使所有的 engine.tld 标记可用于剩余的带有 prefix.wps 的 JSP 页面。

      <%@ taglib uri="/WEB-INF/tld/engine.tld" prefix="wps" %>
      

    • <wps:urlGeneration> portlet 标记中使用 contentNode 参数来指定驻留其他 portlet 的页面的惟一标识符或自定义名称。为了启动到 Receive Address Request Struts Portlet(位于 Struts_Receiver 页面)的页面导航,我们使用了自定义名称 Struts_Receiver_Page

      
      <wps:urlGeneration contentNode="Struts_Receiver_Page">
           <A HREF="<%wpsURL.write(out);%>"style="text-decoration:none" >
           <bean:write name="overviewFormBean" property="addressLinkName" /></a>
      </wps:urlGeneration>

    • 为了启动到 Receive Phone Numbers Request Struts Portlet(位于 Struts_Receiver_2 页面)的页面导航,我们使用自定义名称 Struts_Receiver_2_Page

      
      <wps:urlGeneration contentNode="Struts_Receiver_2_Page">
           <A HREF="<%wpsURL.write(out);%>"style="text-decoration:none" >
           <bean:write name="overviewFormBean"
           property="phoneNumbersLinkName" /></a>
      </wps:urlGeneration>
      

    • 这样我们就从 My Pages 和惟一名称列表获得了页面的自定义名称,如图 2 所示。
  3. overview 模块中,我们使用 <bean:write><html:html> <html:form> Struts 标记。实现这些标记需要以下的步骤:
    • 声明 html bean 前缀:

      
      <%@ taglib uri="/WEB-INF/tld/struts-html.tld" prefix="html" %>
      <%@ taglib uri="/WEB-INF/tld/struts-bean.tld" prefix="bean" %>
      

    • <html:html> Struts 标记:如果在用户会话中有可用的当前地点,就会以适当的语言属性来呈现 HTML 元素。
    • <html:form> Struts 标记:用于在 Struts 中的所有 HTML 表单处理。form 元素必须始终包含 action 属性。action 属性必须符合 struts-config.xml 中的有效操作。在 Overview.jsp 文件中,我们使用 form 元素和它的 action 属性:

      
      <html:form action="/start">
      

      start 属性映射 overview/struts-config.xml 文件中的下列操作:

      
      <action-mappings>
           <action  path="/start"
                type="com.test.strutstest.actions.OverviewAction"
                name="overviewFormBean"
                scope="request">
           <forward name="success" path="/Overview.jsp"/>
           </action>
      </action-mappings>

      Struts 标记将表单字段和 Struts 中的表单 bean 连结在一起。根据用于相关联的 ActionMapping 的表单 bean 规范定位(或生成,如果有必要)表单 bean。我们在 overview/struts-config.xml 文件中定义的表单 bean 为 UserFormBean

      
      <form-beans>
           <form-bean  name="overviewFormBean" type="com.test.strutstest.forms.OverviewFormBean"/>
           </form-beans>

    • <bean:write> Struts 标记的使用:

      这一通用标记用于从 bean 输出特性值。在 Overview.jsp 文件中,它显示 <bean:write> 来显示在 UserFormBean 表单 bean 中设置的文本数据。我们使用这一标记来显示 UserFormBean 的某些特性,如下所示:

      
      <bean:write name="overviewFormBean" property="addressLinkName" />
      <bean:write name="overviewFormBean" property="phoneNumbersLinkName" />

开发其余的模块
开发 addressphone-numbers 模块与开发 overview 模块非常类似,不同之处在于:

  • address 模块实现 Receive Address Request Struts Portlet 使用的是:
    • address.jsp
    • DisplayAddressInfoAction class
    • UserFormBean form bean class
    • UserBean backend bean class
    • UserBeanHelper model class
    • address/struts-config.xml file.
  • phone-numbers 模块实现 Receive Phone Numbers Request Struts Portlet 使用的是:
    • phone-numbers.jsp
    • DisplayPhoneInfoAction class
    • UserFormBean form bean class
    • UserBean backend bean class
    • UserBeanHelper model class
    • phone-numbers/struts-config.xml.

对于 addressphone-numbers 模块,我们使用的都是后端 UserBean bean 类和 UserBeanHelper 模型类,这两个类都需要使用存根数据来模拟用户信息,而存根数据是使用我们的模块类在后端 bean 中设置的。这两个模块都使用同样的表单 bean。

要在 DisplayAddressInfoAction 类中开发 address 模块需要做的是:

一旦控制权从 default 模块转移到 address 模块,DisplayAddressInfoAction 类的 execute() 方法就会执行以下任务:

  1. 访问表单 bean——UserFormBean,并设置以下属性:

    
    try
    {
         String forwardName = null;
    if (form == null)
    {
              form = (ActionForm) request.getAttribute("userFormBean");
    }
         //Set-up form bean fields
         UserFormBean formBean = (UserFormBean) form;
         setFormBean(formBean);
         ...................................................
    

  2. 在正确的作用域中存储该表单 bean:

    
    try
    {
         ........................................
         //Store the bean in the correct scope
         if ("request".equals(mapping.getScope()))
              request.setAttribute(mapping.getName(), formBean);
         else
              session.setAttribute(mapping.getName(), formBean);
    }
    catch (Exception e)
    {
         ..................................
    }
    

  3. address/struts-config.xml

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多