Blazeds体系结构
Blazeds体系结构 ? 整个体系主要包括通道、端点、消息、 Blazeds体系结构 ? 整个体系主要包括通道、端点、消息、服务、目的地、适配器等,把这些搞懂也就差不多了。通道使得组件能够和Blazeds服务端的端点通信,将请求送到目的地。端点和通道是相互映射的。
? ? 下面的例子在services-config.xml文件中创建了一个AMFChannel通道,与服务器上的AMFEndpoint通信: ? <channels> ? <channel-definition id="samples-amf" class="mx.messaging.channels.AMFChannel"> <endpoint url="http:// servername:8400/myapp/messagebroker/amf" class="flex.messaging.endpoints.AMFEndpoint"/> ?????? ?</channel-definition> </channels> ? ??? ?2.1为flex组件指定通道 ? 如果你通过-services选项指定services-config.xml文件来编译MXML文件,那么组件(RemoteObject、HTTPService等等)会自动指定一个或者多个通道配置实例。 ??? 不过如果你没有加这个编译参数,或者想自己覆写编译项的行为,那么你可以在MXML或者AS文件中为组件指定通道。当你想要为你的组件使用动态目的地的时候,整个应用级别的默认通道非常重要。 ? 通过加上-services编译参数,可以包含所有的客户端连接服务器需要的信息,但是一下情况你可能会选择手动设置通道: ? 1)????? 你不想硬编码端点路径在你编译的客户端swf文件。 2)????? 你想要动态的创建目的地(目的地不在services-config.xml文件内)。 3)????? 你想要在客户端代码控制组件使用通道的顺序。 ? 下面的代码展示了如何在MXML文件中定义通道: ? <RemoteObject id="ro"destination="Dest"> <mx:channelSet> <mx:ChannelSet> ? <mx:channels> <mx:AMFChannel id="myAmf" ? uri="http://myserver:2000/myapp/messagebroker/amf"/> </mx:channels> ? </mx:ChannelSet> </mx:channelSet> </RemoteObject> ? 下面的代码则是AS文件: ? private function run():void { ro = new RemoteObject(); var cs:ChannelSet = new ChannelSet(); cs.addChannel(new AMFChannel("myAmf", "http://servname:2000/eqa/messagebroker/amf")); ro.destination = "Dest"; ro.channelSet = cs; } ? 注意:当你在客户端代码创建通道时,还是必须在services-config.xml文件里配置一个指定端点的通道。否则,messagebroker就不能床底客户端请求到端点。 ? ?? ?2.2 ?为目的地指定通道和端点 ? ?? ?如果大多数的目的地使用使用相同的通道,你可以指定应用级别的默认通道,比如: ? ??? ?<services-config...> ... <default-channels> <channel ref="my-http"/> <channel ref="my-amf"/>s </default-channels> ... ? ??? ?也可以单独指定通道,比如: ? ?? ?<destination id="sampleVerbose"> ? <channels> <channel ref="my-secure-amf"/> </channels> ... </destination> ? ? ??? ?2.3 选择端点 ? ?????? ?????? 可以参考文档或者看blazeds通道、端点配置 消息?
? <!-- MessageBroker Servlet --> <servlet> ??? <servlet-name>MessageBrokerServlet</servlet-name>//servlet名称 ? ?? ?<display-name>MessageBrokerServlet</display-name> ? ?? ?<servlet-class>flex.messaging.MessageBrokerServlet</servlet-class>//servlet对应类 <init-param>? //初始化参数 ??????? <param-name>services.configuration.file</param-name>? //参数名:services配置文件 ??????? <param-value>/WEB-INF/flex/services-config.xml</param-value>//参数值:配置文件相对地址 ? </init-param> ? ?? ?<load-on-startup>1</load-on-startup>//启动后装载 </servlet> ? *********************************************************? *在servlet的配置当中,<load-on-startup>1</load-on-startup>的含义是: *标记容器是否在启动的时候就加载这个servlet。 *当值为0或者大于0时,表示容器在应用启动时就加载这个servlet; *当是一个负数时或者没有指定时,则指示容器在该servlet被选择时才加载。 *正数的值越小,启动该servlet的优先级越高。 ********************************************************* ? <!-- Http Flex Session attribute and binding listenersupport --> ?</listener>
? ? 服务端FlexClient、MessageClient、FlexSession类的实例代表了Flex应用和服务端的连接。你可以使用这些对象管理FLEX应用程序和服务端的同步。 ? FlexClient,MessageClient,and FlexSession objects ? FlexClient ? 每一个MXML或者AS的Flex应用都被编译进SWF文件。当SWF文件和Blazeds服务通信的时候,一个flex.message.client.FlexClient对象就被创建,并在服务端代表这个SWF文件。SWF文件和FlexClient实例具有一对一的映射关系。Blazeds服务端为每个FlexClient实例生成一个唯一的标识id。在客户端也有一个单例类mx.message.FlexClient,用于存储这个唯一的FlexClient Id。 ? MessageClient ? 如果某个Flex应用程序含有一个订阅组件(flex.message.Consumer),服务端就会创建一个相应的flex.messaging.MessageClient实例来代表这个订阅者的发布者。每个MessageClient都有一个唯一的clientId,可以自动由Blazeds服务端生成,也可以在调用Consumer.subscribe()方法之前指定这个Consumer.clientId属性。 ? FlexSession ? FlexSession对象代表在Flex程序和Blazeds服务之间的连接。它的生命周期基于通道和端点使用的底层协议。如果是基于HTTP的通道,例如AMFChannel或者HTTPChannel,在Blazeds服务端就是浏览器范围。如果它连接的端点是一个基于servlet的端点,那么这个HTTPsession是基于J2EE HttpSession 对象。 ? 三者之间的关系 ? 一个FlexObject对象可以拥有多个FlexSession实例,这取决于Flex应用使用的通道数。例如,一个程序使用了一个HTTPChannel,那么在Blazeds服务端一个FlexSession代表这个HTTP session就会被创建。 ? 一个FlexSession也可以拥有一个或多个FlexClient和它关联。例如,a SWF file that uses an HTTPChannelis opened in two tabs,在BlazeDS服务端2个FlexClient实例被创建(一个SWF文件一个),但是只有一个FlexSession,因为两个tab共享同一个HTTP session。 ? ? 每个订阅组件都会创建MessageClient。每一个MessageClient都会和一个FlexClient以及一个FlexSession关联。 ? 理解:一个channel对应一个FlexSession,一个SWF文件实例对应一个FlexClient,多个请求会创建多个SWF文件实例,服务端也将创建多个FlexClient对应每一SWF文件,但只有一个FLexSession被创建(假设他们都是用一个HTTPChannel通信) ? 关于三者的监听器 ? BlazeDS服务端提供了下列监听器,来让你根据自己的逻辑来创建、销毁、以及改变三者的状态。 ?
数据序列化 ? ?????? ?AS对象转换为Java对象 ?
Java对象转换为AS对象 ?
? // Product.as package samples.externalizable { ? import flash.utils.IExternalizable; importflash.utils.IDataInput; importflash.utils.IDataOutput; [RemoteClass(alias="samples.externalizable.Product")] public classProduct implements IExternalizable { ? public function Product(name:String=null) { this.name = name; } ? public var id:int; public var name:String; public var properties:Object; public var price:Number; ? public function readExternal(input:IDataInput):void { name = input.readObject() as String; properties = input.readObject(); price = input.readFloat(); } ? public function writeExternal(output:IDataOutput):void { output.writeObject(name); output.writeObject(properties); output.writeFloat(price); } } } ? ? // Product.java package samples.externalizable; import java.io.Externalizable; import java.io.IOException; import java.io.ObjectInput; import java.io.ObjectOutput; import java.util.Map; ? public class Product implements Externalizable { ? private String inventoryId; public String name; public Map properties; public float price; ? public Product(){ } ? public String getInventoryId() { return inventoryId; } ? public void setInventoryId(String inventoryId) { if (inventoryId != null &&inventoryId.startsWith("X")){ this.inventoryId = inventoryId; }else{ throw new IllegalArgumentException("3rd party product inventory identities must start with 'X'"); } } ? public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException { name = (String)in.readObject(); properties = (Map)in.readObject(); price = in.readFloat(); setInventoryId(lookupInventoryId(name,price)); } ? public void writeExternal(ObjectOutput out) throws IOException { // Write out the client properties from the serverrepresentation out.writeObject(name); out.writeObject(properties); out.writeFloat(price); } ? private static String lookupInventoryId(String name,floatprice) { String inventoryId = "X" + name + Math.rint(price); return inventoryId; } } ? ? 服务、目的地、适配器等,把这些搞懂也就差不多了。 通道使得组件能够和Blazeds服务端的端点通信,将请求送到目的地。 端点和通道是相互映射的。1. Blazeds客户端体系结构 ?????? Blazeds使用一个基于消息的框架与服务端结合。这个框架使用通道封装了Flex程序和Blazeds服务端之间的连接。下面是Blazeds客户端的结构 ? ?????? 以下Flex组件和Blazeds服务端结合: ?????? . RemoteObject ?????? ? HTTPService ?????? ? WebService ?????? ? Producer ?????? ? Consumer ?????? 所有的这些组件都包含在FlexSDK和rpc.swc组件库中。 ?????? 尽管RemoteObject、Producer、Consumer包含在FlexSDK中,他们仍然需要一个服务端来反编译出他们发送的消息。Blazeds和LiveCycle Data Services ES服务就是两个这样的服务端。当然Flex应用程序可以不使用Blazeds这种中间层而是直接使用HTTP Service或者Web Service来调用远程服务 2.0 通道和通道设置 ??????? Flex组件使用通道和Blazeds服务端交互。一条通道包含多条道路,他们的基础功能就是提供Flex客户端和Blazeds服务端的交流。通道中的道路都是按性能排序的。Flex组件会尝试连接第一条道路,不过这并不能保证一定能连接,有可能使用的还是道路中后面的那几条。它会搜寻通道中的道路知道连接上或者已经没有连接。
? ? 下面的例子在services-config.xml文件中创建了一个AMFChannel通道,与服务器上的AMFEndpoint通信: ? <channels> ? <channel-definition id="samples-amf" class="mx.messaging.channels.AMFChannel"> <endpoint url="http:// servername:8400/myapp/messagebroker/amf" class="flex.messaging.endpoints.AMFEndpoint"/> ?????? ?</channel-definition> </channels> ? ??? ?2.1为flex组件指定通道 ? 如果你通过-services选项指定services-config.xml文件来编译MXML文件,那么组件(RemoteObject、HTTPService等等)会自动指定一个或者多个通道配置实例。 ??? 不过如果你没有加这个编译参数,或者想自己覆写编译项的行为,那么你可以在MXML或者AS文件中为组件指定通道。当你想要为你的组件使用动态目的地的时候,整个应用级别的默认通道非常重要。 ? 通过加上-services编译参数,可以包含所有的客户端连接服务器需要的信息,但是一下情况你可能会选择手动设置通道: ? 1)????? 你不想硬编码端点路径在你编译的客户端swf文件。 2)????? 你想要动态的创建目的地(目的地不在services-config.xml文件内)。 3)????? 你想要在客户端代码控制组件使用通道的顺序。 ? 下面的代码展示了如何在MXML文件中定义通道: ? <RemoteObject id="ro"destination="Dest"> <mx:channelSet> <mx:ChannelSet> ? <mx:channels> <mx:AMFChannel id="myAmf" ? uri="http://myserver:2000/myapp/messagebroker/amf"/> </mx:channels> ? </mx:ChannelSet> </mx:channelSet> </RemoteObject> ? 下面的代码则是AS文件: ? private function run():void { ro = new RemoteObject(); var cs:ChannelSet = new ChannelSet(); cs.addChannel(new AMFChannel("myAmf",floatprice) { String inventoryId = "X" + name + Math.rint(price); return inventoryId; } } (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |