Spring BlazeDS Integration简介与入门
integrationflow的使用

integrationflow的使用IntegrationFlow是Spring Integration框架中的一个关键概念,它提供了一种简单而强大的方式来处理应用程序中的消息传递和集成。
通过IntegrationFlow,我们可以定义消息的传递路径和处理逻辑,以实现不同应用系统之间的数据交换和业务流程的协调。
一种常见的使用场景是在微服务架构中,不同的微服务通过消息队列进行通信。
IntegrationFlow可以帮助我们将消息从一个微服务传递到另一个微服务,并在传递过程中进行数据转换、过滤和路由等操作。
在使用IntegrationFlow时,首先需要定义一个消息通道(Message Channel)。
消息通道是消息在不同组件之间传递的媒介,类似于一个队列或管道。
接下来,我们可以通过IntegrationFlow的DSL(领域特定语言)来定义消息的传递路径和处理逻辑。
IntegrationFlow的DSL提供了丰富的操作符和方法,以便我们灵活地定义消息的处理流程。
例如,我们可以使用transform操作符对消息进行转换,使用filter操作符对消息进行过滤,使用split操作符将消息拆分成多个部分等。
通过这些操作符的组合,我们可以构建出复杂的消息处理流程。
除了基本的操作符,IntegrationFlow还提供了一些高级特性,例如消息路由、消息聚合和消息延迟等。
通过这些特性,我们可以实现更加灵活和高效的消息处理逻辑。
总的来说,IntegrationFlow提供了一种简单而强大的方式来处理应用程序中的消息传递和集成。
通过定义消息的传递路径和处理逻辑,我们可以实现不同应用系统之间的数据交换和业务流程的协调。
在使用IntegrationFlow时,我们可以通过DSL来定义消息处理流程,并利用其丰富的操作符和特性来实现灵活和高效的消息处理。
Spring Integration 系统集成

Spring Integration 系统集成Spring Ingegration 提供了基于Spring的EIP(Enterprise Integration Patterns,企业集成模式)的实现。
Spring Integration 主要解决的问题是不同系统之间交互的问题,通过异步消息驱动来达到系统交互时系统之间的松耦合。
Spring Integration 主要有Message、Channel、Message EndPoint组成。
MessageMessage是用来在不同部分之间传递的数据。
Message有两部分组成:消息体(payload)与消息头(header)。
消息体可以是任何数据类型;消息头表示的元数据就是解释消息体的内容。
/*** A generic message representation with headers and body.** @author Mark Fisher* @author Arjen Poutsma* @since 4.0* @seeorg.springframework.messaging.support.MessageBuilder */public interface Message {/*** Return the message payload.*/T getPayload();/*** Return message headers for the message (never {@code null} but may be empty).*/MessageHeaders getHeaders();}123456789101112131415161718192021Channel在消息系统中,消息发送者发送消息到通道(Channel),消息接受者从通道(Channel)接收消息。
1、顶级接口(1) MessageChannelMessageChannel 是Spring Integration消息通道的顶级接口:public interface MessageChannel {/*** Constant for sending a message without a prescribed timeout.*/long INDEFINITE_TIMEOUT = -1;/*** Send a {@link Message} to this channel. If the message is sent successfully,* the method returns {@code true}. If the message cannot be sent due to a* non-fatal reason, the method returns {@code false}. The method may also* throw a RuntimeException in case ofnon-recoverable errors.* This method may block indefinitely, depending on the implementation.* To provide a maximum wait time, use {@link#send(Message, long)}.* @param message the message to send* @return whether or not the message was sent*/boolean send(Message message);/*** Send a message, blocking until either the message is accepted or the* specified timeout period elapses.* @param message the message to send* @param timeout the timeout in milliseconds or {@link #INDEFINITE_TIMEOUT}* @return {@code true} if the message is sent,{@code false} if not* including a timeout of an interrupt of the send*/boolean send(Message message, long timeout);}1234567891011121314151617181920212223242526272 8293031MessageChannel 有两大子接口,分别是PollableChannel(可轮询)和SubscribableChannel(可订阅)。
最佳实践:Flex Spring JAVA BLAZEDS整合

