Flex 学习

来自 http://www.chineselinuxuniversity.net/articles/25985.shtml
2009 年 7 月 15 日
借助 Rich Internet Application(RIA)的理念,Adobe® Flex 将您带到了 Web 应用程序开发的更高级别,而 IBM® WebSphere® Portal 则提供了复合工具来构建基于 SOA 的灵活解决方案。但是如何将这二者结合起来呢?一种方法是直接将 Flex 集成到 WebSphere Portal 服务器。本文带您亲历面向 WebSphere Portal 快速构建基于富客户端和组件的 Flex 应用程序的全过程,并提供了一种很有效的方法来减少 WAR 文件的大小。
先决条件
本文面向的读者是想要用 WebSphere Portal 集成应用程序的 Flex 开发人员。本文假设您对 Flex 的基本编程以及 Java™ 编程都比较熟悉。此外,本文的相关部分还需要您具有对 WebSphere Portal 服务器的管理员权限。不过,本文并不要求您熟悉 WebSphere Portal 的编程或管理。

为了跟随本文的学习,您需要安装如下工具以确保本文给出的示例能够很好地工作。

Adobe Flex Builder — 本文用 Adobe Flex Builder 3 进行编程。当然,您也可以用适当的 JDK 和文本编辑器进行编写,但额外的工作量会比较多。
WebSphere Portal V6.0.1 或更高 — 如果您使用的是 WebSphere Portal V6.0,则应该升级您的 WebSphere Portal V6 环境(参见 参考资料)。
IBM Rational Software Architecture v7.0.0
IBM DB2 Enterprise v9.1

示例应用程序概览

让我们简单看看这个名为 TODOList 的示例应用程序的业务要求。很多用户都希望能够为约会、周年纪念、提醒或其他的一些活动保留记录。而且他们还希望能够方便地查阅他们将来的一些内容项、创建新内容项或在需要的时候删除任意项。我们能否为他们的这种需要提供一种灵活的工具呢?在本文中,我们将向您阐释如何以一种类似于大多数开发人员创建应用程序的方式构建这个应用程序并展示完整的开发过程。

如下所示的图 1 给出了这个示例应用程序的基础架构。在用 Adobe Flex 和 IBM WebSphere Portal 构建实际的应用程序之前,我们先快速介绍一下这个示例的技术层面。整个应用程序将在一个 WAR 文件中构建,其中包括表示层和业务层模块,这些模块是在不同项目中开发的。

顶部的方框代表的是作为表示层的一个 Flex 项目,由 MXML 和 ActionScript 构建,底部的方框代表的是作为业务层的一个 Java 项目,由 Java 和 JDBC 构建。Flex 应用程序通过一个 RemoteObject 调用 Java 服务,RemoteObject 是 Flex 所提供的远端过程调用(RPC)组件之一。在这个示例应用程序内,我们将导入 BlazeDS 来实现这个远端对象。


图 1. 基础架构
Flex 学习
构建 Flex 项目

Adobe Flex 是一个高效、免费的开源框架,可用来构建和维护表述性的 Web 应用程序,这些应用程序被一致地部署在所有主要的浏览器、桌面和操作系统上。

它包含一个丰富的组件库,内有 100 多个经过证明的可扩展 UI 组件,可用来创建 RIA。它还提供一种基于标准的语言和编程模型,该模型支持常见的设计模式。MXML 是一种基于 XML 的声明式语言,用来表示 UI 布局和行为,并且每个 MXML 文件都是一个单独的组件。ActionScript 则是一种功能强大的面向对象的编程语言,用来创建客户逻辑。ActionScript 提供了 MXML 内所没有的流控制和对象处理特性。Flex 3 在 2008 年 2 月底发布,在 Adobe Flex Web 站点(参见 参考资料)可以更多地了解 Flex 3 的有关特性。

