如何实现Flex 3.6A+BlazeDS+Java6应用中服务器向客户端推送消息?
我看你已经在动手搭建Flex 3.6A + BlazeDS + Java 6的服务器推送服务了,正好帮你把代码和配置补全,确保客户端能稳稳拦截到推送消息。
1. 服务器端ServiceAdapter完整实现
你写的TestMessaging作为自定义消息适配器是正确的方向,我把它补全成可运行的完整代码,包含定时推送逻辑:
import flex.messaging.Message; import flex.messaging.messages.AsyncMessage; import flex.messaging.services.ServiceAdapter; import flex.messaging.util.UUIDUtils; import java.util.Random; public class TestMessaging extends ServiceAdapter { private String previousMsg = ""; private volatile boolean running; private Thread pushThread; private Random random = new Random(); @Override public void start() { super.start(); running = true; // 启动推送线程,每隔2秒发一条测试消息 pushThread = new Thread(() -> { while (running) { Message testMsg = createTestMessage(); // 推送消息到所有订阅该目的地的客户端 getDestination().pushMessageToClients(testMsg, true); try { Thread.sleep(2000); } catch (InterruptedException e) { Thread.currentThread().interrupt(); } } }); pushThread.start(); } @Override public void stop() { running = false; if (pushThread != null) { pushThread.interrupt(); } super.stop(); } private Message createTestMessage() { AsyncMessage msg = new AsyncMessage(); msg.setDestination("RandomDataPush"); msg.setClientId(UUIDUtils.createUUID()); msg.setMessageId(UUIDUtils.createUUID()); // 生成随机测试内容,避免和上一条重复 String newMsg; do { newMsg = "推送测试数据:" + random.nextInt(1000); } while (newMsg.equals(previousMsg)); previousMsg = newMsg; msg.setBody(newMsg); return msg; } @Override public Message invoke(Message message) { // 如果需要处理客户端请求,在这里实现,推送场景下可以返回null return null; } }
2. BlazeDS消息目的地配置
接下来要在BlazeDS的配置文件(一般是WEB-INF/flex/messaging-config.xml)里注册这个适配器和对应的消息目的地:
<?xml version="1.0" encoding="UTF-8"?> <service id="message-service" class="flex.messaging.services.MessageService"> <adapters> <adapter-definition id="testMessagingAdapter" class="com.yourpackage.TestMessaging" default="false"/> </adapters> <destination id="RandomDataPush"> <adapter ref="testMessagingAdapter"/> <channels> <channel ref="my-amf"/> </channels> </destination> </service>
注意替换com.yourpackage为你实际的Java包路径,my-amf是BlazeDS默认的AMF通道,如果你的项目里有自定义通道,替换成对应的通道ID即可。
3. 客户端MXML拦截推送消息
在Flex的MXML页面里,使用mx.messaging.Consumer组件订阅目的地,监听message事件来拦截推送消息:
<?xml version="1.0" encoding="utf-8"?> <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="vertical" creationComplete="initConsumer()"> <mx:Script> <![CDATA[ import mx.messaging.Consumer; import mx.messaging.events.MessageEvent; import mx.controls.Alert; private var consumer:Consumer; private function initConsumer():void { consumer = new Consumer(); consumer.destination = "RandomDataPush"; consumer.addEventListener(MessageEvent.MESSAGE, onMessageReceived); consumer.subscribe(); } private function onMessageReceived(event:MessageEvent):void { // 这里拦截到推送消息,处理逻辑写在这里 var pushContent:String = event.message.body as String; Alert.show("收到推送消息:" + pushContent, "推送通知"); // 也可以把消息显示在页面组件里 messageText.text = pushContent; } ]]> </mx:Script> <mx:Label text="最新推送消息:"/> <mx:TextArea id="messageText" width="300" height="100"/> </mx:Application>
关键注意事项
- 确保BlazeDS的核心jar包(比如
blazeds-common.jar、blazeds-messaging.jar、blazeds-core.jar)已经添加到Java项目的WEB-INF/lib目录下 - 推送线程使用了
volatile的running变量来控制启停,这是正确的线程安全做法,避免线程无法停止的问题 - 客户端的
Consumer必须和服务器端配置的destination名称完全一致,否则无法订阅到消息 - Java 6环境下,
UUIDUtils的包路径是flex.messaging.util.UUIDUtils,不要导错包
内容的提问来源于stack exchange,提问作者Giacomo Chiavarini
相关产品推荐
相关产品推荐

