IBM®
跳转到主要内容
    中国 [选择]    使用条款
 
 
Select a scope: Search for:    
    首页    产品    服务与解决方案     支持与下载    个性化服务    
跳转到主要内容

developerWorks 中国  >  WebSphere  >

IBM WebSphere 开发者技术期刊: 使用新的 Remote Request Dispatcher 在 Web 应用程序中无缝包含远程文件

developerWorks
文档选项

未显示需要 JavaScript 的文档选项

样例代码


级别: 中级

Stephan Hesmer (stephan.hesmer@de.ibm.com), 性能首席开发师, IBM 
Curtiss Howard (cjhoward@us.ibm.com), Software Engineer, IBM 
Todd Kaplinger, WebContainer and RRD Architect, IBM 
Max Moldenhauer (mmolden@us.ibm.com), Staff Software Engineer, IBM 
Timo Kussmaul (TIMO@de.ibm.com), Software Engineer, IBM 

2006 年 11 月 13 日

Remote Request Dispatcher 是 IBM® WebSphere® Application Server V6.1 中的新功能,它提供了在您的 Web 应用程序中无缝包含远程 WAR 文件的方法。了解 Remote Request Dispatcher 的强大功能、如何扩展远程调用以便将自定义数据通过网络传递到远程系统,以及如何将 Remote Request Dispatcher 应用到门户环境(其中 Portlet 聚合框架可以使用此技术包含远程 Portlet)。

摘自 IBM WebSphere 开发者技术期刊

引言

Remote Request Dispatcher (RRD) 是 Web 容器的可插入扩展,可以使应用程序框架、Servlet 和 JavaServer™ Pages 能够作为发送到客户端的响应的一部分而包含当前执行资源的 Java 虚拟机 (JVM) 以外的内容。

RRD 是可扩展的基础结构,可以使其他组件和堆栈产品能够将自定义扩展(如生成器和处理程序)添加到 RRD 扩展。RRD 增强了标准 J2EE™ javax.servlet.RequestDispatcher 实现,使之能够使用 Web 服务查找远程资源,以便在 WebSphere Application Server Network Deployment 核心组中的计算机之间进行通信。RRD 扩展可以将远程服务器上发生的任何错误报告给发起服务器。它还可以利用 SSL 进行安全通信,并利用 WS-Security 在服务器之间进行安全上下文传播。

RRD Portlet 支持将 RRD 概念引入 Portlet,并增强了 Portlet 容器,使之可以调用当前执行资源的 JVM 外部的 Portlet。

利用 RRD 扩展,您可以通过在计算单元中包含远程服务器而在多个计算机和 JVM 之间共享请求负载。如果 RRD 资源是内存密集型的或处理器密集型的,那么调用资源不会像在同一 JVM 中运行的标准 RequestDispatcher 那样受到较大影响。RRD 通过将资源分到不同的 JVM 解决了此问题。

关于示例

本文提供的示例旨在演示 RRD,从一个简单的基础用例开始,然后介绍一些较复杂的用例。前四个示例的设计以前面每个示例的演示内容为基础。最后一个示例与其他示例无关,它演示如何扩展 RRD 以便支持 Portlet。

下面是示例的摘要,在后续部分中将对每个示例进行详细的描述:

  1. 示例 1 是通常使用的“Hello World”应用程序的 RRD 等效项。在本示例中,本地服务器 (AppServerLocalNode) 允许 RRD 调用远程服务器 (AppServerRemoteNode) 并输出“hello”。

  2. 示例 2 构建在示例 1 基础之上,并且还利用了 J2EE 安全。在本示例中,定义了三个角色:LocalRole、RemoteRole 和 BothRole。在本地和远程服务器上,输出了与应用程序关联的多个角色,并指示是否将已登录的用户映射到该角色。

  3. 示例 3 构建在示例 2 基础之上,并且还利用了动态缓存,即用于缓存响应内容的 Webphere 扩展。在本示例中,AppServerRemoteNode 的内容缓存在 AppServerLocalNode 上,它支持要完成的请求,无需联系 AppServerRemoteNode,因为先前调用请求的响应存在一个缓存副本。

  4. 示例 4 构建在示例 3 基础之上,并且还演示了如何使用 RRD 扩展生成器和处理程序框架扩展 RRD。在本示例中,扩展处理程序和扩展生成器已被定义为在 AppServerLocalNode 和 AppServerRemoteNode 之间传递附加信息。

  5. 示例 5 演示如何扩展 RRD 以便利用 Portlet。在本示例中,AppServerLocalNode 和 AppServerRemoteNode Servlet 位于两个不同的时区中,每个 Servlet 都附带相同的 Standard World Clock Portlet,分别安装在各自的应用服务器上。

