Flex通过Blazeds利用Remoteservice与后台java消息推送

准备工作:Myeclipse中先建立一个Web project工程,然后导入Blazeds的文件,再转换为Flex项目类型。
前言:Flex 通过开源的 BlazeDS消息服务来支持订阅及发布消息。这个消息服务管理着Flex客户端可以订阅或发布的目标地址。Flex提供了 Producer和Consumer这两个组件,让你用来向目标地址发送或订阅消息。如果要订阅消息,你就使用Consumer类的 subscribe()方法。当有消息发送到你订阅了的目标地址时,Consumer上就会触发message事件。
消息传递的目标地址是在 Flex应用根下一个叫messaging-config.xml中配置的。一个目标地址配置的关键元素是在客户端和服务器建立交换数据的通道。使用BlazeDS,消息传递的目标地址通常使用流通道或者轮询通道。
 
1, 使用流通道,服务器响应会一直保持开放状态,直到通道连接关闭,这样可以让服务器持续向客户端发送变化的数据。
2,如果数据没有立刻准备好(长轮询),就可以通过一个简单的时间间隔或者服务器等待时间来配置 轮询通道。
修改两个配置文件services-config.xml,messaging-config.xml
services-config.xml 加入以下代码:
 
 
  
  1. <channel-definition id="my-streaming-amf" class="mx.messaging.channels.StreamingAMFChannel">   
  2. <endpoint url="http://{server.name}:{server.port}/{context.root}/messagebroker/streamingamf" class="flex.messaging.endpoints.StreamingAMFEndpoint"/>   
  3.     <properties> 
  4.           <idle-timeout-minutes>0</idle-timeout-minutes> 
  5.           <max-streaming-clients>10</max-streaming-clients> 
  6. <server-to-client-heartbeat-millis>5000  
  7. </server-to-client-heartbeat-millis> 
  8.       <user-agent-settings> 
  9.        <user-agent match-on="MSIE" kickstart-bytes="2048" max-streaming-connections-per-session="1"/> 
  10.        <user-agent match-on="Firefox" kickstart-bytes="2048" max-streaming-connections-per-session="1"/> 
  11.        </user-agent-settings> 
  12.      </properties> 
  13. </channel-definition>   
messaging-config.xml 加入以下代码
 
 
  
  1. <destination id="message-data-feed"> 
  2.        <properties> 
  3.         <server> 
  4.            <allow-subtopics>true</allow-subtopics> 
  5.            <subtopic-separator>.</subtopic-separator> 
  6.         </server> 
  7.       </properties> 
  8.       <channels> 
  9.            <channel ref="my-polling-amf" /> 
  10.            <channel ref="my-streaming-amf" /> 
  11.       </channels> 
  12. </destination> 
