这几天用spring-flex做一个能够接收离线消息的Flex应用,在网上找了很多资料,但是都没提到如何实现离线消息,最后在blazeds的开发文档里找到了如何让blazeds message service实现持久化订阅JMS消息。但是还是找不到在spring-flex里如何配置,最后只能两个并用了,下面把过程贴上来给大家看看!
环境:
JMS服务器: activemq5.2
spring-flex 1.0
blazeds
1、首先是在tomcat中配置JMS服务器信息:
在应用根目录下/META-INF/context.xml(没有可以自己创建)中增加如下内容:
- < Context antiJARLocking = "true" >
- < Resource
- name = "jms/flex/ActiveMqConnectionFactory"
- auth = "Container"
- type = "org.apache.activemq.ActiveMQConnectionFactory"
- description = "JMS Connection Factory"
- factory = "org.apache.activemq.jndi.JNDIReferenceFactory"
- brokerURL = "tcp://localhost:61616"
- brokerName = "LocalActiveMQBroker"
- useEmbeddedBroker = "false" />
- < Resource name = "jms/JMSChat"
- auth = "Container"
- type = "org.apache.activemq.command.ActiveMQTopic"
- factory = "org.apache.activemq.jndi.JNDIReferenceFactory"
- physicalName = "stockQuoteTopic" />
- </ Context >
2、在web.xml文件中增加如下内容:
- < resource-ref >
- < description > Connection Factory </ description >
- < res-ref-name > jms/flex/ActiveMqConnectionFactory </ res-ref-name >
- < res-type > javax.jms.QueueConnectionFactory </ res-type >
- < res-auth > Container </ res-auth >
- </ resource-ref >
- < resource-env-ref >
- < resource-env-ref-name > jms/JMSChat </ resource-env-ref-name >
- < resource-env-ref-type > javax.jms.Topic </ resource-env-ref-type >
- </ resource-env-ref >
3、接下来是配置Blazeds的message service
- <? xml version = "1.0" encoding = "UTF-8" ?>
- < service id = "message-service" class = "flex.messaging.services.MessageService" >
- < adapters >
- < adapter-definition id = "actionscript" class = "flex.messaging.services.messaging.adapters.ActionScriptAdapter" default = "true" />
- < adapter-definition id = "jms" class = "flex.messaging.services.messaging.adapters.JMSAdapter" />
- </ adapters >
- < destination id = "JMSChat" >
- < properties >
- <!--这里的配置是最关键的,只有durable 属性设计为true才能实现持久化订阅-->
- < server >
- < durable > true</ durable >
- </ server >
- < jms >
- < destination-type > Topic </ destination-type >
- < message-type > javax.jms.TextMessage </ message-type >
- < connection-factory > java:comp/env/jms/flex/ActiveMqConnectionFactory </ connection-factory >
- < destination-jndi-name > java:comp/env/jms/JMSChat </ destination-jndi-name >
- < delivery-mode > PERSISTENT </ delivery-mode >
- < message-priority > DEFAULT_PRIORITY </ message-priority >
- < acknowledge-mode > AUTO_ACKNOWLEDGE </ acknowledge-mode >
- < initial-context-environment >
- < property >
- < name > Context.INITIAL_CONTEXT_FACTORY </ name >
- < value > org.apache.activemq.jndi.ActiveMQInitialContextFactory </ value >
- </ property >
- < property >
- < name > Context.PROVIDER_URL </ name >
- < value > tcp://localhost:61616 </ value >
- </ property >
- </ initial-context-environment >
- </ jms >
- </ properties >
- < channels >
- < channel ref = "my-polling-amf" />
- < channel ref = "my-streaming-amf" />
- </ channels >
- < adapter ref = "jms" />
- </ destination >
- </ service >
4、前端Flex聊天室代码
- <? xml version = "1.0" encoding = "utf-8" ?>
- < mx:Application creationComplete = "init()" xmlns:mx = "http://www.adobe.com/2006/mxml" fontSize = "12" >
- < mx:Script >
- <![CDATA[
- import mx.controls.Alert;
- import mx.messaging.messages.AsyncMessage;
- import mx.messaging.messages.IMessage;
- import flash.external.ExternalInterface;
- //以下代码向浏览器反向插入js方法监听浏览器关闭事件
- private function init():void{
- ExternalInterface.call(FUNCTION_USEREXIT);
- ExternalInterface.addCallback("checkExit",checkExit);
- }
- //关闭浏览器时退出
- public function checkExit():String {
- logout();
- var userExitStr:String = "你已经离开聊天室,下次再见!";
- return userExitStr;
- }
- //监听浏览器关闭事件函数
- private static var FUNCTION_USEREXIT:String =
- "document.insertScript = function () " +
- "{ " +
- "window.onbeforeunload = function() " +
- "{ " +
- "var flexObj = JMSChat.checkExit(); " +//JMSChat是swf在html中object的id
- "if(flexObj != \"\") " +
- "{ " +
- "return flexObj; " +
- "}else{ " +
- "return; " +
- "} " +
- "} " +
- "} ";
- private function login():void{
- //订阅主题的时候带上一个唯一ID,jms服务器会记录ID,在下次登录时发送离线消息
- if(userName.text==""){
- Alert.show("请输入您的用户名");
- }else{
- consumer.subscribe(userName.text);
- userName.enabled=false;
- }
- }
- private function logout():void{
- //退订消息的时候,true表示在jms服务器端记录离线消息,flase的时候将不记录离线消息
- consumer.unsubscribe(true);
- userName.text="";
- userName.enabled=true;
- }
- private function send():void
- {
- var message:IMessage = new AsyncMessage();
- if(userName.enabled){
- Alert.show("您还未登录!");
- }else{
- message.body=userName.text+" : "+ msg.text;
- producer.send(message);
- msg.text = "";
- }
- }
- private function messageHandler(message:IMessage):void
- {
- chatRoom.text += message.body+ "\n";
- }
- ]]>
- </ mx:Script >
- < mx:ChannelSet id = "cs" >
- < mx:AMFChannel url = "http://192.168.0.109:8080/FlexJms/messagebroker/amflongpolling" />
- < mx:AMFChannel url = "http://192.168.0.109:8080/FlexJms/messagebroker/amfpolling" />
- </ mx:ChannelSet >
- < mx:Producer id = "producer" destination = "JMSChat" channelSet = "{cs}" />
- < mx:Consumer id = "consumer" destination = "JMSChat" channelSet = "{cs}"
- message = "messageHandler(event.message)" />
- < mx:Panel title = "聊天室" width = "100%" height = "100%" >
- < mx:TextArea id = "chatRoom" width = "100%" height = "100%" />
- < mx:ControlBar >
- < mx:Label text = "用户名" />
- < mx:TextInput id = "userName" />
- < mx:TextInput id = "msg" width = "100%" enter = "send()" />
- < mx:Button label = "发送" click = "send()" />
- < mx:Button label = "登陆" click = "login()" />
- < mx:Button label = "退出" click = "logout()" />
- < mx:Button label = "清屏" click = "chatRoom.text=''" />
- </ mx:ControlBar >
- </ mx:Panel >
- </ mx:Application >
以下是截图:
这个时候我们“退出test”, 然后用test2发送多条信息!
过两分钟后我们再用test登录:
这就简单的实现了离线消息的发送。下图是activemq控制台上持久消息订阅用户信息图:
可通过http://localhost:8161/admin 查看.
这里记录了JMS信息的持久订阅者及等发送信息等内容。