拓扑

RRD 需要 IBM WebSphere Application Server Network Deployment (以下称为 Network Deployment)。本文假设 RRD 用户熟悉 Network Deployment 和与 Network Deployment 关联的集群技术。本文主要针对已熟悉 Java Servlet API 的 Java™ Web 应用程序编程人员而编写。有关指向可以帮助您获得这些技能的信息的链接,请参阅参考资料





回页首


第一步

示例 1 中的服务器由两个集群(LocalCluster 和 RemoteCluster)组成,每个集群包含单一节点和集群成员。集群拓扑的图形表示形式如图 1 所示。


图 1. 集群拓扑包含两个集群,每个集群附带一个节点和一个集群成员
集群拓扑包含两个集群,每个集群附带一个节点和一个集群成员

为应用程序安装并启用 Remote Request Dispatcher

RRD 通过在应用程序安装过程中在企业应用级别指定的两个属性(用于分派和服务 RRD 包含)而启用:

1. 将 Web 应用程序配置为分派远程包含

您可以使用管理控制台脚本来执行此配置。

2. 将 Web 应用程序配置为服务远程包含

另外,您还可以使用管理控制台脚本来执行此配置。

a. 要使用 wsadmin 脚本接口(而不是使用控制台)安装同一应用程序,请执行以下脚本逻辑:

cd C:\wasinstall\bin
wsadmin
$AdminApp install C:/rrdArticle/RRDExample_v1_remote.ear {-cluster RemoteCluster 
–allowServiceRemoteInclude}
$AdminConfig save

示例 1

此示例将阐释最简单的 RRD 用例,它包含在 JSP 上执行远程包含的本地 Servlet。要安装并运行该示例,请执行以下操作:

  1. 使用 WebSphere Application Server 管理控制台将 RRDExample_v1_local.ear 安装到 AppServerLocalNode。在安装过程中,确保选中 Allow dispatching includes to remote resources 选项。保存您的更改,并启动应用程序。

  2. 使用管理控制台将 RRDExample_v1_remote.ear 安装到 AppServerRemoteNode。在安装过程中,确保选中 Allow servicing includes from remote resources 选项。保存您的更改,并启动应用程序。

  3. 通过以下 URL 访问该示例:http://localhost:9080/rrd_example_v1_local/invoke。确保使用您的 WebSphere Application Server 的主机和端口值分别替换 localhost9080。如果示例安装正确,则出现的屏幕应类似于图 8。



    图 8. 来自远程包含的 jsp 的 Hello world
    来自远程包含的 jsp 的 Hello world

  4. 在 RRDExample_v1_local.ear 的 RRDExample_v1_local_web.war 中检查本地 Servlet 源,该源是文件 WEB-INF/source/com/ibm/ws/rrd/example/servlet/RRDLocalServlet.java。doPost() 方法中的相关部分说明了以下示例中执行的远程包含:

    getServletContext().getContext 
    ("/rrd_example_v1_remote").getRequestDispatcher
    ("/invoke.jsp").include (request, response);

这是一个标准的请求分配器包含。不过,由于我们在该本地应用程序和远程应用程序上都启用了 RRD,所以可以跨应用服务器无缝执行该包含。





回页首


安全

让我们查看一下 RRD 中的安全功能,包含 SSL(安全套接字层)和 Web 服务令牌传播。