Flex 应用程序可以只使用免费的 Flex SDK 构建,Flex SDK 包含 Flex 框架(组件类库)和 Flex 编译器,让您能够使用自选的任意一个 IDE 自由开发和部署 Flex 应用程序。开发人员可以使用 Adobe Flex Builder 3 来显著加快开发。

Flex 向导会指导您如何快速轻松地在 Flex Builder 3 内创建这个示例。

打开 Flex Builder 3,并选择 File --> New --> Flex Project。
输入 TODOListFlex 作为项目名称。
选择 default 位置,作为项目的位置,也是我们的工作空间。
选择 Web application 作为应用程序类型。
对于应用服务器类型,如果有服务器,可能需要遵循 Adobe Flex 3 Help\Using Flex Builder 3\Flex Builder Basic\Working With Projects 内的步骤。但是在本例中,由于我们不需要这样,因此我们选择了 None,如图 2 的屏幕快照所示。

图 2. 新建 Flex 项目
Flex 学习

6为这个 Flex 应用程序保留全部默认设置并在接下来的两个配置页面中构建路径。
7单击 Finish 创建项目。
之后,Flex Builder 3 将生成一个主 MXML,名称与新项目的名称相同。这个应用程序包含一个 MXML 文件,并以 <mx:Application> 根标记开始,如清单 1 所示。

清单 1. MXML 应用程序根
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute">
</mx:Application>


在本节,您只需关注这个主要的文件 TODOListFlex.mxml。可以使用 Flex 导航视图将其他资源(MXML、ActionScript 和 Image)从我们的示例代码中导入到此项目。项目类别如图 3 所示。


图 3. Flex 项目类别
Flex 学习        
Flex Builder 3 内的 MXML 编辑器允许您在编辑器区域的顶部工作在 Source 或 Design 模式下。请确保您处于 Source 模式,然后添加一个 <mx:Panel> 组件作为主应用程序的子程序来表示 UI 布局,并在这个面板内放上一个 <mx:VBox> 组件并确保它被垂直放置。参见清单 2。


清单 2. 在 MXML 文件内添加面板和 VBox
<mx:Panel title="TODO List" width="100%" height="100%" 
   paddingLeft="4" paddingTop="8" paddingRight="8" paddingBottom="4">
   <mx:VBox width="100%">
   </mx:VBox>
</mx:Panel>


在 <mx:VBox> 标记之间放上一个 <mx:DataGrid> 组件以列出所有 to-do 项。定义一个 ArrayCollection todoItemColl 并将其指派为 DataGrid 的 dataProvider(参见清单 3)。在 “在 Flex 中使用 RemoteObject” 一节中,我们将会调用 RemoteObject 服务来为此 ArrayCollection 获得数据。


清单 3. 在 VBox 内添加 DataGrid
<mx:DataGrid id="todoListDG" dataProvider="{todoItemColl}">
   <mx:columns>
   <mx:DataGridColumn visible="false" dataField="id"/>
   <mx:DataGridColumn width="100" headerText="Date" dataField="deadlineStr"/>
   <mx:DataGridColumn width="400" headerText="Subject" dataField="task"/>
   ...
   </mx:columns>
</mx:DataGrid>


在 VBox 下有一个表单,允许用户添加新的 to-do 项。此表单包含三个文本字段(Date、Subject 和 Owner)和一个按钮。我们使用一个 <mx:Grid> 组件来控制这个 UI 的对齐(参见清单 4)。


清单 4. 为项目表单添加网格
<mx:Grid>
   <mx:GridRow>
      <mx:GridItem> 
         <mx:Label text="Date:"/>
      </mx:GridItem>
      <mx:GridItem>
         <mx:DateField id="deadlineDateField" formatString="YYYY-MM-DD"/>
      </mx:GridItem>
   </mx:GridRow>
   ...
   <mx:GridRow>
      <mx:GridItem colSpan="2" horizontalAlign="right">
         <mx:Button label="Add" click="saveNewItem()"/>
      </mx:GridItem>
   </mx:GridRow>