BlazeDS初始化时用于动态创建services, destinations, and adapters。
SpringRemotingDestinationBootstrapService扩展AbstractBootstrapService。
SpringRemotingDestinationBootstrapService 自动导出包含"@Service标注及以FlexService结尾"的Spring Bean为RemoteObject。
@SuppressWarnings("all")public class SpringRemotingDestinationBootstrapService extends AbstractBootstrapService {public static final String DEFAULT_INCLUDE_END_WITH_BEANS = "FlexService";private static Logger logger =LoggerFactory.getLogger(SpringRemotingDestinationBootstrapService.cla ss);private String destChannel;private String destSecurityConstraint;private String destScope;private String destAdapter;private String destFactory;private String serviceId;private String includeEndsWithBeans;@Override/***初始化入口*/public void initialize(String id, ConfigMap properties) { serviceId = properties.getPropertyAsString("service-id", "remoting-service");destFactory = properties.getPropertyAsString("dest-factory", "spring");destAdapter = properties.getProperty("dest-adapter");destScope = properties.getProperty("dest-scope");destSecurityConstraint =properties.getProperty("dest-security-constraint");destChannel = properties.getPropertyAsString("dest-channel", "my-amf");includeEndsWithBeans =properties.getPropertyAsString("includeEndsWithBeans",DEFAULT_INCLUDE_END_WITH_BEANS);Service remotingService = broker.getService(serviceId);if (remotingService == null)throw createServiceException("not found Service with serviceId:" + serviceId);createSpringDestinations(remotingService);}private ServiceException createServiceException(String message) {ServiceException ex = new ServiceException();ex.setMessage(message);return ex;}/***将Spring的Service Name自动定义为destination*/private void createSpringDestinations(Service remotingService) { WebApplicationContext wac = WebApplicationContextUtils.getWebApplicationContext(broker.getServletContext());List<String> addedBeanNames = new ArrayList();for (String beanName : wac.getBeanDefinitionNames()) {Class type = wac.getType(beanName);logger.debug("{}: {}", new Object[]{beanName,type.getName()});boolean isCreateSpringDestination = !type.isAnnotationPresent(com.grgbanking.platform.core.flex.NoneRemoti ngObject.class)|| beanName.endsWith(includeEndsWithBeans) || isCreateDestination(beanName, type);if (isCreateSpringDestination) {createSpringDestination(remotingService, beanName);addedBeanNames.add(beanName);}}("[Auto Export Spring toRemotingDestination],beanNames={}", addedBeanNames);}protected boolean isCreateDestination(String beanName, Class type) {return false;}/** <!-- 动态生成的配置内容 --> <destination id="sampleVerbose"><channels> <channel* ref="my-secure-amf" /> </channels> <adapter ref="java-object" /> * <security> <security-constraint ref="sample-users" /> </security> * <properties> <source>pany.SampleService</source>* <scope>session</scope> <factory>myJavaFactory</factory></properties>* </destination>*/protected void createSpringDestination(Service service, String destinationId) {flex.messaging.services.remoting.RemotingDestinationdestination = (flex.messaging.services.remoting.RemotingDestination) service.createDestination(destinationId);destination.setSource(destinationId);destination.setFactory(destFactory);if (destAdapter != null) {destination.createAdapter(destAdapter);}if (destScope != null) {destination.setScope(destScope);}if (destSecurityConstraint != null) {destination.setSecurityConstraint(destSecurityConstraint);}if (destChannel != null) {destination.addChannel(destChannel);}service.addDestination(destination);}2)修改SpringFactory并扩展FlexFactory根据destination的id,将Flex的destination映射为Spring的Beanpublic class SpringFactory implements FlexFactory {private static final String SOURCE = "source";/***This method can be used to initialize the factory itself.It is called*with configuration parameters from the factory tag which defines the id*of the factory.*/public void initialize(String id, ConfigMap configMap) {}/***This method is called when we initialize the definition of an instance*which will be looked up by this factory.It should validate that the*properties supplied are valid to define an instance.Any valid properties*used for this configuration must be accessed to avoid warnings about *unused configuration elements.If your factory is only used for *application scoped components,this method can simply return a factory*instance which delegates the creation of the component to the*FactoryInstance's lookup method.*/public FactoryInstance createFactoryInstance(String id, ConfigMap properties) {SpringFactoryInstance instance = new SpringFactoryInstance(this, id, properties);instance.setSource(properties.getPropertyAsString(SOURCE, instance.getId()));return instance;} // end method createFactoryInstance()/***Returns the instance specified by the source and properties arguments.*For the factory,this may mean constructing a new instance, optionally*registering it in some other name space such as the session or JNDI, and*then returning it or it may mean creating a new instance and returning *it.This method is called for each request to operate on the given item*by the system so it should be relatively efficient.*<p>*If your factory does not support the scope property,it report an error*if scope is supplied in the properties for this instance.*/public Object lookup(FactoryInstance inst) {SpringFactoryInstance factoryInstance = (SpringFactoryInstance) inst;return factoryInstance.lookup();}/***Spring工厂实例,执行实际的查找动作.**@author yrliang**/static class SpringFactoryInstance extends FactoryInstance { SpringFactoryInstance(SpringFactory factory, String id, ConfigMap properties) {super(factory, id, properties);}@Overridepublic String toString() {return"SpringFactory instance for id="+ getId() + " source=" + getSource() + " scope=" + getScope();}@Overridepublic Object lookup() {Logger logger =LoggerFactory.getLogger(SpringFactory.class);ApplicationContext appContext = WebApplicationContextUtils .getWebApplicationContext(flex.messaging.FlexContext.getServletCo nfig().getServletContext());String beanName = getSource();try {logger.debug("lookup(): bean id=" + beanName);//flex.messaging.FlexContext.getHttpRequest().getSession().getAttribute (arg0);return appContext.getBean(beanName);} catch (NoSuchBeanDefinitionException nexc) {ServiceException e = new ServiceException();String msg = "Spring service named '"+ beanName + "' does not exist.";e.setMessage(msg);e.setRootCause(nexc);e.setDetails(msg);e.setCode("Server.Processing");logger.error("",nexc);throw e;} catch (BeansException bexc) {ServiceException e = new ServiceException();String msg = "Unable to create Spring service named '" + beanName + "' ";e.setMessage(msg);e.setRootCause(bexc);e.setDetails(msg);e.setCode("Server.Processing");logger.error("",bexc);throw e;}}}}3)配置service-config.xml<?xml version="1.0" encoding="UTF-8"?><services-config><factories><factory id="spring"class="com.grgbanking.platform.core.flex.spring.SpringFactory"/> </factories><services><service-include file-path="remoting-config.xml" /><service-include file-path="proxy-config.xml" /><service-include file-path="messaging-config.xml" /><service id="spring-remoting-service"class="com.grgbanking.platform.core.flex.spring.SpringRemotingDestina tionBootstrapService"><!-- 其它生成的RemotingDestination默认属性<adapters><adapter-definition id="java-object"class="flex.messaging.services.remoting.adapters.JavaAdapter"default="true" /></adapters><default-channels><channel ref="my-amf" /></default-channels>--><properties><!--<service-id></service-id><dest-factory></dest-factory><dest-adapter></dest-adapter><dest-scope></dest-scope><dest-channel></dest-channel><dest-security-constraint></dest-security-constraint><includeEndsWithBeans></includeEndsWithBeans>--></properties></service></services>4)FLEX客户端调用this.blogFlexService = new RemoteObject("blogFlexService");//这里需要指定endpoint,因为是动态的RemotingDestination,而静态的RemotingDestination ,flex编译器会将endpoint编译进源代码.//这个也是flex编译器需要指定配置文件而导致使用flex经常会犯的错误之一.this.blogFlexService.endpoint = '../messagebroker/amf';3.公司应用案例这种整合最早是在2010年的FEEL View 5.0中使用,后台的统一平台,FEEL View5.1中都采用这种方法进行整合。
spring入门教程

spring入门教程Spring是一个开源的Java框架,用于构建企业级应用。
它提供了一种基于IoC(控制反转)和AOP(面向切面编程)的方式来管理对象和解决各种企业级应用开发中的常见问题。
在正式开始学习Spring之前,我们需要先了解一些基本概念和术语。
1. IoC(控制反转):IoC是Spring框架的核心概念之一,它通过将对象的创建和依赖关系的维护交给Spring容器来实现。
在传统的开发方式中,我们需要手动去创建对象并维护它们之间的关系,而在Spring中,我们只需要定义好对象的配置信息,Spring容器就会负责创建和管理对象。
2. AOP(面向切面编程):AOP是另一个重要的概念,它提供了一种在程序运行时动态地将代码切入到方法的过程中的方式。
通过AOP,我们可以将一些与核心业务逻辑无关的功能(如事务管理、日志记录等)从业务逻辑中分离出来,提高代码的重用性和可维护性。
3. Spring容器:Spring容器是一个用于管理和组织Spring应用中的对象的运行环境。
它负责创建、装配和管理对象,并提供了一些额外的功能,如依赖注入、AOP等。
Spring容器有两种主要的实现方式:BeanFactory和ApplicationContext。
BeanFactory是Spring最基本的容器,而ApplicationContext是BeanFactory的子接口,它提供了更丰富的功能,如国际化支持、事件发布等。
接下来,我们将一步步学习如何使用Spring构建一个简单的应用。
首先,我们需要将Spring框架的相关依赖添加到项目中,可以通过Maven或Gradle来管理依赖。
在项目的配置文件(如application.properties或application.yml)中,我们需要配置Spring的相关信息,如数据库连接、日志配置等。
然后,我们可以开始定义我们的业务逻辑了。
首先,我们需要定义一个POJO类(纯Java对象),它代表了我们的业务实体。
Spring核心技术详解

Spring核⼼技术详解⼀、Sring简介Spring是⼀个分层的Java SE/EE应⽤⼀站式的轻量级开源框架。
Spring核⼼是IOC和AOP。
Spring主要优点包括:⽅便解耦,简化开发,通过Spring提供的IoC容器,我们可以将对象之间的依赖关系交由Spring进⾏控制,避免硬编码造成的程序耦合度⾼。
AOP编程的⽀持,通过Spring提供的AOP功能,⽅便进⾏⾯向切⾯编程。
声明式事务的⽀持,在Spring中,我们可以从单调烦闷的事务管理代码中解脱出来,通过声明式⽅式灵活地进⾏事务的管理,提⾼开发效率和质量。
⽅便程序的测试,可以⽤⾮容器依赖的编程⽅式进⾏⼏乎所有的测试⼯作。
⽅便集成各种优秀框架,Spring提供了对各种优秀框架的直接⽀持。
⼆、Spring体系结构如下图所⽰,整个spring框架按其所属功能可以划分为五个主要模块,这五个模块⼏乎为企业应⽤提供了所需的⼀切,从持久层、业务层到表现层都拥有相应的⽀持,这就是为什么称Spring是⼀站式框架的原因。
核⼼模块(Core Container) Spring的核⼼模块实现了IoC的功能,它将类和类之间的依赖从代码中脱离出来,⽤配置的⽅式进⾏依赖关系描述。
由IoC容器负责类的创建,管理,获取等。
BeanFactory接⼝是Spring框架的核⼼接⼝,实现了容器很多核⼼的功能。
Context模块构建于核⼼模块之上,扩展了BeanFactory的功能,包括国际化,资源加载,邮件服务,任务调度等多项功能。
ApplicationContext是Context模块的核⼼接⼝。
表达式语⾔(Expression Language)是统⼀表达式语⾔(EL)的⼀个扩展,⽀持设置和获取对象属性,调⽤对象⽅法,操作数组、集合等。
使⽤它可以很⽅便的通过表达式和Spring IoC容器进⾏交互。
AOP模块Spring AOP模块提供了满⾜AOP Alliance规范的实现,还整合了AspectJ这种AOP语⾔级的框架。
FLEX4系列教程

RIA 是什么?RIA 是富网络应用(Rich Internet Application)的缩写,也即丰富互联网应用程序。
它只是一种技术形式而不是具体的技术。
RIA 出现的背景在 RIA 出现之前,软件开发都是基于 C/S(Client/Server)或 B/S(Browser/Server)架构,但两者各有缺点。
C/S 的主要缺点:1.开发、部署成本高传统 B/S 结构的软件需要针对不同 OS 开发对应的版本,且软件更新换代的速度越来越快自然成本会很高。
2.维护成本高服务器和客户端都需要维护管理,工作量较大且技术支持复杂。
B/S 的主要缺点:1.受限于 HTML 技术,很难像 C/S 那样产生丰富,个性的客户端界面;2.存在浏览器兼容性差问题;3.Server 端负荷较重,响应速度慢;绝大多数处理都集中在 Server 端,并且每次响应都要刷新页面(利用 Ajax 技术会有所缓解)。
随着软件的飞速发展,此时需要出现一种能够摒弃上诉缺点的新的技术形式– RIA 出现了。
目前比较流行的 RIA 技术▪Adobe 的Flex▪微软的Silverlight▪Sun 的JavaFX以上三种技术各有优势,本教程只关注目前应用较广泛的 Flex。
Flex 和 Flex SDK 是什么?Flex 是一个开源、免费的框架,用于构建在Adobe® Flash® Player 或Adobe AIR® runtimes 环境内运行的跨浏览器、桌面和操作系统的富网络应用。
Flex SDK(Flex Software Development Kit)除了包括 Flex 框架以外还包括 compilers(编译器)和debugger(调试器)等开发工具。
(这也意味着没有 Flash Builder 等 IDE 同样可以开发 Flex 应用,但效率会很低。
)授权Mozilla Public License, version 1.1 (MPL)开发语言Flex Framework : Action Script 3.0开发者Adobe Systems IncorporatedFlex 应用运行环境–Adobe® Flash® Player 和Adobe AIR® Runtimes两者都是运行环境,前者基于浏览器,后者基于桌面。
Springblazedswithamf讲解

Springblazedswithamf讲解很简单,直接经由过程flex就能拜访到java的service,假如熟悉dwr的必定知道这个与dwr有惊人的类似;然则这个构架存在一个理念上的问题,纯理念上的。
1. 耦合了客户端和办事端的开辟,客户端和办事端的开辟都须要同一个flex/services-config.xml(services-config.xml 设备了channel 和destination2. 一个客户端只能绑定一个amf办事(假如拜访不合办事器的amf办事,无法设备)3.amf构架本身的bean container,无法与传统的spring容器进行整合。
这三个问题,一度让人放弃amf框架,比如采取json协定甚至更便捷,更能跨各类说话(amf今朝只有稳定的php版本,不算稳定的java版本)好在spring blazeds 框架的出来(今朝也不算稳定)能很好的解决了这个问题。
首页和设备所有的spring mvc一样设备一个dispatcher(假设你已经懂得了spring 和amf)<servlet><servlet-name>blazeds</servlet-name><servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class><load-on-startup>1</load-on-startup></servlet><servlet-mapping><servlet-name>blazeds</servlet-name><url-pattern>/blazeds/*</url-pattern></servlet-mapping>其次在blazeds-servlet.xml设备broker<flex:message-broker />borker默认其实就是指向了上文里面的web-inf/flex/services-config.xml (当然可以指定目次的地位不必定非要在flex下面)这里面定义了channel;而本来定义的destination 则不须要在这里定义,而是经由过程直接裸露spring bean的方法来调用<flex:remote-service ref="weaponAdminService" channles="my-admin-amf" />这里的意思用weaponAdminService这个spring bean来裸露destination,同时destination的id也就是weaponAdminService; 同时应用的channl就是my-admin-amf 然后flex那边不须要如上文中设备一个J2EE server的工程,只须要正常的建立一个flex工程;经由过程amf的run-time configuration机制就可以设备var employeeRO:RemoteObject= new RemoteObject();employeeRO.destination = "weaponAdminService";var adminChannelSet:ChannelSet = new ChannelSet();employeeRO.channelSet = adminChannelSet;employeeRO.getOperation("getWeapons").addEventListener(ResultEvent.RESULT, getListResultHandler);employeeRO.getOperation("getWeapons").addEventListener(FaultEvent.FAULT, faultHandler);employeeRO.getOperation("getWeapons").send();public function getListResultHandler(event:ResultEvent):void {var results : ArrayCollection = event.result as ArrayCollection;Alert.show((results[0] as Weapon).id+"", 'OK');}public function faultHandler (event:FaultEvent):void {Alert.show(event.fault.faultString, 'Error');}如许就可以正常的结合spring 和amf 至于为什么要用amf呢?只能说看小我爱好,如今RPC的规范多得是,AMF不算主流,纯粹是因为这个是adobe原生的罢了。
Spring 入门教程

Spring 入门教程Spring入门教程2010-10-07 20:32Spring入门教程1.Spring简介(1)Spring是什么Spring是轻量级的J2EE 应用程序开源框架。
它由Rod Johnson创建。
它是为了解决企业应用开发的复杂性而创建的。
Spring使用基本的JavaBean来完成以前只可能由EJB完成的事情。
然而,Spring 的用途不仅限于服务器端的开发。
从简单性、可测试性和松耦合的角度而言,任何Java应用都可以从Spring中受益。
Spring的核心是个轻量级容器(container),实现了IoC (Inversion of Control)模式的容器,Spring的目标是实现一个全方位的整合框架,在Spring框架下实现多个子框架的组合,这些子框架之间彼此可以独立,也可以使用其它的框架方案加以替代,Spring希望提供one-stop shop的框架整合方案Spring不会特别去提出一些子框架来与现有的OpenSource框架竞争,除非它觉得所提出的框架够新够好,例如Spring有自己的MVC框架方案,因为它觉得现有的MVC方案有很多可以改进的地方,但它不强迫您使用它提供的方案,您可以选用您所希望的框架来取代其子框架,例如您仍可以在Spring中整合您的Struts框架。
Spring的核心概念是IoC,IoC的抽象概念是「依赖关系的转移」,像是「高层模块不应该依赖低层模块,而是模块都必须依赖于抽象」是IoC的一种表现,「实现必须依赖抽象,而不是抽象依赖实现」也是IoC的一种表现,「应用程序不应依赖于容器,而是容器服务于应用程序」也是IoC的一种表现。
回想一下面向对象的设计原则:OCP原则和DIP原则。
Spring的核心即是个IoC/DI的容器,它可以帮程序设计人员完成组件(类别们)之间的依赖关系注入(连结),使得组件(类别们)之间的依赖达到最小,进而提高组件的重用性,Spring是个低侵入性(invasive)的框架,Spring中的组件并不会意识到它正置身于Spring中,这使得组件可以轻易的从框架中脱离,而几乎不用任何的修改,反过来说,组件也可以简单的方式加入至框架中,使得组件甚至框架的整合变得容易。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
Spring BlazeDS Integration简介与入门作者Ryan Knight ,译者张龙发布于九月24, 2009 去年底Adobe与Spring共同宣布将联合开发一个新项目:Spring BlazeDS Integration。
其目标是:开发者可以利用Spring开发模型通过Adobe Flex、BlazeDS、Spring以及Java技术创建RIA。
这样我们就可以通过BlazeDS 公开Spring管理的服务而无需额外的配置文件。
其优势在于将Spring的易用性与Flex、BlazeDS以及Java整合起来以共同创建应用。
我将在本文中介绍Spring BlazeDS Integration项目对传统开发方式有哪些改观,同时展示一些相关示例。
首先,我们一起来看看它是如何改变应用的集成方式以及如何对现有的Spring项目进行转换使之可以利用新的集成。
最后我将对该项目的其他特性以及优势进行适当的介绍。
本文所用的示例应用是个简单的苏打(soda)服务,它提供了基本的账户信息。
其所用的数据模型是SodaAccount,代表了客户端账户信息。
以Spring的方式开发RIASpring的横空出世完全颠覆了传统Java服务端的开发方式。
它鼓励通过依赖注入的方式来装配POJO,这极大地简化了应用的开发与测试。
Spring的核心配置是通过Java bean实现的。
借助于bean,任何Java类都能被公开成为服务。
比如说,下面的配置片段就将Soda服务声明为一个Spring bean:为了将这些bean公开成为Flex客户端所用的远程服务,Integration项目采用了Spring Web MVC。
Spring Web MVC将DispatcherServlet作为一个中央分发器,用以处理任何类型的HTTP请求或是基于HTTP的远程服务。
我们可以通过相同的JavaBean配置方式来配置该DispatcherServlet以将请求转发给相应的处理器进行后续处理。
之前,BlazeDS项目会通过MessageBrokerServlet将请求路由给相应的BlazeDS Message Broker。
现在借助于Spring BlazeDS,Spring Web MVC DispatcherServlet已经替代了MessageBrokerServlet,接下来就需要配置DispatcherServlet以将请求转发给MessageBrokerHandlerAdapter。
该适配器本身是个Spring工厂bean,它会在Spring Web应用上下文中创建一个局部BlazeDS Message Broker实例,然后将Spring bean公开成为远程服务,之后Flex客户端就能够直接调用该服务了。
这种配置BlazeDS Message Broker的方式可以与Spring项目结合的更加紧密,同时还减少了将Spring bean 公开成远程服务所需的配置量。
比如说之前,我们需要在messaging.xml中声明一个单独的条目来公开Java服务,但现在可以轻松地在声明Spring bean的那个配置文件中公开远程bean。
Spring BlazeDS Integration也使用了一些标准的BlazeDS XML配置文件来配置消息基础设施。
这包括通道定义等一些内容。
该项目的下一版本将要增加与Spring Security的集成。
最初的实现会通过一个pointcut advisor来保护BlazeDS 端点。
Pointcut advisor是Spring AOP支持的一部分。
建立全新的Spring BlazeDS Integration项目——服务器端无论是建立全新的项目还是为现有的项目增加支持,步骤都是大同小异的。
第一步需要将所需的jar文件增加到程序库目录中。
可以通过Spring Source站点(/spring-flex)下载,也可以使用示例项目中的程序库。
对于这个示例来说,我们打算将一个简单的Soda Service项目修改为Spring BlazeDS项目。
首先要修改web.xml文件。
将该文件中所有对BlazeDS MessageBrokerServlet的引用都删掉,然后加上对Spring DispatcherServlet的引用:以上配置通过标准的Servlet映射模式将所有的请求路由给DispatcherServlet,同时还将上下文配置信息指定为web-application-config.xml。
标准的BlazeDS文件位于WEB-INF/flex中,其主文件为services-config.xml,其中定义了通道、日志及其他系统配置。
该文件的一个变化就是标准AMF通道的URL变成通过DispatcherServlet来路由请求:web-application-config.xml是主配置文件。
事实上,一旦配置好了其他文件,那么在大多数情况下只需要修改该文件就行了。
在web-application-config.xml文件中声明了MessageBrokerHandlerAdapter,这样就会将HTTP 消息路由给Spring管理的Message Broker。
文件中声明的框架的另一部分是MessageBrokerFactoryBean。
它对我们想处理的URL进行了映射,也就是发往Dispatch Servlet的所有请求:由于DispatcherServlet监听着/gorilla路径,因此该配置会将发送给/gorilla URL的所有请求都传给Spring管理的MessageBroker。
然后由于Message Broker使用了WEB-INF/flex/services-config.xml外的通道配置,这样发送给/gorilla /messagebroker的消息就会被路由给声明为服务的那些bean了。
这样,Message Broker就与bean发生了联系,下一步配置就是声明应用中的Spring bean并将其公开成为远程服务。
在该示例中,我们将SodaService声明为sodaBean:接下来,为BlazeDS remoting公开sodaBean:上面的配置引用了之前的Message Broker bean来公开sodaBean。
默认情况下,类中所有方法都会被公开成为远程服务。
FlexRemotingServiceExporter拥有众多选项来对服务进行配置。
比如说,我们可以通过includeMethods和excludeMethods来选择公开或是不公开哪些方法。
建立全新的Spring BlazeDS Integration项目——客户端用于连接服务器的客户端代码使用了标准的Flex RemoteObjects。
对于该示例应用,我们声明了如下的RemoteObject:凭借该remote对象,Flex客户端可以调用远程的Java服务器。
有两种手段能让客户端知道该向哪个通道发起调用。
其一是针对服务端配置文件services-config.xml来编译客户端,通常这不是一个好办法,因为它将客户端与服务器端紧密耦合在了一起。
其二是通过一个通道集将通道配置在客户端上。
对RemoteObject的调用与本地对象调用大同小异,区别在于返回结果的过程是异步的。
基于这个原因声明了一个resultHandler以在服务端的结果返回时进行回调。
在本示例中,对服务器端的调用形式如下:返回的结果是个ResultEvent,然后将其转换为sodaModel:保护远程服务——服务器端为了保护与服务器端的通信,Spring BlazeDS Integration项目使用了一个客户化的认证和授权过程。
该过程将Spring Security与BlazeDS安全过程集成起来了(注意,在本文撰写之际,该处所使用的代码仅仅存在于SVN 上。
同时我将示例所用代码的快照放到了jar文件中)。
在服务器端进行安全配置的第一步就是定义安全上下文。
这需要为用户定义用户名、密码以及相关角色等信息。
在该简单示例中,我们仅仅将用户信息定义在文件中。
真实的企业项目很可能会将这些信息放到数据库中或是使用单点登录。
我们通过一个单独的配置文件(security-context.xml)来声明系统中的用户。
需要将该文件加到DispatcherServlet上下文配置中以便服务器启动时就能对其进行加载。
如下配置片段展示了如何在web.xml文件中配置该文件:接下来,在security-context.xml文件中声明系统用户:第二步就是通过客户化的安全配置文件来配置Message Broker。
为了将额外的服务或是安全配置到Spring 管理的Message Broker上,我们需要对MessageBrokerFactoryBean增加一些额外的配置处理器。
该处理器实现了两个方法:processBeforeStartup及processAfterStartup,它们可以在Message Broker的启动前后为其设定相关的配置。
要想配置Message Broker的安全信息,我们需要设定两个处理器。
其一是登录命令,它提供了认证与授权;其二是一个安全配置处理器,它保护个别的通道与URL。
LoginCommand是BlazeDS中的一个接口名,它用于定义客户化的认证与授权过程。
接下来,SpringSecurityLoginCommand bean就将Spring Security与BlazeDS security集成起来,将BlazeDS发出的进行认证与授权的调用传递给Spring管理的安全上下文。
下面的代码片段声明了该bean的一个实例并引用了之前定义的安全上下文:第二个过程需要定义一个安全配置处理器以作为pointcut advisor,它定义了保护每个通道及URL的机制。
pointcut advisor是Spring AOP的一部分,定义了在某个方法调用之前需要调用的advice。
本质上,它会过滤对远程服务的调用然后阻止未授权的调用。
BlazeDS在内部通过AMF Filter来执行消息调用的预处理与后续处理。
这些Filter的工作方式类似于Servlet Filter并遵循着标准的pipe-and-filter设计模式。
这样,每个Filter都能阻止对消息的进一步处理。
该安全过程会通知通道的AMF Filter来增加Spring管理的安全。
为了定义安全处理器,首先需要向WEB-INF/flex/services-config.xml文件中添加两个额外的通道。
接下来我们定义一个端点源(endpoint source),它配置了需要保护的端点或通道以及访问它们所需的角色。