因为 RRD 可以将敏感信息作为消息的一部分在本地服务器和远程服务器之间传输,所以不管最初请求的连接是否在 HTTP 或 HTTPS 端口上进行,建议都通过 SSL 连接进行此通信。为适应此需求,RRD 需要检查安全属性 SSLRequired。在启用此属性时,将始终使用 SSL。如果禁用此属性,将使用初始请求上使用的同一连接类型。通过位于 <was_install>/profiles/<profileName>/properties 的 rrdSecurity.props 文件可以配置 RRD 安全设置。

因为 RRD 可以利用 Web 服务,所以我们还可以利用 Web 服务安全(WS 安全)的某些功能将安全上下文传播到远程应用服务器。这样可以使用 javax.servlet.HttpServletRequest 安全方法 java.security.Principal getUserPrincipal ()() 和 boolean isUserInRole(java.lang.String 角色)。由 Web 服务传播的 LTPA 令牌包含此用户主体。在本地和远程两端必须同时提供用户到角色的映射,在任何两个不同的 Web 模块之间都需要此映射。RRD 安全属性 LTPAPropagation 指示应启用此功能。根据 Servlet Specfication Version 2.4 SRV.12.2,在包含或转发时不检查安全性,所以,如果不需要这些 API,管理员可以禁用此属性。

还可以作为 LTPA 令牌的属性启用 RRD 安全属性 SecurityAttributePropagation,以传递自定义安全令牌。安全属性传播支持使用与 CSIv2 支持中相同的可插入 JAAS Login 模块。此 WS 安全功能的详细讨论不在本入门指南的范围之内。有关详细信息,请参阅参考资源

通过位于 <was_install>/profiles/<profileName>/properties 的 rrdSecurity.props 文件可以配置 RRD 安全设置。此文件的格式为(bold 为缺省值):

LTPAPropagation=( True |False)
SecurityAttributePropagation=(True|
False )
SSLRequired=(
True |False)

本地和远程应用服务器之间的这些属性必须相同。要使 rrdSecurity.props 文件的更改生效,必须重新启动应用服务器。

示例 2

此示例构建在示例 1 中的应用程序之上,添加了资源约束并演示了 RRD 的传播授权信息的能力。要安装并运行该示例,请执行以下操作:

  1. 使用 WebSphere Application Server 管理控制台启用应用程序安全。(请参阅 WebSphere Application Server V6.1 信息中心。)
  2. 将 RRDExample_v2_local.ear 安装到 AppServerLocalNode,如示例 1 中的步骤 1 所示。
  3. 将 RRDExample_v2_remote.ear 安装到 AppServerRemoteNode,如示例 1 中的步骤 2 所示。
  4. 使用管理控制台,导航到 Applications => Enterprise Applications => RRDExample_v2_local => Security role to user/group mapping
  5. 选择 LocalRoleBothRole,然后选择 Look up users
  6. 选择用户,然后单击 OK。保存更改。
  7. 导航到 Applications => Enterprise Applications => RRDExample_v2_remote => Security role to user/group mapping
  8. 选择 RemoteRoleBothRole,然后选择 Look up users
  9. 选择用户,并单击 OK。保存更改。
  10. 通过 URL:http://localhost:9080/rrd_example_v2_local/invoke 可以访问该示例,再将 localhost9080 更改为适当的值。如果示例安装正确,在步骤 6 和步骤 9 中选择的用户身份登录后,将显示图 9 所示的屏幕。

图 9. 带有安全传播的 RRD
带有安全传播的 RRD

在本例中,在本地 Servlet 上为授权角色 LocalRole 启用资源约束。 我们接着使用它将安全上下文传播到在 AppServerRemoteNode 上运行的示例应用程序。 正如示例中所显示的,用户到角色的映射不同于 AppServerLocalNode 上运行的本地 Servlet 和 AppServerRemoteNode 上运行的远程 JSP。





回页首


缓存

执行 RRD 调用的开销非常大。创建表示请求和响应的消息,并跨网络传输这些数据会产生巨大的开销。在用于 RRD 调用的目标服务器上进行缓存有一定的帮助,但是不能始终足以提供有价值的性能改进。

要增强性能,本地计算机必须了解远程服务器的缓存规则,并知道何时进行本地缓存响应,以防止一起调用 Web 服务。通过使用现有的动态缓存 API 来存储响应映射的 RRD 唯一缓存项,我们可以防止普通缓存场景的远程跳跃。动态缓存向来是 WebSphere Application Server 的性能特征。WebSphere Application Server 信息中心提供了更详细的信息。

为了解远程缓存规则,RRD 将通知动态缓存发送响应标头,它是远程应用程序的 cachespec.xml 文件(即缓存配置文件)的表示形式。此响应标头包含 RRD 支持的缓存规范的相应规则。RRD 会截取响应内容,并检查是否可以在将结果发送回客户端之前进行本地缓存响应。然后检查随后的请求,以查看它们是否匹配先前缓存的任何项。如果远程缓存规范通常使用 RRD 不支持的规则,那么最好禁用本地缓存,因为未缓存请求的开销稍微大些。在本地和远程计算机上启用 Servlet 缓存时,支持以下规则:

  • parameters——检索命名的参数值。
  • cookie——检索命名的 cookie 值。
  • header——检索命名的请求标头。
  • locale——检索请求位置。
  • requestType——从请求检索 HTTP 请求方法。

WebSphere Application Server V6.1 信息中心提供了有关所有规则(包含 RRD 支持的和不支持的规则)的信息。

缓存规则通常有一个时间段,在该时间段中等待以使缓存项失效。远程失效操作必须被传回给RRD 缓存,以使其在本地失效。 要支持这种失效操作, DynaCacheEsi 应用程序必须被安装在本地 RRD Web 模块所在的同一台虚拟主机上<was_install>/installableApps/DynaCacheEsi.ear 中提供了此应用程序。

示例 3

此示例构建在示例 2 中的应用程序之上,并演示如何使用 RRD 请求中的动态缓存。要安装和运行该示例,请执行以下操作:

  1. 请按照示例 2 中的步骤 1 至步骤 9 使用应用程序 RRDExample_v3_local.ear 和 RRDExample_v3_remote.ear。请注意,对应用程序 RRDExample_v3_local 和 RRDExample_v3_remote 应分别执行步骤 4 和步骤 7 中的用户到角色的映射。
  2. 通过 URL http://localhost:9080/rrd_example_v3_local/invoke 访问该示例,再将 localhost9080 的值替换为适当的值。

如果示例安装正确,以步骤 1 中选择的用户身份登录后,您会看到以下结果:


图 10. 使用计数器值观察缓存行为的 RRD
使用计数器值观察缓存行为的 RRD

页面底部的计数器值以 0 开始,并且每增加一个请求,值增加 1。如果通过 URL http://localhost:9080/rrd_example_v3_local/invoke?cache=true 访问该示例,则会触发动态缓存,并将缓存随后的请求。此示例中使用的缓存规范演示了如何使用基于请求参数的缓存,可以在 RRDExample_v3_remote.ear 的 RRDExample_v3_remote_web.war 中找到它,即 WEB-INF/cachespec.xml 文件。





回页首


使用自已的数据扩展远程调用

RRD 提供了灵活的机制,允许应用程序通过附加自定义数据来扩展 RRD 请求,从而使应用程序能够将特定的应用程序上下文传递到远程系统。本部分将介绍中心扩展概念,描述由 RRD 定义的适用的 Java 接口和扩展点,并阐述与 Eclipse Modeling Framework (EMF) 的关系。

RRD 扩展由扩展生成器扩展处理程序 对组成。扩展生成器是一个 Java 类,负责将一个扩展数据元素 附加到 RRD 请求。接收 RRD 请求后,扩展处理程序负责处理扩展数据元素。

扩展链

扩展生成器或扩展处理程序的序列称为扩展链。RRD 在启动 RRD 请求之前调用扩展生成器链。扩展处理程序链在接收 RRD 请求时执行,方法是调用每个与附加到 RRD 请求的某些扩展数据匹配的扩展处理程序。

扩展生成器链和扩展处理程序链在相应的扩展点文件 plugin.xml 中定义,该文件位于下列位置之一:

  • 另一个 OSGI 包
  • 任何共享的库
  • 在支持 RRD 的 Web 应用程序的 WEB-INF 目录中。

在扩展点 com.ibm.wsspi.rrd.generators 中定义了扩展生成器链;每个扩展生成器由生成器元素定义。因而,在 com.ibm.wsspi.rrd.handlers 扩展点定义了扩展处理程序链,并且每个扩展处理程序由一个处理程序元素定义。

生成器和处理程序元素由以下属性组成:

  • id——分配关联扩展生成器和扩展处理程序的唯一标识符;即在匹配扩展生成器和扩展处理程序时,必须为此属性声明相同的值。
  • class——指定扩展生成器或扩展处理程序的类名。
  • order——在有多个描述符文件的环境中,强制按顺序执行;每个扩展生成器和扩展处理程序都可以具有与之关联的执行顺序。
  • type——定义生成器的类型;目前,为此属性指定的值为 servlet

此外,每个处理程序元素都包含 namespaceURI 和 localName 属性,二者共同定义扩展处理程序可以处理的扩展元素的限定名称。RRD 使用 ID 属性指定的此限定名称和标识符来查找用于扩展的匹配扩展处理程序。此外,可以为扩展生成器或扩展处理程序指定初始化参数,参数可以包含 0 或作为生成器或处理程序元素的子元素的更多初始化参数元素。

扩展生成器声明的示例为:

    <extension point="com.ibm.wsspi.rrd.generators">
    <generator id="int1" class="com.ibm.ws.rrd.example.extension.IntExtensionGenerator"
            order="1" type="servlet">
      <init-param>
        <param-name>intValue</param-name>
        <param-value>123</param-value>
      </init-param>
    </generator>
    <generator id="string1" 
               class="com.ibm.ws.rrd.example.extension.StringExtensionGenerator"
               order="2" type="servlet">
      <init-param>
        <param-name>stringValue</param-name>
        <param-value>This is an example string.</param-value>
      </init-param>
    </generator>
  </extension>

下面显示了扩展处理程序声明的示例:

<extension point="com.ibm.wsspi.rrd.handlers">
    <handler id="int1"
             class="com.ibm.ws.rrd.example.extension.IntExtensionHandler"
             namespaceURI="http://www.ibm.com/rrd/example/types"
             localName="ExampleType" order="1" type="servlet" />
    <handler id="string1"
             class="com.ibm.ws.rrd.example.extension.StringExtensionHandler"
             namespaceURI="http://www.ibm.com/rrd/example/types"
             localName="ExampleType" order="2" type="servlet" />
</extension>
			

扩展生成器

扩展生成器必须实现接口 ExtensionGenerator:

public interface ExtensionGenerator {
     ExtensionGeneratorConfig getExtensionGeneratorConfig ();
     void init (ExtensionGeneratorConfig config) throws RRDException;
     void doGenerate (ExtensionGeneratorRequest request,
               ExtensionGeneratorResponse response, ExtensionChain chain)
               throws RRDException, IOException;
     void destroy ();
}
			

扩展生成器必须遵守扩展生成器生命周期:

  • 初始化
  • 生成
  • 销毁。

在初始化支持 RRD 的应用程序的本地部分时,会解析 RRD 扩展生成器描述符,并使用解析的 ExtensionConfig 对象初始化每个扩展生成器。然后将每个扩展生成器放置在扩展生成器链中。在发送每个 RRD 请求之前,通过按顺序调用每个扩展生成器上的 doGenerate 方法来执行此链。然后,借助提供的 ExtensionGeneratorRequest 对象,每个扩展生成器会将 EMF 对象的实例添加到出站 RRD 请求的标头、正文或附加到两者。因此,ExtensionGeneratorRequest 分别提供了两个方法 setHeaderObject 和 setBodyObject。此 EMF 对象包含在 RRD 请求中,可用于远程系统上的匹配扩展处理程序。然后,每个扩展生成器通过调用传递的 ExtensionChain 对象的 doNext 方法,负责执行扩展生成器链的下一部分。