</mx:Grid>


之后,我们再在 <mx:Script> 标记内用 ActionScript 代码创建客户逻辑并将内容包装成一个 CDATA 结构(参见清单 5)。为了访问不同的数据源,我们定义了一个常量 USE_MOCK_DATA 来控制此应用程序是否可以访问远端数据或本地 mock 数据。现在,我们将常量值设置为 true,这是因为我们此时只需将其显示为一个单独的应用程序。我们在随后的 “在 Flex 内使用 RemoteObject” 一节中将详细介绍如何使用 RemoteObject 服务来访问数据。


清单 5. 添加脚本来调用数据源
<mx:Script>
   <![CDATA[
      …
      private static const USE_MOCK_DATA:Boolean = true;	…
      private function getTodoList():void
      {
         if(USE_MOCK_DATA) {
            // Creat the mock data
         }
         else {
            // Use remote object to access the back-service
         }
      }
      …
   ]]>
</mx:Script>


在本文的随附部分可以找到更多示例代码(参见 下载)。完成上述步骤后,选择 TODOListFlex.mxml 并单击工具栏中的 Run 按钮。Flex Builder 将会编译这个应用程序并显示如下页面,如图 4 所示。


图 4. TODOList 页面
Flex 学习
构建 portal 项目

WebSphere Portal 是一个框架,允许添加称为 portlet 的新特性或扩展。Portlet 是 WebSphere Portal 内的应用程序,这些应用程序封装了可重用组件,综合了基于 Web 的内容、应用程序功能性和对资源的访问。

WebSphere Portal 最初的版本是 5.0.2.1,为 JSR 168 Portlet API 和 IBM Portlet API 均提供了一个运行时环境。JSR 168 是来自 Java Community Process 的一种规范,用于 portlet 的标准化。此规范的作用是提供在 JSR 168 portlet 容器的任何供应商实现上运行 portlet 的互操作性。在 WebSphere Portal V6.0 中已经淡化了 IBM Portlet API 以显示 IBM 对 JSR 168 标准 portlet API 的大力支持。而且,很多新功能都将只对标准 portlet 可用。在我们的示例中,我们将使用 JSR 168 标准 portlet。

本节显示了如何使用 Rational Software Architecture(RSA)向导创建一个新的 portlet 项目(参见图 5)。

打开 RSA 并选择 File --> New --> Project。
选择 Portlet Project 来创建一个项目。
输入 TODOList 作为项目名称。
目标运行时应为 WebSphere Portal V6.0 stub。
Portlet API 应为 JSR 168 Portlet。
选择 “Create a portlet” 的 复选框。
确保 Basic Portlet 被选中为 Portlet 类型。
单击 Next,保留所有字段的默认设置。
单击 Finish 创建这个 portlet 项目。


图 5. 新建 portlet 项目
Flex 学习
完成以上步骤后,这个项目的类别应该如图 6 所示。


图 6. Portlet 项目类别
Flex 学习
实际上,您现在已经可以将这个 portlet 部署到您的 portal 服务器上了。但首先我们要将前面小节中所创建的这个 Flex 应用程序集成到此 portlet 项目中。


将 Flex 集成到 portlet 项目中

要想将 Flex 应用程序集成进我们的 portlet 项目,必须要完成几个步骤。

引入 Web-tier 编译器

Flex 编译器可以创建能够在 Adobe Flash Player 中运行的 SWF 文件。Flex 提供了很多种编译器:Web-tier 编译器、mxmlc 命令行编译器及 Flex Builder 项目编译器。在本文中,我们将使用 Web-tier 编译器,Web-tier 编译器是一组运行在 J2EE 应用服务器内的 servlet 和 servlet 过滤器。应用服务器将请求从 *.mxml 文件传递到 servlet 容器,此容器之后再将它们编译到一个 SWF 文件并将结果返回给此客户端。在本例中,只需将 Flex 文件简单复制到服务器可见的目录下即可,并且在您用 Web 游览器请求主应用程序文件时,flex 代码将会自动编译。这就让您可以快速地编译、测试与部署一个应用程序,而不必将 MXML 文件编译成 SWF 文件,然后再将它的包装程序部署到 Web 服务器上。

