整合 Adobe Flex 和 Spring

随着 Adobe Flex 技术的成熟,越来越多的企业开始采用 Adobe Flex 技术开发 RIA (Rich Internet Application)。在常见的 RIA 应用程序架构中,客户端用 Adobe Flex 渲染出漂亮的界面,而渲染界面所需要的数据则从服务器端的应用程序获取。在 Java EE 领域,服务器端的应用程序通常是运行在 Java EE 应用服务器中,以获取安全,事务,高可靠性等企业级特性,这直接催生了整合 Abode Flex 和 Java EE 应用服务器的需求。而Spring 又是当前应用最广泛的 Java EE 应用服务器之一,本文将主要介绍如何整合这两种技术,使你能够轻松构建既健壮又漂亮的 Web 应用程序。整合 Adobe Flex 和 Spring 的关键就在于提供一种方法使得 Adobe Flex 客户端程序可以很容易访问到 Spring 管理的Bean,并避免过多的配置。利用开源框架 BlazeDS 和 Spring BlazeDS Integration 来集成 Adobe Flex 和 Spring 可以帮助你做到这一点。
BlazeDS 和 Spring BlazeDS Integration
BlazeDS, BlazeDS 是 Adobe 公司的一个开源项目,用于实现基于 Flex 的前端与基于 Java 的后端应用程序之间的远程调用和消息传送。而 Spring BlazeDS Integration 是 Adobe 和 Spring 联合开发的一个开源集成项目,目标是使得开发人员可以轻松创建前端采用 Flex 而后台采用 Spring 的RIA 应用程序,同时避免过多的配置。图1展示了 Spring BlazeDS Integration 的工作原理。首 先,在 web.xml 中注册 Spring Web MVC 框架的 DispatcherServlet,用于处理 Spring 请求,通常 DispatcherServlet 只是将接收到的 Spring 请 求转给相应的处理器(handler), 处理器会处理接收到的请求并返回一个响应。而这些处理器需要在 Spring Web MVC 框架的配置文件中进行装配,BlazeDS 就是在这里被装配为 Spring Web MVC 框架的一个处理器,用于 处理 Flex 的 远程调用请求,装配后的 BlazeDS 可以把 Spring 管理的 Bean 封装成 Flex 客户端可以远程调用的服务对象。整个过程会涉及到3个配置文件,如图1中的白色折角框所示。下面会一步一步介绍如何使用 Spring BlazeDS Integration 整 合 Flex 和 Spring。
图1 – Spring BlazeDS Integration 示意图

整合 Adobe Flex 和 Spring

软件环境要求
Java 1.5或更高版本
Tomcat 6或更高版本
Spring 2.5或更高版本
BlazeDS 3.2或更高版本
Spring BlazeDS Integration 1.0 或更高 版本
Internet Explorer 6/7/8 或Firefox 3.0/3.5
Flash player 9.0或更高版本
Flex Builder 3.0或更高版本
下面我们要用 Flex Builder 创建一个基于 Spring 的 服务器端应用程序和一个基于 Flex 的客户端应用程序,我们可以用 Flex Builder 的 Java/Flex 组合工程将二种应用程序合并到一个工程中。
创建一个 Java/Flex 组合工程
首先,启动 Flex Builder,新建一个 Flex 工程,选择Application server typeJ2EE ,并选中 Create combined Java/Flex project using WTP 复选框,该复选框的意思就是把基于 Java 的服务器端应用程序和基于 Flex 的客户端应用程序放在同一个工程中。如图2所示。
图2 – 新建 Flex 工 程

整合 Adobe Flex 和 Spring