支持远程 RRD 的应用程序接收并处理 RRD 请求后,可以将一系列扩展附加到支持本地 RRD 的应用程序接收的 RRD 响应。扩展生成器链中的每个扩展生成器都可以潜在地从此 RRD 响应接收扩展数据,通过 getHeaderObject 和 getBodyObject 方法从提供的 ExtensionGeneratorResponse 实例检索该响应。此(可选)处理发生后,在创建另一个 RRD 请求之前完成扩展生成器链的执行。

在应用服务器终端上,通过调用其销毁方法销毁每个扩展生成器。此时,应释放与扩展生成器关联的任何永久性资源。

扩展处理程序

扩展处理程序必须实现以下接口:

public interface ExtensionHandler {
     ExtensionHandlerConfig getExtensionHandlerConfig();
     void init (ExtensionHandlerConfig config) throws RRDException;
     void doHandle (ExtensionHandlerRequest request,
          ExtensionHandlerResponse response, ExtensionChain chain)
          throws RRDException, IOException;
     void destroy ();
}
			

扩展处理程序遵循扩展处理程序生命周期:初始化、处理和销毁,发生的过程如下:

当初始化支持 RRD 的应用程序的远程部分时,会使用与扩展处理程序描述符对应的 ExtensionConfig 解析对象启动每个扩展处理程序。然后将每个扩展处理程序放置在扩展处理程序链中。在接收到 RRD 请求时通过调用每个扩展处理程序(与附加到 RRD 请求的一些扩展数据的限定名称 匹配)上的 doHandle 方法来执行此链。每个扩展处理程序然后借助提供的 ExtensionHandlerRequest 对象来处理接收的扩展数据(这些数据可能位于 RRD 请求的标头、正文或同时位于二者中)。接着,每个扩展处理程序负责执行扩展链的下一个处理程序。

执行完扩展处理程序链后,将创建 RRD 响应,每个扩展处理程序都有机会通过提供的 ExtensionHandlerResponse 实例将 EMF 对象作为扩展数据附加到响应中;然后此扩展数据由支持 RRD 的应用程序本地部分上的适当扩展生成器接收。此(可选)处理发生后,在接收另一个 RRD 请求之前完成扩展处理程序链的执行。

在应用服务器终端上,通过调用其销毁方法销毁每个扩展处理程序。

类 GenericExtensionGenerator 和 GenericExtensionHandler 定义处理基本初始化和配置方法的抽象类。这两个类是新扩展生成器或扩展处理程序类的基础,示例 4 对此进行了说明。

EMF 与 RRD 的集成

RRD 将 Eclipse Modeling Framework (EMF) 用作序列化和反序列化任意扩展数据的方法,以便与扩展生成器和处理程序结合使用。此方法为 RRD 提供了极大的灵活性,这样可以非常容易地通过现成的工具(如为 Eclipse 提供的 EMF 插件)完成将扩展数据添加到远程调用这一过程。关于 EMF 的概念不在本文讨论的范围内,但是,如果您不熟悉 EMF,用 Eclipse Modeling Framework 实现模型驱动开发 是一篇优秀的入门文章。对于本文而言,我们假设您已具备 EMF 方面的知识。

为您的模型生成代码后,基本上就可以将其与 RRD 扩展生成器和处理程序对结合使用了。需要注意的重要一点是,RRD 会使用扩展的元数据注释将 EMF 序列化和反序列化为 XML 数据,这种情况通常不是 EMF 的一般用法。因此,通常不需要在启用扩展的元数据注释时 EMF 使用的根元素名称,应将该名称更改为更接近于在模型中定义的名称(但这不是严格的要求)。生成模型代码后,请找到生成的包实现类(这应该是一个以 PackageImpl.java 结尾的文件名)。查找方法 createExtendedMetaDataAnnotations()。应更改对方法 addAnnotation() 的第一个调用,以反映所需的根元素名称。示例 4 中使用的以下代码对此进行了说明:

addAnnotation (exampleTypeEClass, source, new String[] { "name", "exampleType_._type",
"kind", "elementOnly" });