可以从 Adobe 开源 Web 站点下载 FlexModule_J2ER。按以下步骤将它引入到这个示例 portlet 项目。

将 webtier.war 文件解压缩到一个名为 webtier 的目录下。
将 flex-bootstrap.jar 和 flex-bootstrap-jsp.jar 从 webtier\WEB-INF\lib 复制到 portlet 项目对应的 WEB-INF\lib 目录下。
将所有文件和目录从 webtier\WEB-INF\flex 目录复制到 portlet 项目对应的 WEB-INF\flex 目录下。
根据 webtier\WEB-INF 中的 web.xml 文件更新 portlet 项目 WEB-INF\ 目录下的 web.xml 文件内容(您可以从我们已经相应做过更新的示例代码中复制 web.xml 文件,参见 下载)。
引入 BlazeDS

Flex SDK 具有访问服务器端数据的特性。这些组件使用 RPC 来与服务器环境进行交互以为 Flex 应用程序提供数据并将数据发送给后端数据资源。

Flex 支持三种 RPC 组件:HTTPService、WebService 和 RemoteObject。客户端 RPC 组件可以调用远端服务,然后将响应数据保存到 ActionScript 对象以便于您获取数据。

RemoteObject

在本例中我们使用 RemoteObject 组件,因为它可以让您像用 HTTPService 或 WebService 那样直接访问原生格式的业务逻辑,而不必先将它们转换为 XML 格式。这就节省了将现有逻辑公开为 XML 所耗费的时间。Flex 应用程序可以通过对一个指定对象上的方法的远程调用来直接访问 Java 对象。而该服务器上的那些对象随后就可以作为参数处理原生数据类型、从这些参数查询数据库并作为值返回其原生数据类型。

RemoteObject 服务的另一个优点就是网络上的通信速度。仍然会通过 HTTP 或 HTTPS 发生数据交换,但数据本身已被序列化为 Action Message Format (AMF),AMF 是用于数据序列化/反序列化及远程方法调用的一种二进制格式。由于大大压缩了传输数据量,且将二进制数据解析到内存中的对象要远比解析 XML 数据高效,因此它的性能得到了很大的提高。

使用 BlazeDS

BlazeDS 是一个 Adobe 开源项目,它采用 RemoteObject 组件来访问远端 Java 对象。它包含一些可配置通道并能够运行在一个 J2EE 应用服务器上,这些通道用来在客户端与服务器间传输数据。

可以从 Adobe 开源 Web 站点下载 BladeDS 程序包(参见 参考资料)。执行下面的步骤以使这个 portlet 应用程序使用 BlazeDS:

将 blazeds.war 解压缩到 blazeds 目录。
将所有 jar 文件从 blazeds\WEB-INF\lib 复制到 WEB-INF\lib 目录。
将所示配置文件从 blazeds\WEB-INF\flex 目录复制到此应用程序的 WEB-INF\flex 目录下。如果目录下已经有同名文件,那么要全部覆盖。
在这个 portlet 应用程序的 WEB-INF\web.xml 中定义 MessageBrokerServlet 和 一个会话侦听程序,如清单 6 所示。如果您已经从我们的示例代码中复制了这个 web.xml,可以跳过这个步骤。

清单 6. 定义 MessageBrokerSerlet 和会话侦听程序
<!-- Http Flex Session attribute and binding listener support -->
<listener>
   <listener-class>flex.messaging.HttpFlexSession</listener-class>
</listener>
	