注:这里的 id就是目标地址,也就是在flex代码中需要订阅消息的Consumer的属性destination所要设置的值,以及发布消息java后台代码AsyncMessage的setDestination()所要传递的参数,必须保证这三个地方名称一致。正是通过这一个目标地址,信息发布者就会将信息发布到该目标地址,然后所有已经设置订阅了该目标地址的flex就会触发MessageEvent.MESSAGE事件,来获取发布的消息。
Flex前端代码:
 
 
  
  1. <?xml version="1.0" encoding="utf-8"?> 
  2. <s:Application xmlns:fx="http://ns.adobe.com/mxml/2009"   
  3.               xmlns:s="library://ns.adobe.com/flex/spark"   
  4.               xmlns:mx="library://ns.adobe.com/flex/mx"   
  5. minWidth="955" minHeight="600"> 
  6.     <fx:Script> 
  7.        <![CDATA[  
  8.            import mx.messaging.Channel;  
  9.            import mx.messaging.ChannelSet;  
  10.            import mx.messaging.Consumer;  
  11.            import mx.messaging.events.MessageEvent;  
  12.            import mx.rpc.events.ResultEvent;   
  13.            private var myConsumer:Consumer = new Consumer();   
  14.          
  15.            //直接利用Remote来进行远程的消息调用  
  16.            //开始订阅消息  
  17.            protected function rbt_clickHandler(event:MouseEvent):void  
  18.            {  
  19.               // TODO Auto-generated method stub  
  20.               //利用远程调用来触发开始工作  
  21.               subMessage.startSendMessage("start");  
  22.               //准备开始订阅消息  
  23.         myConsumer.destination = " message -data-feed";   
  24. //这里也要与后台的主题名称必须相同  
  25.         myConsumer.subtopic = "tick";   
  26.         myConsumer.channelSet = new ChannelSet(["my-streaming-amf"]);   
  27.         myConsumer.addEventListener(MessageEvent.MESSAGE, remote_messageHandler);   
  28.         myConsumer.subscribe();   
  29.         }  
  30. //获取订阅的消息,以文本来显示显示  
  31. private function remote_messageHandler(event:MessageEvent):void   
  32.  
  33.         var mess:String = event.message.body as String;   
  34.         demot.appendText("\n"+ mess);  
  35.  
  36. //退订该消息  
  37. protected function cbr_clickHandler(event:MouseEvent):void  
  38. {  
  39.         subMessage.stopSendMessage("stop");  
  40.         myConsumer.unsubscribe(false);  
  41. }  
  42. protected function subMessage_resultHandler(event:ResultEvent):void  
  43. {}
  44. ]]> 
  45. </fx:Script> 
  46. <fx:Declarations> 
  47.      <!—用来启动消息发布 --> 
  48. <mx:RemoteObject id="subMessage" destination="RemoteMessage"   
  49.     result="subMessage_resultHandler(event)"> </mx:RemoteObject> 
  50. </fx:Declarations> 
  51.     <s:TextArea x="445" y="42" width="257" id="demot"/> 
  52.     <s:Button x="445" y="210" label="订阅消息Remote" id="rbt" click="rbt_clickHandler(event)"/> 
  53.     <s:Button x="597" y="207" label="退订消息R" id="cbr" click="cbr_clickHandler(event)"/> 
  54. </s:Application> 
 
Java 后台代码:
 
  
  1. package com.whut.daemon;  
  2. import flex.messaging.MessageBroker;  
  3. import flex.messaging.messages.AsyncMessage;  
  4. import flex.messaging.util.UUIDUtils;  
  5. public class DaemonMessage {  
  6.     private static FeedThread thread;  
  7.     //开始传递消息  
  8.     public void startSendMessage(String flags)  
  9.     {  
  10.        if (thread == null)   
  11.        {  
  12.            thread = new FeedThread();  
  13.            thread.start();  
  14.        }  
  15.     }  
  16.     //停止消息发布  
  17.     public void stopSendMessage(String flags)  
  18.     {  
  19.        thread.running=false;  
  20.        thread=null;  
  21.     }  
  22.     public static class FeedThread extends Thread   
  23.     {  
  24.        public boolean running = true;  
  25.        public void run() {  
  26.            MessageBroker msgBroker = MessageBroker.getMessageBroker(null);  
  27.            String clientID = UUIDUtils.createUUID();  
  28.            System.out.println("clientID="+clientID);  
  29.            while (running) {  
  30.               //异步消息  
  31.               AsyncMessage msg = new AsyncMessage();  
  32.               msg.setDestination("tick-data-feed111");  
  33.               msg.setHeader("DSSubtopic""tick");  
  34.               msg.setClientId(clientID);  
  35.               msg.setMessageId(UUIDUtils.createUUID());  
  36.               msg.setTimestamp(System.currentTimeMillis());  
  37.               msg.setBody("hello");  
  38.               msgBroker.routeMessageToService(msg, null);  
  39.               try {  
  40.                   Thread.sleep(500);  
  41.               } catch (InterruptedException e) {}}}}}  
remoting-config.xml 加入以下代码:
 
 
  
  1. <destination id="RemoteMessage"> 
  2.  <properties> 
  3.       <source>com.whut.daemon.DaemonMessage</source> 
  4.   </properties> 
  5. </destination>