如果生成的代码保留原样,则将把 exampleType_._type 用作根元素名称对扩展数据进行序列化和反序列化。只要扩展生成器和处理程序扩展点反映这一点,就是可以接受的。不过,这样根元素名称并不直观,因此不需要此名称;在示例中,我们将此名称更改为 ExampleType,它与模型中使用的名称匹配。

最后,我们必须确保在使用之前正确初始化了由 RRD 扩展生成器和处理程序使用的已生成 EMF 包。尽管可以在扩展生成器和处理程序内部显式执行此操作,但完成此操作的最方便的方法是让 RRD 通过 com.ibm.wsspi.rrd.rrd-emf-packages 扩展点自动初始化 EMF 包。所以,除了在 plugin.xml 中定义扩展生成器和处理程序外,还应定义 com.ibm.wsspi.rrd.rrd-emf-packages 扩展点,并包含必须初始化的每个 EMF 包的项。

以下代码示例说明了此过程:

<extension point="com.ibm.wsspi.rrd.rrd-emf-packages">
  <emfPackages>
    <emfPackage className="com.ibm.ws.rrd.example.types.impl.TypesFactoryImpl" />
</emfPackages>
</extension>
			

虽然 RRD 正在初始化 EMF 包,但是每个 emfPackage 元素的 className 属性必须指向 EMF 生成的工厂实现类。此类以 FactoryImpl.java 结尾。请记住,必须为本地和远程应用程序同时定义这一相同的扩展点。

示例 4

此示例构建在示例 3 中的应用程序之上,并演示了 RRD 通过使用扩展生成器和处理程序传递数据的功能。要安装和运行该示例,请执行以下操作:

  1. 按照示例 3 中的步骤使用应用程序 RRDExample_v4_local.ear 和 RRDExample_v4_remote.ear。应分别在对应的应用程序 RRDExample_v4_local 和 RRDExample_v4_remote 上执行用户到角色的映射。
  2. 通过下列 URL 可访问该示例(使用适当的值替换 localhost9080):http://localhost:9080/rrd_example_v4_local/invoke。如果示例安装正确,在选择的用户身份登录后,您可以看到如图 11 中的结果:

图 11. 使用扩展生成器发送附加数据的 RRD
使用扩展生成器发送附加数据的 RRD

示例中的其他输出由扩展生成器和处理程序生成。本地应用程序的相关文件位于 RRDExample_v4_local.ear 中的 RRDExample_v4_local_web.war 中,这些文件有:

  • WEB-INF/plugin.xml——包含扩展生成器的定义。
  • WEB-INF/source/com/ibm/ws/rrd/example/extension/IntExtensionGenerator.java——包含生成整数数据的示例扩展生成器。
  • WEB-INF/source/com/ibm/ws/rrd/example/extension/StringExtensionGenerator.java——包含生成字符串数据的示例扩展生成器。

类似地,远程应用程序的相关文件也位于 RRDExample_v4_remote.ear 中的 RRDExamlpe_v4_remote_web.war 中,这些文件有:

  • WEB-INF/plugin.xml——包含扩展处理程序的定义。
  • WEB-INF/source/com/ibm/ws/rrd/example/extension/IntExtensionHandler.java——包含处理整数数据的示例扩展生成器。
  • WEB-INF/source/com/ibm/ws/rrd/example/extension/StringExtensionHandler.java——包含处理字符串数据的示例扩展生成器。

文件 RRDExample_v4_types.src.jar 包含模型和生成的 EMF 源代码,用于操作此示例使用的扩展数据类型。使用自已的数据扩展远程调用EMF 与 RRD 的集成两部分都包含有关 RRD 创建和使用扩展生成器和处理程序的方式的信息。





回页首


聚合远程 Portlet 的门户

也可以将 Remote Request Dispatcher 与 Portlet 结合使用。为此,我们利用了 WebSphere Application Server V6.1 中 Portlet 容器附带的 Portlet 聚合框架。(文章 Exploiting the WebSphere Application Server V6.1 portlet container, Part 2 详细介绍了聚合功能。)