<!-- MessageBroker Servlet -->
<servlet>
   <servlet-name>MessageBrokerServlet</servlet-name>
   <display-name>MessageBrokerServlet</display-name>
   <servlet-class> flex.messaging.MessageBrokerServlet </servlet-class>

   <init-param>
      <param-name>services.configuration.file</param-name>
      <param-value>/WEB-INF/flex/services-config.xml</param-value>
   </init-param>

   <load-on-startup>1</load-on-startup>
</servlet>
 
       



将 Flex 代码复制到 portlet 项目

将 src 目录下的所有文件从 Flex 项目复制到 WebContent/_TODOList/jsp/html 目录。portle 项目的类别应如图 7 中所示 。


图 7.将 Flex 代码复制到 portlet
Flex 学习
创建 Java RemoteObject 类

为了简单起见,我们只需要一个 Java RemoteObject 类(TodoItemRO)作为远程业务服务。您可以将 Java 源代码和 jdbc.properties 文件从 示例代码(WEB-INF\src)复制到 portlet 项目。TodoItem 是本例中的惟一一个实体 Java bean(参见图 8)。


图 8. Java RemoteObject 类
Flex 学习
在 portal 内配置 RemoteObject

Flex 依据 WEB-INF\flex 内的配置文件 services-config.xml 寻找远端服务。因此需要在 BlazeDS services-config.xml 文件或者它所引用的文件(比如 remoting-config.xml)中,在远端服务目标的源属性中指定完全限定类名。这个类还必须具有一个 no-arg 构造函数,该函数将被 Flex 用来实例化一个实例。我们在位于 WEB-INF\flex 内的 remoting-config.xml 文件中配置这个 Java RemoteObject,如清单 7 所示。


清单 7. 在 portal 内配置 RemoteObject
<destination id= ‘todoItemRO’>
   <properties>			 
      <source> todolist.ro.TodoItemRO </source>
   </properties>
</destination> 
           



在 Flex 内使用 RemoteObject

在创建并配置了远端对象之后,就可以将其用作一个远端服务了。

首先在 TODOListFlex.mxml 内创建一个具有惟一 ID srvTODOList 的 RemoteObject 组件。目标的值应该匹配此 portal 项目的 WEB-INF\flex\remoting-config.xml 文件内的目标项,在本例中,为 todoItemRO(参见清单 8)。


清单 8. 在 Flex 内创建 RemoteObject 组件
<mx:RemoteObject id="srvTODOList" destination="todoItemRO" showBusyCursor="true" 
requestTimeout="10"/>
          



接下来,利用 RemoteObject 组件的惟一 ID 创建一个 AsyncToken 对象来调用在此目标服务内定义的 Java 方法。此 AsyncToken 类提供了一个位置,可用来为异步 RPC 操作设置额外的或标记(token)级的数据。

它还允许为单个的调用(或回调方法)附加一个 IResponder。我们定义了一个简单的 responder 类 TokenResponder,它能实现 IResponder Interface(参见 代码示例,TODOListFlex\src\util\TokenResponder.as)。它在 Java 为了处理某个错误而返回或发出特定的告警时调用特定的回调方法。我们将其作为 AsyncToken 对象的响应者添加,获得响应数据并将其转变为一个 Flex 变量类型(参见清单 9)。


清单 9. 在 Flex 内创建回调方法
var asyncToken:AsyncToken = AsyncToken(srvTODOList.getTodoItems());
asyncToken.addResponder(new TokenResponder(displayTodoItems, "Error Getting TODO List"));

private function displayTodoItems(event:ResultEvent):void
{
   todoItemColl = event.result as ArrayCollection;
   todoItemColl.refresh();
}
             



将 Flex 组件包括到 JSP 内

面向 J2EE 应用服务器的 Flex 编译器模块还提供了一个 JSP 标记库,可用来将 Flex 应用程序包括到 JSP 内。将如下的标记库声明添加到您的 JSP 页面以将 Flex 3 Tag Library 导入到 JSP:WebContent\_TODOList\jsp\html\TODOListPortletView.jsp(参见清单 10)。


