领先一步
VMware 提供培训和认证,助力你加速进步。
了解更多今天我们宣布开源 Spring 项目组合的最新成员 Spring BlazeDS 集成 1.0 GA 版本正式发布。配合此事件,我认为是时候更新我的之前的入门文章了。回顾一下
该项目的目的是使使用 Adobe Flex 作为前端客户端构建 Spring 驱动的富互联网应用程序 (RIA) 更加容易。它旨在通过提供一流的支持,将开源 Adobe BlazeDS 项目及其强大的远程调用和消息传递功能与熟悉的 Spring 编程模型结合使用,从而实现这一目的。
现在项目发行版中包含了与 Adobe 合作构建的大量示例,这些示例展示了各种功能的使用,被称为 Spring BlazeDS 集成试用版。这些示例是快速开始使用该项目的好方法,在这里我将快速介绍一下它们是如何协同工作的。
如果你想在 IDE 中跟着操作,请下载发行版并按照这些说明使用 Maven 构建示例并将其导入到 Eclipse 中。最终结果是你的 Eclipse 工作空间中会导入相当多的新项目。大多数项目用于独立的 Flex 示例(即它们包含 .mxml 和 .as 源代码并编译为 .swf 文件)。实际可部署的 WTP Web 应用程序结构位于“testdrive”项目中,这也是我们首先关注的地方。
在项目中首先值得一看的是 /testdrive/src/main/webapp/WEB-INF/web.xml。在这里你会看到一个相当典型的根 Web 应用程序上下文配置,通过 ContextLoaderListener 进行配置,以及 Spring Security 过滤链的基本设置,还有 Spring DispatcherServlet 的这个配置
<servlet>
<servlet-name>testdrive</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>testdrive</servlet-name>
<url-pattern>/messagebroker/*</url-pattern>
</servlet-mapping>
这取代了你在典型独立 BlazeDS 应用程序中会发现的 MessageBrokerServlet 配置。/messagebroker/* 路径的映射对应于你在 /testdrive/src/main/webapp/WEB-INF/flex/services-config.xml 中会找到的典型 BlazeDS AMF 通信通道设置,例如这个
<channel-definition id="my-amf" class="mx.messaging.channels.AMFChannel">
<endpoint url="http://{server.name}:{server.port}/{context.root}/messagebroker/amf"
class="flex.messaging.endpoints.AMFEndpoint"/>
</channel-definition>
这是 BlazeDS 的主要配置文件。在示例中查看此文件时,请注意“services”部分中没有引用 remoting-config.xml 或 messaging-config.xml。Spring BlazeDS 集成的一个好处是,以前在那些 BlazeDS 特定文件中定义的设置现在可以通过提供的 Spring XML 配置命名空间和 Java 注解完全定义。这大大减少了思维上下文切换,此外,如果你使用免费的 SpringSource Tool Suite,在编辑 Spring 配置文件时可以获得完整的代码自动完成支持。
现在让我们看看示例的 Spring 应用程序上下文的一些方面。
应用程序设置了一个根 Web 应用程序上下文,该上下文由 /testdrive/src/main/webapp/WEB-INF/spring 中的 *-context.xml 文件组装而成,以及一个子应用程序上下文,该子应用程序上下文是前述 DispatcherServlet 本地的,由 /testdrive/src/main/webapp/WEB-INF/testdrive-servlet.xml(其名称和位置由约定确定)组装而成。我们将所有 Flex 特定的配置分离到这个子上下文中。
让我们进一步详细检查 testdrive-servlet.xml。该文件以必要的 XML 序言开头,用于设置标准的 Spring "beans" 配置命名空间以及新的 "flex" 命名空间。然后你首先会看到 BlazeDS MessageBroker 的基本设置
<flex:message-broker>
<flex:message-service
default-channels="my-streaming-amf,my-longpolling-amf,my-polling-amf" />
<flex:secured />
</flex:message-broker>
message-broker 标签是触发将 MessageBroker 作为 Spring 管理的 bean 进行引导的标记,并自动设置所有必需的 Spring MVC 基础设施,包括 HandlerMapping 和 HandlerAdapter。你可以通过可选属性和标签进一步定制,例如 services-config.xml 的位置、映射到 MessageBroker 的特定路径等,但在一般情况下,这些就足够了。
message-service 子标签正在为 BlazeDS MessageService 设置默认通信通道(按优先级顺序)。此标签完全可选,但通常需要类似的设置,因为发布/订阅消息的通信通道要求与直接远程调用的要求往往不同。有关一些指导,请参阅此BlazeDS 文档部分。
secured 标签是启用与 /testdrive/src/main/webapp/WEB-INF/spring/security-context.xml 中定义的现有 Spring Security 设置集成的全部所需。存在此标签后,由 Flex 客户端 ChannelSet API 使用驱动的身份验证请求将被路由到 Spring Security AuthenticationManager。成功身份验证返回的 ActionScript 对象包含一些额外的有用信息,例如用户的授予权限数组。(还有一些额外的安全功能和配置选项可用,超出了本文的范围,因此如果你想了解更多详细信息,我将参考相关文档。)
一旦完成了这个基本设置,你就可以开始创建远程调用和消息目的地,将你的 Flex 客户端应用程序连接到 Spring 驱动的服务。如果你查看 /testdrive/src/main/webapp/WEB-INF/spring/services-context.xml,你会看到几个数据访问对象的定义,包括这个
<bean id="contactService" class="org.springframework.flex.samples.contact.ContactDAO">
<constructor-arg ref="dataSource" />
</bean>
然后,通过 testdrive-servlet.xml 中的以下内容,将该基本 Spring bean 暴露给 Flex 客户端进行远程调用
<flex:remoting-destination ref="contactService" />
这将 bean 暴露为一个名为“contactService”的远程目的地(默认情况下,目的地名称与导出的 bean 的 ID 相同)。要从客户端访问此目的地,我们只需使用 Flex RemoteObject 类。例如,请看 /insync01/src/main/flex/insync01.mxml 中的以下代码片段
<mx:RemoteObject id="ro" destination="contactService"/>
<mx:ApplicationControlBar width="100%">
<mx:TextInput id="searchStr"/>
<mx:Button label="Search" click="ro.findByName(searchStr.text)"/>
</mx:ApplicationControlBar>
<mx:DataGrid id="dg" dataProvider="{ro.findByName.lastResult}" width="100%" height="100%"/>
如你所见,一旦连接了 RemoteObject,你可以轻松地在其上调用方法并将结果绑定到 Flex UI 控件,例如 DataGrid。Spring 管理的 MessageBroker 负责传入 HTTP 消息的路由以及 AMF 和 Java 之间的序列化。基于 POJO 的 Spring 编程模型在服务器端保持不变,这在 /testdrive/src/main/java/org/springframework/flex/samples/contact/ContactDAO.java 中“findByName”方法的实现中显而易见。
public List<Contact> findByName(String name) {
return this.template.query("SELECT * FROM contact WHERE UPPER(CONCAT(first_name, ' ', last_name)) LIKE ? ORDER BY first_name, last_name",
this.rowMapper, "%" + name.toUpperCase() + "%");
}
异步发布/订阅式通信同样简单。Spring BlazeDS 集成为三种不同的消息适配器提供集成支持
<flex:message-destination id="chat" />
这设置了一个名为“chat”的基本 AMF 目的地。定义了此目的地后,Flex 客户端可以使用 Producer 和 Consumer API 通过它进行通信。要查看此特定目的地如何使用,请查看 /chat/src/main/flex/chat.mxml 中的 Flex 聊天示例源代码。
连接由 JMS 目的地支持的消息目的地类似,使用 jms-message-destination 标签变体
<flex:jms-message-destination id="jms-chat" jms-destination="chatTopic" />
此版本引用了一个 Spring 管理的 JMS Topic(在本例中定义在 /testdrive/src/main/webapp/WEB-INF/spring/infrastructure-context.xml 中)。查看 /jmschat/src/main/flex/jmschat.mxml 中 Flex jms-chat 示例的源代码,你会注意到它与使用基本 AMF“chat”目的地的版本相同。
同样,连接到 Spring Integration MessageChannel 只需要使用 integration-message-destination 标签。务必查看试用版中的“POJO Messaging”示例,看看将简单的 POJO 消息处理器引入其中有多容易。