flex3 ria开发详解与精深实践(第三部分)


第 7 章 Flex 企业级开发实践—— Flex + Struts 在当前 IT 行业最热门的技术中,我 们认为有两者极为重要:一是如日中天的 RIA(Rich Internet Application)技术,另外 就是企业级应用开发技术。在 RIA 领域, 相信大家对 Ajax、Flex、JSF 等技术已耳 熟能详;而.NET 和 JavaEE 也早已成为企 业级开发平台的两大阵营。 事实上,RIA 和企业级开发并不是完 全独立的两种技术。可以说,RIA 和企业 级开发的关系极为密切:首先,大多数企 业级开发都是基于 Intranet 或 Internet 的 B/S 架构的应用,在这些应用中,用户界 面设计常常成为被忽视而往往给用户带 来不佳体验的瓶颈;其次,尽管 RIA 的核 心是用户界面,业务逻辑的计算和处理往 往才是应用的“用”之体现。毕竟,强大 的功能才是衡量应用成功与否的标准。所 以,RIA 常常需要强大的计算和处理能力, 而企业级应用常常又需要穿上更加亮丽 的外衣。如果两者能有机地结合起来,一 定能迸发出激动人心的火花。 关键词 Flex 与 Struts Flex 与数据服务 Flex 3 RIA 开发详解与精深实践   企业级 Web 应用与 AIR 桌面应用   [ 230 ] 7.1 Flex 与 Struts 提到企业级应用开发,就不能不提近十年来发展迅速、风光无限的程序设计语言—— Java。在 Java 领域,为寻求创建用户界面的最佳方式所作的努力从未停止过。Java 作为一 门高级编程语言,其强大的语言特性,丰富的数据结构,浩瀚的各类 API 支持及成熟的跨 平台能力使其成为 IT 行业的领跑者和事实上的行业标准之一。基于 Java 三大平台 (J2ME/J2SE/J2EE 或 JavaEE)所开发的各类产品和项目在各个行业都拥有无数成功的案例。 7.1.1 Flex 与 Java,自然又必然 然而,与 Java 数十年辉煌的行业地位极不协调的是,在 UI(User Interface)设计领域, 无论是基于 AWT 或 Swing 的桌面应用,还是以 JSP(Servlet)或 JSF 为前端的企业级应用, 都或多或少地让人们感觉到了 Java 在界面展现和用户体验方面有点力不从心。 AWT 和 Swing 最为让人诟病的就是程序的响应速度和内存泄露等诸多问题,而 JSP 在 “富客户端”的互联网应用盛行的今天并没有提供多少可供开发人员使用甚至扩展的页面 组件,JSP 程序员仍然需要花大量的时间去开发标签库,需要在并不熟悉的 JavaScript 上面 耗费大量的开发和调试时间,因此多年来 JSP 始终只能作为各种商业控件的“载体”,始终 在 JSP+标签库+表达式语言的前端开发模式中扮演“绿叶”。 而 JSF 技术,是 Sun 公司力图使 Java 互联网应用从“请求-响应”机制向“事件处理” 机制进化跨出的革命性的一步,其特点为强大的事件处理功能和界面组件支持及其对 Request 和 Response 对象处理细节的隐藏,应该说 JSF 代表了未来互联网应用的方向,但 是 JSF 对开发人员的角色区分较为细致,例如分网页设计人员、应用程序设计人员和组件设 计(集成)人员等,要想精通 JSF,就必须深入了解 JSF 标准标签的使用、自定义标签开发、 事件驱动模型、UI 组件开发等技术细节,学习的难度较大,周期较长。 在 RIA 领域,最近几年最为风生水起的技术就要算是 Flex 了。相信通过前面章节的介 绍,读者已经对 Flex 的基本概念有了了解。在当今流行的 RIA 解决方案中,不乏 Applet 这 样成熟稳重的老兵,也不乏 Ajax 这样风风火火的新贵,而 Flex 却是独树一帜,稳健而不失 犀利。 作者认为,Flex 会在未来几年成为 RIA 平台的领航者,理由有两条: 第一是其基于 Flash Player 的开发模型。Flash Player 提供了 Flex 应用在不同操作 系统和不同浏览器之间整合的能力。据统计,全世界 84%的个人计算机上安装有 Flash Player,并保有 80%的升级率。这使我们在几乎所有的互联网用户的运行时 中发布跨平台的 RIA 应用成为可能,因为应用的最终形式只是一个 swf 文件,而 这个文件能在任何安装了 Flash Player 的浏览器中运行,无论用户使用的是 Windows、Linux 还是 Mac OS。   第 7 章  Flex 企业级开发实践——  Flex + Struts  [ 231 ] 第二是框架的成熟度。Flex 开始进入人们的视野是在 2004 年,最初作为企业级应 用服务器打入市场。从那时起, Flex 根据技术和市场的需要进行了一系列的改进。 升级了 Flash 运行时、ActionScript 语言和服务器组件的 Flex 2.0 于 2006 年 6 月发 布,Adobe 于 2007 年 4 月宣布 Flex 框架开源。Flex 使得软件开发人员为增强用 户体验开发稳健、开源的框架成为现实。开源社区也会为 Flex 技术的成熟与高速 发展提供强大的技术支撑。 Java 技术非常成熟,大量的企业级应用采用 Java 技术构建。Java 能为这些复杂的应用 提供强大的业务计算能力,但却往往不能为其提供完美的界面和良好的用户体验。对于技 术人员来说,保留 Java 强大的业务逻辑处理能力,以非 Java 技术取代其略显晦涩的界面展 现能力,不失为一种好的选择。现在,是 Java 开发人员向 Flex 敞开怀抱的时候了! Flex 基于 Java/J2EE 社区构建,如果你有过 Java 开发背景,当你接触 Flex 编程的时候, 你会发现 Flex 其框架、语言和工具非常易于上手。反之,如果你精通 Flex 编程,在学习 Java 的时候,你常常会发现某些 ActionScript 的语言特征(诸如面向对象)和 Java 极为相似,甚至 完全一致。 Flex Builder 是基于 Eclipse 构建的,可以同时以独立产品和插件的形式提供。几乎所 有的 Java 开发人员都使用 Eclipse 进行开发,所以他们自然对 Flex Builder 不会陌生。Flex 还提供了大量 Ant 任务,为自动构建 Flex 工程提供了足够的支持。而 Ant 则早已成为 Java 开发人员和 Java 社区最密切的朋友,这又为 Java 开发人员向 Flex 领域进军提供了天然的 条件。 Flex 的优势在于构建绚丽的用户界面,提供所谓的“富客户端”体验,业务处理并不 是 Flex 的强项,毕竟 ActionScript 的数据结构、语言特性及库函数支持尚不能和成熟的高 级语言(诸如 Java、C++等)相提并论,Flex 的开发者们在 Flex 面世时就考虑到了 Flex 的定 位,同时推出了其获取后台服务的工具——LiveCycle Data Service ES。LiveCycle 组件为 Flex 前端提供了多种与 Java 后台交互的方式,如远程对象调用、 Java 消息服务和数据管理服务。 我们将在后面的章节用大量的篇幅介绍这几种与后台服务交互的方式。 综上所述,基于 Flex 框架构建的 RIA 应用允许 Java 开发人员利用强大和成熟的 Java 平台实现复杂的服务器端业务逻辑;同时用 Flex 能取代传统的 Java 用户界面技术如 JSP, Servlet 等,提供极为出色的用户体验和数据展现能力。可见 Flex 和 Java 的结合实在是既自 然而又必然的事情。 7.1.2 Struts,外表-思想-内心 在程序设计的过程中,设计模式应该是开发者谈论最多的话题之一。作者认为,设计 模式就是一套被反复使用的、针对某一特定场景或解决某一类特定问题的代码设计经验的 总结。使用设计模式是为了代码复用,因为设计模式是被很多开发人员反复使用,经过实 践证明是有效而且可靠的,将某些为开发人员广泛认可的设计模式应用到自己的系统当中, 能够增加代码的可读性、高效性。 Flex 3 RIA 开发详解与精深实践   企业级 Web 应用与 AIR 桌面应用   [ 232 ] MVC 模式是“Model-View-Controller”的缩写,意即“模型-视图-控制器”。MVC 模 式在 IT 行业中被广泛应用(特别是在互联网应用当中),因为它能将复杂应用有效地进行分 层,从而达到“分而治之”的目的。按照 MVC 的设计思想,应用程序的代码可以分为如下 三层。 模型:为界面存储数据和应用逻辑。 视图:提供用户界面。 控制器:对用户输入进行处理,修改模型。 MVC 的基本思想是分离责任。在 MVC 应用当中,模型层只关心应用的状态和业务逻辑。 它并不关心状态如何展现给用户及用户输入是如何接收的。而视图层关心的是如何根据模 型的改变创建用户界面,并不关心应用逻辑和用户输入最终的处理,它仅仅确保反映出当 前模型的状态。控制层负责将视图层提供的用户输入进行处理,将更改作用到模型,它不 关心输入是如何接收的,也不管这种改变如何作用到模型的状态上(见图 7.1)。 图 7.1 MVC 模式 将应用按 MVC 模式进行分层可以给我们带来相当多的好处: 允许同样的信息(模型)产生不同的表现(视图),例如,对于同样一组数据,我们可 以在界面上将其展示为饼图,体现其中每项数据占总值的比例;也可以将其展示 为柱状图,体现每项数据之间的比较关系。 开发人员能在编译时或运行时随意增加、替换或删除视图。 弱耦合,开发人员可以轻易地对处理用户输入的逻辑进行修改或替换。 代码重用,可以将商业软件集成到自己的应用中,例如,可以购买一套非常漂亮 和复杂的 UI 代码,将其作为视图层放到系统中 可以将开发团队按 MVC 三层进行分组,例如,精通 HTML 和 JavaScript 的开发人 员可以专注于 UI 设计,而数据库人员可以专注于模型的设计,精通程序设计的人 员可以专注于业务逻辑的编写。 由于 MVC 能够清晰地为应用进行分层并因此带来很多优势,很多大型的项目都会基于 MVC 模式进行架构。在作者曾经参与的几家世界 500 强公司的互联网应用项目中无一例外 地采用了 MVC 架构。更确切地说,都采用了 Struts 框架,那么 Struts 是什么呢? Struts 在最近几年的 Java 互联网应用领域中可以说是占有举足轻重的地位,它是 Apache 基金会 Jakarta 项目组的一个开源项目,采用了 MVC 模式,是一个能够帮助开发人   第 7 章  Flex 企业级开发实践——  Flex + Struts  [ 233 ] 员迅速建立起自己的项目的一个半成品框架。就是说,如果基于 Struts 开发应用,开发者 只需要做下面几件事情: 为应用开发视图。通常是 JSP,将界面上的表单对应到 Struts-config.xml 中的 ActionForm 中,以处理用户输入。 为应用设计业务逻辑处理程序。Struts 框架中的控制器是一个 ActionServlet(确切 地说是 RequestProcessor)实例,一般不需要开发者自己定义或修改控制器,但是 必须设计业务处理逻辑,控制器会将相应的请求映射到这些处理程序中(Action), 相应的配置也在 Struts-config.xml 中。 开发模型层。这是几乎所有应用都要做的,可结合一些 ORM 框架(如 Hibernate) 简化这一层的工作 综上所述,开发基于 Struts 框架的应用非常简单,主要是管理好 Struts-config.xml 这个 文件,实际上,这个配置文件就像一瓶“胶水”,将界面和业务逻辑处理“粘合”在一起, 隐藏了 ActionServlet 这个请求的核心控制者,只要读懂 Struts-config 文件,你就能很清楚, 你页面上的请求由谁来处理。 Struts 框架还为互联网应用面临的一些共通的问题提供了解决方案,诸如国际化支持、 页面重用与复合(tiles 框架)等。 尽管 Struts 大大地方便了开发人员的工作,但是在改善用户体验这一点上并没能有革 命性的突破:使用的仍然是“请求 -响应”的传统的处理机制,每当客户端发起请求,服务 器端会根据请求进行计算并产生结果,重新生成 HTML 页面发回客户端。这样,用户会感 到页面“刷新”了。相比而言,Flex 应用中的文件会最终编译成一个二进制的 SWF 文件, 发送到客户端,当其发送请求到服务器的时候,服务器仅仅传送所需的数据回客户端,并 不会重新编译 SWF 文件,也不会刷新页面。这也正是 RIA 的优势所在。 其实,Flex 本身也是一个 MVC 架构的产品,只不过更多地关心 MVC 中“View”的实 现,而 Struts 的业务处理应该是核心,视图层使用了大量的标签库以简化开发人员的工作。 所以,如何能将 Flex 在视图设计和 Struts 在业务处理方面的优势结合到一个应用当中,应 该是读者此时考虑并亟待获得答案的问题。 7.1.3 Flex 为 Struts 披上了绚丽的外衣 前面的小节对 MVC 模式做了详细的阐述,也介绍了 Java 互联网应用开发中流行的 Struts 框架。我们知道,Flex 框架本身也是 MVC 模式非常标准的实践,那么为什么我们不 直接使用 Flex 框架的 MVC 实现,而要在本节中将 Flex 和 Struts 结合使用呢?如果您仔细 权衡一下 Flex 和 Struts 各自的优势所在,您会发现,这种整合是非常必要的。我们已经对 Flex 在用户界面设计方面的强大能力印象深刻,现在,只需结合 Struts 在核心控制和后台 数据整合方面的先天优势,一个“内外兼修”的应用便会浮现在眼前。 Flex 3 RIA 开发详解与精深实践   企业级 Web 应用与 AIR 桌面应用   [ 234 ] 本小节中采用的开发工具、应用框架和应用服务器为: Eclipse-jee-europa-fall2-win32 Flex Builder Eclipse plug-in Adobe LiveCycle Data Service ES struts-1.3.8 apache-tomcat-6.0.16 关于 Flex Builder Eclipse 插件的安装请参照前述章节。 现在,我们将着手开发一个简单的基于 Struts 的用户管理系统,将 Flex 作为其视图层 实现。应用的最终效果如图 7.2 所示。 图 7.2 项目最终效果 它实现了简单的浏览和更新功能,旨在介绍如何将 Struts 和 Flex 良好地集成在一起。 首先,打开 Eclipse,按 Ctrl+N 组合键新建项目,选择 Flex Project,如图 7.3 所示。 单击 Next 按钮进入下一步,输入项目名“ UserInfoSys”,勾选“ Use default location”, 使用默认的工作区目录;选择应用类型为“Web Application(runs in Flash Player)”,指定 我们要创建的项目是互联网应用,运行在浏览器中;在 Server technology 中选择“J2EE”, 因为我们要使用 Tomcat 作为服务器;不要勾选“ Use remote object access service”,因为 在这个示例中,我们会使用 HTTPService 组件,采取 URL 访问远端服务的形式;勾选“Create combined Java/Flex project using WTP”,这样会为 Flex 和 Java 分别生成存放代码的目录。   第 7 章  Flex 企业级开发实践——  Flex + Struts  [ 235 ] 图 7.3 新建 Flex 项目 最终设置如图 7.4 所示。 图 7.4 Flex 项目设置 单击 Next 按钮进入下一步,如图 7.5 所示。 Flex 3 RIA 开发详解与精深实践  企业级 Web 应用与 AIR 桌面应用  [ 236 ] 图 7.5 J2EE 服务器设置 项目将部署和运行在 Tomcat 上,这一步将进行其相关设置。由于是第一次进行配置, 所以在 Target runtime 后单击 New 按钮,新建一个服务器配置。在弹出的对话框中选择 “Tomcat v6.0 Server”,其他默认,单击 Next 按钮进入服务器运行时设置,如图 7.6 所示。 图 7.6 Tomcat 运行时设置   第 7 章  Flex 企业级开发实践——  Flex + Struts  [ 237 ] 在弹出的对话框中选择您的 Tomcat 安装路径,使 Eclipse 能够找到启动它的命令和相 关运行时库,单击 Finish 按钮,刚刚建立的配置出现在 Target runtime 下拉列表框中,如 图 7.7 所示。 图 7.7 选择设置好的 Tomcat 选择“Apache Tomcat v6.0”,其他保留默认设置;单击 Next 按钮进入下一步;此时 Eclipse 会生成项目所需文件,并将 Flex 运行时库加入到项目的类路径中,如图 7.8 所示。 图 7.8 Flex 运行时库 Flex 3 RIA 开发详解与精深实践   企业级 Web 应用与 AIR 桌面应用   [ 238 ] 可以看到 Flex 的相关运行时库都已经出现在了 Build path libraries 中。单击 Finish 按 钮结束项目的配置,这时 Eclipse 会提醒我们是否切换到 Flex 视图,选择“是”,我们建立 的项目在 Flex Navigator 中显示,如图 7.9 所示。 此时,我们完成了配置的第一步,这时的项目是一个 Flex 互联网应用,但是如果现在 就将其部署到 Tomcat 上,用 URL 访问 MXML 文件,你只能看到响应的源代码 (XML 格式), MXML 并不会被编译成 SWF 文件。因为 Tomcat 会把 MXML 格式的文件当作普通的 XML 文件,不会对其进行处理,此时我们需要一种“映射”机制,将访问 MXML 的请求交给专 门的 Servlet 处理。这个专门的 Servlet 存在于前面提到的 LiveCycle Data Service ES 运行时 中,下载和安装 LiveCycle 的过程非常简单,不再赘述。 下面,我们介绍如何为访问 MXML 提供支持。 在 Flex Navigator 中右击,从弹出的快捷菜单中选择 Import 命令,如图 7.10 所示。 图 7.9 新建的 Flex 项目 图 7.10 选择“导入”菜单命令 在弹出的对话框中选择“WAR file”,如图 7.11 所示。 单击Next按钮,在弹出的对话框中选择 LiveCycle安装目录下的flex.war,这是LiveCycle 提供的一个空的应用,开发人员可以在其基础上添加自己的界面及业务逻辑,这个空的应 用提供了与企业级应用进行各种形式交互的支持,包括 JMS、RPC(远程调用),代理服务及 数据管理服务;我们的应用使用了 RPC 功能中的 HTTPService 调用,如果单纯调用 HTTPService,其实并不需要 LiveCycle,我们将在下一节对 LiveCycle 的各种服务进行详细 的介绍。单击 Open 按钮,如图 7.12 所示。   第 7 章  Flex 企业级开发实践——  Flex + Struts  [ 239 ] 图 7.11 导入 WAR file 图 7.12 选择 flex.war 单击 Finish 按钮完成导入。flex.war 在导入后会作为一个 Web 项目出现在 Flex Navigator 中,如图 7.13 所示。 Flex 3 RIA 开发详解与精深实践   企业级 Web 应用与 AIR 桌面应用   [ 240 ] 图 7.13 flex 项目 此处省略 30 页内容…… 7.2 Flex 与数据服务 我们在 7.1.3 小节中“小试牛刀”,完成了一个简单的基于 Struts 框架的 Flex 互联网应 用,这个应用基本上可以称为一个企业级应用程序了,但是并不具备真正企业级应用的诸 多特点,例如分布式、消息服务、事务管理等。 而且在这个应用中,Flex 只是作为视图层,所有的业务逻辑统统交给 Struts 处理,真 真正正只是一件“外衣”而已。 Flex 当然不是只有这点本事,作为 RIA 领域的排头兵,Flex 有着许多强悍的特性需要我们去了解和学习。 7.2.1 LiveCycle 很好很强大 如果单纯将 Flex 作为用户界面的开发工具,那么 Flex SDK 足够构建一个完整的互联网 应用。与 7.1.3 小节中给出的示例类似,我们可以将很多复杂的业务逻辑交由 Java 或.NET 企业级应用服务进行处理,而通过 HTTPService 或 WebService 组件(我们将在 7.3 节中详细 讲述 WebService 组件)直接访问这些远端服务,这就是 Flex 的 RPC(远程过程调用)特性;   第 7 章  Flex 企业级开发实践——  Flex + Struts  [ 241 ] 如果我们需要构建一个真正的 Flex 企业级应用,例如进行复杂的数据库处理或访问消息服 务,或是直接调用远端 Java 对象上的方法(Flex RPC 除 HTTPServcie 和 WebService 之外的 另一种形式),那么我们必须借助于 Flex 的数据服务(Flex Data Service)来实现。 Flex Data Service(FDS)是用 Java 开发的服务器运行时,就是开发人员经常说的“容器”, 它本身也是作为一个应用部署在诸如 WebSphere、Tomcat 等服务器上的。FDS 是一个“中 间件”,并不处理业务逻辑,而是提供诸如安全性、跨域访问、数据格式交换等服务,所 以 FDS 并不是 Flex 开发所必需的。FDS 经历了长期的发展和改进,最新版本更名为 LiveCycle Data Service ES。 其实在 7.1.3 节中,我们已经接触过 LiveCycle,大家应该还记得我们在建立应用的同时 导入了一个叫 flex 的 WAR 包,然后将其 WEB-INF 下面的 flex 目录和 lib 目录中的所有库文 件都拷贝到了我们的项目中,然后将 flex 中的 web.xml 也照搬了过来。其实我们并没有用 到 LiveCycle 的任何特性,仅仅是使用其中的 BootstrapServlet 来处理我们访问 MXML 资源 的请求,使 Tomcat 能编译 MXML 文件并将 SWF 返回到客户端。那么 LiveCycle 到底有哪 些深藏不露的强悍功能呢? LiveCycle 具有下列特性: 加强的数据服务。 多个客户端的数据共享服务。 客户到客户的数据通信支持。 客户访问服务器资源的认证。 数据服务日志。 企业消息服务访问。 加强的远程过程调用(RPC)服务。 我们会在本节中针对其中几个比较重要的企业级特性进行详细的阐述并给出示例。包 括加强的 RPC 服务、消息服务和数据管理服务。 7.2.2 RPC,Flex 也能“分布式” 本章是讲述如何开发 Flex 企业级应用的,而说到企业级应用,不得不提到一个重要的 概念——分布式。 在传统的客户机/服务器结构中,应用程序逻辑通常分布在客户端和服务器两端,客户 端发出数据资源访问请求,服务器端将结果返回客户端。 Client/Server 结构的缺陷是,当 客户端数目激增时,服务器的性能将会因为无法进行负载平衡而大大下降。而一旦应用的 需求发生变化,客户端和服务器端的应用程序都需要修改,这样给应用的维护和升级带来 了极大的不便,而且大量数据的传输也增加了网络的负载。为了解决客户机 /服务器存在的 问题,企业只有向多层分布式应用转变。 在多层分布式应用中,客户端和服务器之间可以加入一层或多层应用服务程序,这种 程序称为“应用服务器 (Application Server)”。开发人员可以将企业应用的商业逻辑放在中 Flex 3 RIA 开发详解与精深实践   企业级 Web 应用与 AIR 桌面应用   [ 242 ] 间层服务器上,而不是客户端,从而将应用的业务逻辑与用户界面隔离开,在保证客户端 功能的前提下,为用户提供一个瘦的 (Thin)界面。这意味着如果需要修改应用程序代码,则 可以只在一处(中间层服务器上)修改,而不用修改成千上万的客户端应用程序。从而使开发 人员可以专注于应用系统核心业务逻辑的分析、设计和开发,简化了企业系统的开发、更 新和升级工作,极大增强了企业应用的伸缩性和灵活性。当企业需要建立基于 Web 的商业 应用系统时,多层分布式体系结构同样提供了强大的优势,为基于 Web 的商业应用提供了 “瘦客户”的体系结构,使基于浏览器的客户可以与 Intranet 资源进行有效交互,并且不 需要在客户端进行复杂的应用配置工作。多层分布式解决方案在异构平台间架起了桥梁, 可以使基于 Web 的商业应用与企业已有系统集成在一起。 说到这里,读者应该明白我们 7.1.3 小节开发的那个用户管理系统为什么可以称作“企 业级应用”了吧,因为所有的业务逻辑包括数据的处理都是在服务器 (Tomcat)上进行,客 户端得到的仅仅是一个 SWF 文件,这个 SWF 文件会与服务器上的程序进行通信,并不处理 任何业务逻辑,只接收数据显示给用户。其实更大型的企业级应用会将业务逻辑的处理也 进行分层,并将其部署在不同用途的服务器上,例如,核心工作流部署在工作流引擎上 (如 WPS);EJB 部署在 EJB 服务器上(如 Weblogic、JBoss 等);前端 Portal 部署在 Portal 服务器 上(如 WebSphere Portal Server,Liferay 等),数据库安装在单独的数据库服务器或服务器 集群上等。这样对应用进行细致的划分的好处之一是使每一层的功能更加清晰,减少层与 层之间的耦合并减轻服务器的负荷。 想必很多读者已经在很多技术资料或文档中接触过 RPC 这个术语,它是 Remote Procedure Call(远程过程调用)的缩写。但是,究竟什么是 RPC 呢? RPC 最早指的是一种通过网络从远程计算机程序上请求服务,而不需要了解底层网络 技术的协议。 RPC 协议假定某些传输协议的存在,如 TCP 或 UDP,为通信程序之间携带信 息数据。RPC 跨越了 OSI 网络分层模型中的传输层和应用层,使得开发包括网络分布式程 序在内的应用程序更加容易。 RPC 采用客户机 /服务器模式,请求程序就是一个客户机,服 务提供程序就是一个服务器。调用进程发送一个有进程参数的调用信息到服务进程,然后 等待应答信息;在服务器端,进程保持睡眠状态直到调用信息的到达为止。当一个调用信 息到达时,服务器获得进程参数,计算结果,发送应答信息,然后等待下一个调用信息; 最后,客户端调用过程接受应答信息,调用执行继续进行。 RPC 服务会在注册表中给自己 注册一个 UUID,即通用唯一标识符,这个 UUID 针对每一项服务都是唯一的,在所有平台 上通用。当一项 RPC 服务启动的时候,会获得一个端口,并且以 UUID 对端口进行注册, 当客户机要与特定的 RPC 服务进行通讯的时候,它无法事先知道该服务在哪一个端口上运 行,因此该客户会先建立一个到服务器端口映射的服务 (135 端口),并使用其请求的服务 的 UUID 向服务器端口映射器服务查询该端口号,端口映射器会将相应的端口号返回给客 户端,然后关闭连接。最后,客户端利用端口映射器提供的端口号,新建一个到该服务的 连接。 关于 RPC 的更加详细的介绍,请读者参考各种具体的 RPC 实现,在本书中,作者无意 涉及太多 RPC 的底层细节,因为这是一门独立的技术,个中奥妙可能需要单独的一本书才   第 7 章  Flex 企业级开发实践——  Flex + Struts  [ 243 ] 能解释清楚。 Flex 中的 RPC 实际上是抽象的 RPC,也就是说,隐藏了真正的 RPC 实现细节,仅仅是 将 3 种可用的 RPC 服务方式暴露给开发人员,开发人员可以利用 HTTPService 组件、 WebService组件和RemoteObject组件非常容易地实现RPC,而不用关注其底层的技术细节。 在 7.1.3 小节中,我们实际上就是利用 HTTPService 组件将客户端的请求发送给了 Struts 的 控制器,并且等待其返回相应的数据,进而达到 Flex 与 Struts 集成的效果;在后面的章节, 我们会详细讲述如何利用 WebService 组件访问 Web 服务。本节中,我们将重点放在 RemoteObject 组件的使用上。 在 7.1.3 小节的用户管理系统中,我们采用的是 Flex 远程调用的形式之一,即利用 HTTPService 组件以 URL 的方式访问远端服务。这一小节中,我们对这个应用进行一下修 改,去除 Struts 框架,让 Flex 直接与 Java 类进行交互,利用 Java 类完成数据库的查询和 修改,实现更加紧密的“集成”。 我们在 7.1.3 小节中非常详细地介绍了如何新建 Flex 项目,如何导入外部 WAR 包,如 何修改项目配置,如何建立服务器及如何通过数据库管理器操作 Hsqldb 数据库等内容,涉 及到了在 Eclipse 环境中建立互联网应用的方方面面。这些内容是非常基础的,但也是必须 掌握的,希望读者反复练习,因为我们在后面的章节中涉及这些内容时将不再赘述。 首先,建立一个叫“ UserInfoSysRPC”的 Flex 应用,与 7.1.3 小节中不同的是,请勾选 “Use remote object access service”,Eclipse 会自动选择 LiveCycle Data Service,其他设 置与 7.1.3 小节中一致,如图 7.50 所示。 Flex 3 RIA 开发详解与精深实践   企业级 Web 应用与 AIR 桌面应用   [ 244 ] 图 7.50 新建项目 (调用远程对象服务) 单击 Next 按钮进入下一步。在这一步中,与 7.1.3 小节中一样,是关于服务器的选择, 依然选择 Tomcat 并对其安装路径做相应的设置;与 7.1.3 小节中不同的是,因为我们在上 一步选择了要使用 LiveCycle 远程对象服务,这一步会让我们选择 flex.war 的安装路径,因 为 flex.war 中包含了 LiveCycle 所提供的数据服务支持的所有运行时库(服务器端和客户端), 实际上我们在 7.1.3 小节中已经说明,这个 flex.war 是一个“模板”,包含了很多企业级服 务的特性,读者可以在它的基础上建立 Flex 企业级应用。由于我们在 7.1.3 小节中使用的是 HTTPService 组件,其实并不需要 LiveCycle 支持,所以我们手动做了一些拷贝的工作,拷 贝到我们项目中的很多文件其实并没有任何作用,仅仅使用了 BootStrapServlet;而这一小 节中,我们需要 LiveCycle 的远程对象服务的支持,需要使用其中的扩展类库和配置文件, 所以让 Eclipse 来帮我们集成这些特性(效果和直接拷贝没有区别)。选好 flex.war 路径,单 击 Open 按钮,如图 7.51 所示。 图 7.51 选择 flex.war 在主对话框中,单击 Next 按钮,将看到当前项目的运行时类库,如图 7.52 所示。   第 7 章  Flex 企业级开发实践——  Flex + Struts  [ 245 ] 图 7.52 项目运行时类库 单击 Finish 按钮,完成项目的建立,在 Flex Navigator 视图中,我们看到了刚才建立的 项目。Eclipse 将 flex 目录拷贝到 WebContent→WEB-INF 下,并同时将相应的 jar 包也拷贝 到 lib 目录中,与我们在 7.1.3 小节中手动完成的工作一样(见图 7.53)。 Flex 3 RIA 开发详解与精深实践   企业级 Web 应用与 AIR 桌面应用   [ 246 ] 图 7.53 项目目录结构 同时,我们可以看到,WEB-INF 下的 web.xml 也做了相应的改变,自动加入了对 MXML 文件的访问支持,如图 7.54 所示。 现在,我们需要处理数据库的相关部分。按照 7.1.3 小节的步骤建立库表,并将 ConnectionHelper 等数据库相关的类拷贝到 src 目录下,如图 7.55 所示。 在 UserService.java 中添加如下代码:  public static void main(String[] args) throws Exception { List l = new UserService().getUsers(); for (int i=0; i 这是调用 ListAllUsersAction 以在左侧面板中显示所有用户的基本信息。 再来看下面这段代码: {list.selectedItem.user_id} {userName.text} {titl.text} {list.selectedItem.image} {list.selectedItem.imagebref} {description.text} 上面的代码调用了 UpdateUserAction,进行数据的更新,而 标签中的字 段会随着请求发送,最终组成 Struts 表单中的信息。 在本小节中,RPC 的机制已经完全改变,我们需要直接调用远端的 Java 对象,由这个 Java 对象(UserService)来帮助我们完成数据库的操作。 首先,需要在 WebContent→WEB-INF→flex 目录下找到一个叫 remoting-config.xml 的 文件,文件当前的内容如下: 这是默认的设置。其中的 段表明了这是一个远程调用服务,段定义 了一个“适配器”,读者可以将其理解为与对象或服务直接交互的服务器端代码,这可能   第 7 章  Flex 企业级开发实践——  Flex + Struts  [ 249 ] 比较难理解,其实读者可以理解为:Java 写的东西,Flex 是看不懂的,有了这个适配器, 可以在 Java 和 Flex 中建立一种转换机制,能够使 Flex 和 Java 顺利通信,就像 USB 鼠标可 以用一个串口适配器接到串口上当成普通鼠标使用一样。在我们稍后定义的“目标”中, 会引用这个适配器。 段定义了默认的“频道”,频道是指一种传输的协 议,Flex 客户端(Flash Player)需要某种“协议”才能与数据服务进行通信。在 Flex 中,有 3 种基本的“频道”:HTTP、AMF 和 RTMP。形象点说,你调到某个频道,就能收看那个 频道的电视(能接收其信号),这是同一个道理。 现在在段后面加上我们的“目标”定义: flex.userinfosys.db.user.UserService 这里定义了一个元素,可以理解为“目标”,其中的 子元素 中定义了我们要引用的 UserService 类。目标按 Flex 官方的技术资料解释为“ endpoint”(端 点),我们的调用到达 UserService 之前实际上是在网络上传输的,需要编码和解码,所以 这个端点可以理解成负责编码和解码的一个中间服务。 现在,我们修改 UserInfoSys.mxml,调用 UserService 来获取我们的用户数据: 编译项目并部署,启动服务器。打开浏览器,输入以下地址: http://localhost:8080/UserInfoSysRPC/UserInfoSysRPC.mxml 可以看到如图 7.57 所示界面。 页面在加载时调用了 UserService的 getUsers方法, 获取了当前系统中所有的用户信息, 并显示在 DataGrid 组件中,其中,因为我们没有定义列名,所以显示的是每一字段在数据 库中的名称。 Flex 3 RIA 开发详解与精深实践   企业级 Web 应用与 AIR 桌面应用   [ 250 ] 下面,我们添加更新用户信息部分的代码,并对当前界面做修改。 图 7.57 调用 UserService 返回所有用户信息 首先,我们要建立一个 ActionScript 类,用于存放客户端的用户信息,相当于一个 Value Object(涉及模式中的数据传输对象)。单击 flex_src 目录,按 Ctrl+N 组合键,在弹出的对话 框中选择“ActionScript Class”,如图 7.58 所示。 图 7.58 新建 ActionScript 类   第 7 章  Flex 企业级开发实践——  Flex + Struts  [ 251 ] 单击 Next 按钮,在 Name 文本框中填入类的名称“ User”,其他保留默认值,如图 7.59 所示。 图 7.59 设置类属性 单击 Finish 按钮,这样 Eclipse 会为我们建立一个 AcitonScript 类的框架,自动生成如 下代码(User.as): package { public class User { public function User() { } } } 我们在其中添加用户的相关属性字段,并加上元数据标签 [Managed]和[RemoteClass] 如下(User.as): package { [Managed] [RemoteClass(alias="flex.userinfosys.db.user.UserProfile")] Flex 3 RIA 开发详解与精深实践   企业级 Web 应用与 AIR 桌面应用   [ 252 ] public class User { public function User() { } public var userId:int; public var name:String; public var title:String; public var image:String; public var imagebref:String; public var description:String; } } ActionScript 定义的对象有两种类型,一种是其所有属性都是原始类型,如 int、String 等;还有一种是某些属性是对象类型,这种对象称为“层次类型”的对象。 我们使用 UserService 对象来管理 User 对象的持久化,如果 User 对象有对象类型的属 性的话,需要相应的 Java 对象来管理相应属性的持久化。加上 Managed 元数据标签表明, 如果有对象类型的属性,那么这些属性拥有自己的“目标”定义,这些“目标”负责管理 这些属性的状态。我们前面已经定义了一个目标,它与 UserService 关联,如果 User 对象 有对象类型属性如 Address,那么还会为 Address 单独定义目标,负责 Address 的增删改查 操作。 RemoteClass 元数据标签建立了一个 User 类(ActionScript 类)到我们先前建立的 UserProfile 类(Java 类)之间的一个映射。 当我们将数据封装在 User 类中并发送到服务器端,调用 Java 类上的方法时,先前定义 的“目标”和“适配器”会自动为我们完成这种转化,将 User 类对象转化为 Java 的 UserProfile 对象。 在此请注意两点:一是这里的字段名一定要和 Java 对应类中的完全一致,例如 UserProfile 中有 userId 属性,那么这里的 userId 就不能写成 user_id 或其他形式,否则在 更新数据的时候会出错;二是 UserProfile 一定要有默认的构造函数,否则不能实例化 UserProfile 类。 接下来,在 flex_src 下面新建一个“MXML Component”,其方法我们在 7.1.3 小节中 已经详细介绍过。 我们要建立的是一个 Panel 组件,名称设为“ UserForm”,宽度和高度设置为 100%, 其他保留默认值,如图 7.60 所示。   第 7 章  Flex 企业级开发实践——  Flex + Struts  [ 253 ] 图 7.60 新建 Panel 组件 在 UserForm.mxml 中添加如下代码: 改写 UserInfoSysRPC.mxml 的代码,最终代码如下:   第 7 章  Flex 企业级开发实践——  Flex + Struts  [ 255 ] Panel { fontFamily: Thoma; fontSize: 12pt; } 重启服务器,刷新页面,如图 7.61 所示。 图 7.61 用户管理系统界面 单击左边面板的任意一行,如图 7.62 所示。 Flex 3 RIA 开发详解与精深实践   企业级 Web 应用与 AIR 桌面应用   [ 256 ] 图 7.62 用户管理系统界面 (详细信息) 可以看到,用户的详细信息出现在右侧面板,更新其职位,如图 7.63 所示。 图 7.63 用户管理系统界面 (更新职位) 此时,并未提交更新,数据库中的值还没有被刷新,但是左侧面板中相应的职位信息 也随之改变了,这就是数据绑定的“魔力”,关于数据绑定,我们在前面的章节中已经做 了介绍。单击“更新”按钮,如图 7.64 所示。   第 7 章  Flex 企业级开发实践——  Flex + Struts  [ 257 ] 图 7.64 将更新写入数据库 这样,我们就将更改写入了数据库。 通过这一小节的学习,我们掌握了一种与 7.1.3小节中完全不同的 RPC服务的调用方式, 即利用 RemoteObject 组件直接调用 Java 对象上的方法。这种调用方式较之 HTTPService 组件以 URL 的形式调用服务更为直观、简洁,也更加高效。 其实,在学习完本章之后,读者会了解,无论是 HTTPService、RemoteObject 还是 WebService 服务,都是基于 HTTP 实现的。HTTPService 和 WebService 本身就通过 HTTP 进行通信,而 RemoteObject 采用的 AMF 也是基于 HTTP 协议传输的。 7.2.3 消息,让 Flex 走向“企业级” 进行企业级应用开发时,如果没有接触过消息系统或者甚至没有听说过消息机制,未 免显得有点不够“专业”。消息服务,在企业级应用中扮演举足轻重的作用,很多银行、 金融和电信行业的产品都是基于消息服务的, IBM 公司的 MQ 就是行业中赫赫有名的 MOM(面向消息的中间件),被广泛应用于众多的重量级应用中。为什么说消息系统如此不 可或缺呢,这还要从传统应用的先天缺陷说起。 传统的企业级应用往往都是实时地进行请求和应答,比方说,客户端发送一个请求, 服务器端进行计算后要立即(可能是几秒钟,也可能需要用户等上几分钟)将结果发送回客户 端。这在很多现实的应用中是不可能的,为什么呢?例如我们要开发一个网上购物系统, 在客户下了订单以后,不可能马上返回处理的结果,因为订单的处理有个流程,系统需要 验证订单的有效性,需要查看库存,可能需要库存调配等;一旦订单处理完成,还需要生 成出库单,进入配送流程,如果用户退货,可能还需要进入退货流程,生成退货单等。这 Flex 3 RIA 开发详解与精深实践   企业级 Web 应用与 AIR 桌面应用   [ 258 ] 么漫长的过程,用户不可能守在计算机旁等待结果,而我们通常只需要发回一个“订单已 处理”的信息就行,至于处理的过程,可能需要几个小时甚至几天,用户并不需要参与, 只需要在处理完后给用户发送信息(系统信息或邮件)就行,这种处理,就是我们常常说的“异 步”处理机制。而消息系统,就是异步处理机制最好的体现。 正如许多以前在同步、可靠性、可伸缩性和安全性方面的未知问题一样,分布式应用 程序潜在的问题也是不断增长的。一种解决方案是建立在松散耦合组件基础上的消息传递 系统,这些组件之间通过消息进行通信。 此处省略 20 页内容……   本小节还涉及到了简单 Java 线程的开发、如何设置我们自己的服务在 Flex 启动时运行 及 Flex 发送和接收消息的详细配置等知识。读者应该多动手练习,勤于思考,任何大型应 用可能分解开来就是一个又一个不起眼的小程序。开发人员的成长也是一个循序渐进、厚 积薄发的过程。 7.2.4 数据管理服务,Flex 不是花瓶! 在 7.1.3 和 7.2.2 两小节中,我们针对一个简单的用户管理系统,从 Flex RPC 服务的两 种调用形式进行了讲解,一种是直接利用 HTTPService 组件进行调用,另一种是用 RemoteObject 组件进行调用。 这个用户管理系统本质上是一个数据库的应用,就是说我们的主要操作是对数据库中 的数据进行查询和更新,并没有什么复杂的业务逻辑的运算。对于这种数据为核心的应用, LiveCycle 提供了一种更加“优雅”的专门的解决方案,那就是数据管理服务 (Data Management Service)。 在这一小节,我们给出 3 种调用数据管理服务的方式。无论是哪种方式,都需要先做 一些准备工作。首先,我们要下载 JOTM。 JOTM(Java Open Transaction Manager)是由 ObjectWeb 协会开发的功能完整的且资源 开放的独立的事务管理器。它提供了 Java 应用程序的事务支持,而且与 JTA(Java 事务 API) 兼容。由于 Tomcat 并不提供分布式事务的支持,我们必须添加 JOTM 的类库,并配置 Tomcat 以便以“插件”形式提供事务支持。 关于 JOTM 的更多详细资料,请参考 http://jotm.objectweb.org/。将 JOTM 下载后解压, 然后将根目录下的 lib 目录中的所有 jar 包拷贝到我们的 WEB-INF→lib 目录下。其次,找到 server 项目下的 server.xml 文件,找到段,将如下声明加入其中, 如下(server.xml): 好了,我们可以开始我们的 Data Service 之旅了! 第一种方式是直接修改 7.2.2 小节的应用,就是说我们将直接在 UserInfoSysRPC 项目 的基础上进行修改,不会删除任何代码和配置文件。 首先,新建一个类,让其继承自 flex.data.assemblers.AbstractAssembler,名称为 “UserAssembler”,如图 7.69 所示。 图 7.69 新建 UserAssembler 类 代码如下(UserAssembler.java): package flex.userinfosys.db.assembler; import java.util.Collection; import java.util.List; import java.util.Map; import flex.data.assemblers.AbstractAssembler; import flex.userinfosys.db.user.UserProfile; import flex.userinfosys.db.user.UserService; Flex 3 RIA 开发详解与精深实践   企业级 Web 应用与 AIR 桌面应用   [ 260 ] public class UserAssembler extends AbstractAssembler { public Collection fill(List fillArgs) { UserService service = new UserService(); return service.getUsers(); } public Object getItem(Map identity) { UserService service = new UserService(); return service.getUserProfile(((Integer) identity.get("userId")) .intValue()); } public void updateItem(Object newVersion, Object prevVersion, List changes) { UserService service = new UserService(); try { service.update((UserProfile) newVersion); } catch (Exception e) { System.out.println("Error occurred when updating userprofile: " + e.getMessage()); } } } 代码并不复杂,我们将在稍后解释其含义。 打开 flex 目录下的 data-management-config.xml 文件,默认情况下,该配置文件的内 容如下: 我们前面已经讲了适配器的概念。这里定义了两个适配器,一个是 ActionScript 对象适 配器,是用于 ActionScript 对象共享的,另一个是我们前面用到的 Java 适配器。这里给读 者简单介绍一下这两个在 Flex 数据管理服务中起着决定性作用的适配器的概念。   第 7 章  Flex 企业级开发实践——  Flex + Struts  [ 261 ] ActionScript 适配器:在服务器内存中保存对象,主要用于需要临时的分布式数据 的应用。用户客户端同步,而不是服务器“推送”服务。 Java 适配器:将数据改变传递给 Java 对象(Assembler)。实现了 DTO 模式。不仅 用于客户端同步,同时用于服务器“推”服务。开发人员需实现 Java Assembler, 负责数据的持久化。 Flex 数据管理服务在服务器端做的是根据某一个客户端的更新而更新自身数据,同时 更新其他 clients 数据。如果采用 Java 适配器则可以进行持久化。更新其他客户端数据对开 发人员来说几乎是透明的,而持久化则需要开发人员自己显式地实现。所以实际上服务器 内存中的数据起到一个枢纽作用。FDS 与客户端的数据同步可自动完成, 但需要手动把数 据持久化。 每一次客户更新通知服务器,传到服务器的是一个更新列表,包括 create、update 和 delete。每个更新元素保存在 flex.data.ChangeObject 中,可用 isCreate()、isUpdate()和 isDelete()进行判断,并通过 getNewVersion()和 getPreviousVersion()得到完整的数据元素。 每个更新元素有一个标识值,就是用来标识是哪一个元素,这在 段中设定。客 户端传给服务器的每个 ChangeObject 中都包含这个值,并来标识该元素,以及指定各个客 户端将被动态更新的元素。 需要注意的是,第一个适配器设置了 default 属性,就是说,如果有的“目标”没有设 置适配器,那么默认会使用这个适配器,这样就不必为每个目标中重复定义适配器。 在段后面加上如下定义(data-management-config.xml): flex.userinfosys.db.assembler.UserAssembler application 20 Flex 3 RIA 开发详解与精深实践   企业级 Web 应用与 AIR 桌面应用   [ 262 ] 此处省略 11 页内容……  
还剩33页未读

继续阅读

下载pdf到电脑,查找使用更方便

pdf的实际排版效果,会与网站的显示效果略有不同!!

需要 20 金币 [ 分享pdf获得金币 ] 1 人已下载

下载pdf

pdf贡献者

freemark

贡献于2010-08-29

下载需要 20 金币 [金币充值 ]
亲,您也可以通过 分享原创pdf 来获得金币奖励!
下载pdf