清单 10. 将 Flex 标记库包括进 JSP
<%@ taglib uri="FlexTagLib" prefix="mm" %>




您可以引用一个单独的 MXML 文件,也可以通过 <mm:mxml> 标记将 MXML 语法直接包括到 JSP 内(参见清单 11)。


清单 11. 将 Flex 项目包括到 JSP 内
<mm:mxml source="TODOListFlex.mxml" width="100%" height="768">
</mm:mxml>




您可以删除由 RSA 所生成的 JSP 的所有旧的内容。在 示例代码 内可以找到这个 JSP。


部署

使用 RSA 内的 J2EE Web 应用程序的归档特性来导出一个 WAR 文件,以便将其安装在一个准备(staging)或生产 portal 服务器上。

请确保 WebContent\_TODOList\jsp\html\TODOListFlex.mxml 文件内的常量 USE_MOCK_DATA 被设为 false,以便用 RemoteObject 获得 TODO 列表。将 DB2 JDBC 驱动程序 jar 从示例代码复制到 WEB-INF\lib。

执行如下步骤将 WAR 文件从示例项目导出。

右键单击此示例项目名称并从弹出菜单选择 Export。
在 Export 窗口选择 WAR 文件,然后选择 Next。
为新 WAR 文件指定一个位置。
单击 Finish 并确保在此位置下能够找到这个 WAR 文件。
用管理员身份登录到 WebSphere Portal Server,并转到 Administrative 页面,按照如下步骤安装这个 WAR 文件。

如果 portal 服务器尚未运行,就启动这个 portal 服务器。从控制面板,选择 Portlet Management,Web Modules。
在 “Manage Web Modules” 页面,单击 Install。
在 “Installing a Web module” 页面,使用 Browse 按钮来定位这个 WAR 文件。单击 Next 和 Finish。由于文件较大,这一步骤可能会耗时几分钟。您可以使用共享的 lib 来减少 WAR 文件的大小(参考 “减小 WAR 的大小 一节”)。
安装了 portlet 后,我们需要将其放入页面。从 portal 服务器的 Administrative 页面,执行如下步骤。

导航到 Portal --> User Interface --> Manage Pages。
定位此页面并添加一个 portlet,然后单击 Edit Page Layout。
在此页面内添加 portlet(TODOList),并单击 Done 来保存这些更改。
现在,转到此页面并验证这个 TODOList portlet。


图 9. TODOList Portlet
Flex 学习
如果是在 Linux® 系统上托管的 portal 服务器(如果您使用的是 Windows® 系统,可以跳过这个小节),那么这个 flash 可能不会显示。您可能需要为 portal 服务器的 JVM 将 java.awt.headless 参数设置为值 true。执行如下步骤,实现此目的:

启动 WebSphere Application Server: /opt/IBM/WebSphere/AppServer/bin/startServer.sh server1
打开 WebSphere Application Server Administrative Console: http://server:10001/ibm/console
导航到 Server --> Application Server --> WebSphere_Portal --> Process Definition --> Java Virtual --> Custom Properties

图 10. 配置 java.awt.headless
Flex 学习
重启 WebSphere Application Server 和 Portal Server。


减小 WAR 的大小(共享的 lib)

此步骤可选。由于 WAR 可能大于 20MB,所以可以将某些内容移入 WebSphere Application Service 共享 lib 以便减小文件的大小。参考 developerWorks 文章 “Using resource environment providers in WebSphere Application Server” 其中的 “Create a shared library” 一节(参见 参考资料)。

结束语

本文涵盖了在集成 Adobe Flex 和 WebSphere Portal 期间的主要特性和增强。我们还研究了用来显示示例应用程序的运行时环境,以及在发布此应用程序之前创建一个 RIA 应用程序并集成 Portal 特性来提升用户体验是多么容易。

你可能感兴趣的:(应用服务器,Web,Flex,IBM,websphere)