点击按钮 Next,这里我们选择 Target runtime Apache Tomcat v6.0, 设置好 Context root Content folder,如果 Target runtime 下拉框没有想要的 J2EE server ,可以点击按钮 New创建一个。
点击按钮 Finish ,一个新的 Flex 工程就创建好了。接下来我们要把所依赖的 Spring, BlazeDS 和 Spring Blaze Integration 的 jar 文件加入到 WEB-INF/lib 目录下面。下面清单列出了这些 jar 文件。
backport-util-concurrent.jar
cfgatewayadapter.jar
commons-codec-1.3.jar
commons-httpclient-3.0.1.jar
commons-logging.jar
concurrent.jar
flex-messaging-common.jar
flex-messaging-core.jar
flex-messaging-opt.jar
flex-messaging-proxy.jar
flex-messaging-remoting.jar
org.springframework.flex-1.0.0.M1.jar
spring-beans.jar
spring-core.jar
spring-web.jar
spring-webmvc.jar
spring.jar
xalan.jar
配置 Spring DispatcherServlet

Spring 本身自带了一个 Web MVC 框架,这个 Web MVC 框架的入口点是 DispatcherServlet,它用来分发 Spring 请求到相应的处理器。为了在 Web 应用程序中使用 Spring Web MVC 框架,我们需要在 web.xml 里 面注册这个 DispatcherServlet。在上面新创建的 Flex 工程中,打开 WebContent/Web-INF/web.xml , 加入如清单1所示的代码。按照清单1的配置,当请求是发送给以 /spring 开头的 URL 时,Tomcat 会派发给 Spring Web MVC 框架来处理。另外,在清单1中把 Spring Web MVC 框架的配置文件设置为 WEB-INF/config/web-config.xml, 我们需要手动创建这个文件,接下来我们还要在这里配置 BlazeDS。
清单1 – 配置 Spring DispatcherServlet
<servlet>
<servlet-name>SpringDispatcherServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/config/web-config.xml</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>SpringDispatcherServlet</servlet-name>
<url-pattern>/spring/*</url-pattern>
</servlet-mapping>
集成 Spring 和 BlazeDS
首先我们需要在 Spring Web MVC 的配置文件 WEB-INF/config/web-config.xml 中配置 MessageBrokerFactoryBean, MessageBrokerFactoryBean 会在 Spring Web MVC 的应用程序上下文中创建 一个 MessageBroker 的实例,这意味着这个 MessageBroker 实例会被 Spring 管理,初始化 MessageBroker 实例的时候会解析 BlazeDS 的配置文件并将配置信息应用到 MessageBroker 实例。MessageBroker 实例可以用来把 Spring 管理的 Bean 封装成 Flex 客户端可直接远程调用的服务。将清单2所示的代码加入到 WEB-INF/config/web-config.xml 即可配置好 MessageBrokerFactoryBean。
清单2 – 配置 MessageBrokerFactoryBean
<bean id="mySpringManagedMessageBroker" class="org.springframework.flex.messaging.MessageBrokerFactoryBean"/>
默认情况下,MessageBrokerFactoryBean 会在 WEB-INF/flex/services-config.xml 搜索 BlazeDS 的配置文件。如果我们想把 BlazeDS 的配置文件放在其它位置,可以给 MessageBrokerFactoryBean 的 servicesConfigPath 属性赋值。如清单3所示。
清单3 – 配置 BlazeDS 的 配置文件的路径
<bean id="mySpringManagedMessageBroker" class="org.springframework.flex.messaging.MessageBrokerFactoryBean" >
<property name="servicesConfigPath" value="/WEB-INF/flexConfig/servicesconfig.xml"/>
</bean>
Flex 客户端请求首先经由 Spring Web MVC 框架的 DispatcherServlet,DispatcherServlet 负责把 Flex 请求交给相应的处理器处理。为了让 DispatcherServlet 知道要把 Flex 客户端请求转交给 Spring 管 理的 MessageBroker 处理,还需要在 Spring Web MVC 的配置文件中注册一个处理器,即把 MessageBrokerHandlerAdapter 配置为 Spring 管理的 Bean,如清单4所示。
清单4 – 配置 MessageBrokerHandlerAdapter
<bean class="org.springframework.flex.messaging.servlet.MessageBrokerHandlerAdapter"/>
接下来,我们还需要配置一下哪些 URL 可以由 Spring 管理的 MessageBroker 来处理,简单起见,我们可以设置所有经由 Spring Web MVC 框架的 DispatcherServlet 的请求都交给 MessageBroker 来处理,也就是说,客户端只能用 Flex。这需要用 Spring Web MVC 自带的 SimpleUrlHandlerMapping 来配置,如清单5所示。实际应用中我们不会让 Spring 只处理 Flex 客户端的请求,我们可能会想用 Spring 暴露一些 Restful 服务让其他的 HTTP 客户端也可以使用,这时就需要用 SimpleUrlHandlerMapping 设置更复杂的 URL-处理器匹配规则。
清单5 – 配置 SimpleUrlHandlerMapping
<bean class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
<property name="mappings">
<value>/*=mySpringManagedMessageBroker</value>
</property>
</bean>
注意/*的值 mySpringManagedMessageBroker 必须等于清单2设置的 Bean 的 id 值。由于清单1中 DispatcherServlet 被设置为监听发送给 /spring 的请求,所以现在所有发送给 /spring 的请求都会转交给 Spring 管理的 MessageBroker 来处理。如果把清单5中value的值改成/flex/*=mySpringManagedMessageBroker, 那么只有发送给 /spring/flex 的请求会转交给 Spring 管理的 MessageBroker 来处理。
到此读者朋友可能会产生疑问:你不是说可以避免过多的配置吗,到现在为止上面的这些配置就够多了。别 着急,我们之所以介绍上面的配置清单是因为想让读者了解 Spring BlazeDS Integration 的内部原理。实际上,我们完全可以用清单6所示的一行配置代码代替上面清单2,清单 4和清单5的所有配置代码,现在是不是足够简单了?当然清 单6所示的配置都是默认配置 (这里用到了 Convention over configuration 原理),如果我们不想用默认配置,比如我们想修改 BlazeDS 的默认配置文件路径,我们还需要扩展清单6的配置代码,为 <flex:message-broker> 元素加上一个 services-config-path 的属性指定其他的路径。
清单6 – 配置 Flex MessageBroker
<flex:message-broker/>
最后,轮到配置 BlazeDS 本身了,下载 BlazeDS 后,从 blazeds.war 包里面把 WEB-INF/flex 下面的4个配置文件( messaging-config.xml, proxy-config.xml, remoting-config.xml, services-config.xml )拷贝到我们创建的这个 Flex 项目的 WEB-INF/flex 下面。 打开文件 services-config.xml,按照清单7所示修改一下 AMF(Action Message Format) Channel。AMF 是基于 SOAP 的二进制格式,主要用于 Flash 客户端和远程服务器之间的数据交换,每个 AMF 消息包含了一个消息体,消息体中包含了消息响应 和错误信息,消息体可以表示为一个 ActionScript 对象,这样在 Flex 代码中就可以直接访问了。
清单7 – 配置 AMF Channel
<channel-definition id="my-amf" class="mx.messaging.channels.AMFChannel">
<endpoint url="http://{server.name}:{server.port}/{context.root}/spring/amf" class="flex.messaging.endpoints.AMFEndpoint"/>
</channel-definition>
到此为止,我们已经把 Spring 和 BlazeDS 集成起来了。为了检验我们的劳动成果是否有效, 下面我们需要创建一个 Spring 管理的 Bean 并用 BlazeDS 暴露为 Flex 客户端可远程调用的服务对象,然后创建一个 Flex 客户端调用这个 Bean。
创建并配置 Bean
在这里,我们创建一个复杂一点 的 Bean, 取名 TestBean, 这个 Bean 引用了 另外一个自定义类 User。如清单8所示,这个 Bean 有两个方法可以供远程调用,一个方法返回 String 类型,另一个返回 User 类型。
清单8 – 创建二个 Java 类
package flex.test;
public class TestBean {
public String getMessage(){
return "This is a message!";
}
public User getUser(){
User user = new User();
user.setUserage(20);
user.setUsername("username");
return user;
}
}
package flex.test;
public class User {
private String username;
private int userage;
public String getUsername() ...
public void setUsername(String username) ...
public int getUserage() ...
public void setUserage(int userage) ...
}
接下来把上面的 TestBean 类配置为一个 Spring 管理的 Bean, 并用 FlexRemotingServiceExporter 将这个 Bean 暴露成 Flex 客户端可远程调用的服务对象。打开 WEB-INF/config/web-config.xml, 加入 清单9所示的代码即可。注意清单9中 FlexRemotingServiceExporter 的两个属性,messageBroker 引用了清单3中的 MessageBrokerFactoryBean, service 属性引用了 testBean。
清单9 – 将 Spring 管 理的 Bean 暴露 为 Flex 客户 端可远程调用的服务
<bean id="testBean class="flex.test.TestBean"></bean>
<bean id="flexTestBean class="org.springframework.flex.messaging.remoting.FlexRemotingServiceExporter">
<property name="messageBroker" ref="mySpringManagedMessageBroker"/>
<property name="service" ref="testBean"/>
</bean>
也许你已经发现了问题,清单9 中 FlexRemotingServiceExporter 的属性 messageBroker 通过 id 值引用了清单3中的 MessageBrokerFactoryBean。但如果我们只用清单6来配置(我们当然会用它,这很简单),我们在清单9中就没法引用 MessageBrokerFactoryBean 了,因为清单6中没有设置 id 值。这时我们可以用清单10所示的配置代码代替清单9的配置代码。<flex:remoting-destination> 标签自动把要暴露的 bean 和 Spring Web MVC 应用程序上下文中的 MessageBroker 关联起来。
清单10 – 将 Spring 管理的 Bean 暴露为 Flex 客户端可远程调用的服务
<bean id="testBean" class="flex.test.TestBean"></bean>
<flex:remoting-destination ref="testBean"/>
创建 Flex 客户端程序
在 上面的 Java/Flex 组合工程中创建一个 MXML 应用程 序,代码如清单11所示。需要注意的是 <mx:RemoteObject> 这个标签,这个标签建立了一个通道使得 Flex 程序 能够远程异步调用 Bean 对象的方法, 调用成功后会触发一个成功调用的事件,调用失败也会触发一个调用失败的事件。这个标签的 destination 属性须与清单9中 FlexRemotingServiceExporter 的 id 属性( flexTestBean )或者清单10中 TestBean 的 id 属性( testBean )一致,fault 属性设置为当 RemoteObject 调用失败时的事件处理方法。<mx:method> 标签中的 name 属性是要被远程调用的 Bean 对象的方法名,result 属性是调用成功后的事件处理方法,在该事件处理方法中可以用事件对象的 result 属 性得到远程调用的结果。
清单11 – Flex 客户端程序
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute">
<mx:RemoteObject id="ro" destination="testBean" fault="onFault(event);">
<mx:method name="getMessage" result="gotMsg(event);"/>
<mx:method name="getUser" result="gotUser(event);"/>
<mx:channelSet>
<mx:ChannelSet>
<mx:channels>
<mx:AMFChannel id="myAmf" uri="http://localhost:8080/FlexWithSpring/spring/amf"/>
</mx:channels>
</mx:ChannelSet>
</mx:channelSet>
</mx:RemoteObject>
<mx:Script>
<![CDATA[
import ...
private function gotUser(event:ResultEvent):void {
testarea.text = testarea.text+"\n"+"======getUser=======" +"\n"+event.result.username +"\n"+event.result.userage;
}
private function gotMsg(event:ResultEvent):void {
var tmp:String = event.result as String;
testarea.text = testarea.text+"\n"+"======getMessag======="+"\n"+tmp;
}
private function _disibledevent=>
<mx:Button label="getMessage" click="ro.getMessage();"/>
<mx:Button label="getUser" click="ro.getUser();"/>
</mx:Application>
运行程序
选 择上面的的 MXML 文件,右键选择 Run As>Run _disibledevent=>
整合 Adobe Flex 和 Spring
Tags: 

延伸阅读

最新评论

发表评论