Portlet 聚合框架可以使用标记库在一个页面上聚合多个 Portlet。框架利用 URL 的寻址功能包含 Portlet 应用程序。在此上下文中,包含 一词是字面意义,因为框架使用 Servlet 的 include 方法来请求分配器。因此,Remote Request Dispatcher 也适用于此场景。

正如前面提到的,要将 RRD 用于 Portlet,我们需要一个门户框架应用程序、至少一个 Portlet 应用程序和一个部署安装程序。必须使用 Allow dispatching includes to remote resources 选项部署门户框架,并且必须使用 Allow servicing includes from remote resources 选项将 Portlet 应用程序安装到不同的服务器。

示例 5

示例应用程序由一个应用程序组成,它使用 JSP 来呈现具有两列的表,每列包含一个 World Clock Portlet 实例(可以从文章 探索 WebSphere Application Server V6.1 Portlet 容器: 第 1 部分:Portlet 容器介绍 下载该实例)。

使用与前一部分中相同的安装过程将 RRDSamplePortal.ear 安装到 server AppServerLocalNode。您必须选中选项 Allow dispatching includes to remote resources,否则远程请求分派将无法工作。

安装并启动应用程序后,我们可以使用 http://localhost:9080/sample/portal 访问门户应用程序。图 12 显示了在正确部署全部内容后门户应用程序的情况。


图 12. 使用 RRD 聚合两个 Portlet
使用 RRD 聚合两个 Portlet




回页首


结束语

远程请求分派为应用程序部署提供了更大的灵活性,从而可以在 WebSphere Application Server Network Deployment 核心组的任何位置安装应用程序,而无需对应用程序进行重大更改。通过利用这一增强的灵活性,可以更好地将应用程序相互隔离,从而最大限度地减少了大多数基于 Web 的应用程序常见的单点故障问题。






回页首


下载

描述名字大小下载方法
Sample applicationrrd_article_examples.zip156 KBHTTP
关于下载方法的信息


参考资料

学习

获得产品和技术


作者简介

Stephan Hesmer 目前担任性能首席开发师。他担任的前一个职位是 WebSphere Portal 和 WebSphere Application Server 的 Portlet 运行时架构师。他负责将 JSR 168 Portlet 容器集成到 WebSphere Application Server 中。Stephan 曾从事 JSR 168 Java Portlet 规范方面的研究,并设计和实现了 JSR 168 参考实现的最初版本 Pluto。Stephan 于 2000 年获得了德国斯图加特联合教育大学 (University of Cooperative Education Stuttgart) 的信息技术专业的文凭,毕业后,他加入了 IBM B?blingen Development Laboratory,在 WebSphere Portal 团队工作。


Curtiss Howard 目前是 WebSphere Administrative Console、WebContainer 和 RRD 团员的成员。他从北卡罗来纳大学毕业并获得计算机科学学位后,于 2005 年加入 IBM WebSphere Application Server。


Todd Kaplinger 目前担任 WebSphere Application Server 的 WebContainer 和 RRD 团队的架构师和团队负责人。Todd 一直从事 JSR 154 Servlet 2.5 规范研究,并且是 IBM Servlet 专家组的代表。


Maxim Moldenhauer 目前是 WebContainer 和 RRD 团队的成员。Maxim 是从事 SIP Container 集成的 WebContainer 中心人物,他还设计了当前的 WebContainer 测试套件框架。他从弗吉尼亚理工大学毕业并获得计算机科学学位后,于 2003 年加入 IBM WebSphere Application Server。


Timo Kussmaul 目前是 WebSphere Application Server 和 WebSphere Portal 的软件开发人员。他从斯图加特大学计算机科学专业毕业后,于 1997 年加入 IBM。Timo 编写了三本关于应用程序软件和软件开发的书。




对本文的评价










回页首


IBM 公司保留在 developerWorks 网站上发表的内容的著作权。未经IBM公司或原始作者的书面明确许可,请勿转载。如果您希望转载,请通过 提交转载请求表单 联系我们的编辑团队。
    关于 IBM 隐私条约 联系 IBM 使用条款