ActiveMQ(四)———Ajax调用

来源:互联网 发布:线性回归 知乎 编辑:程序博客网 时间:2024/05/01 15:40

一、背景

使用aciveMQ最多的场景就是服务器端向客户端推送消息,当然这里的服务器+客户端合起来组成了消费者或者生产者,不要理解成客户端成了消费者,服务器端成了生产者。activeMQ使用ajax来监听服务器端推送的消息主要是用到了一种特殊的轮询保持机制。一般的轮询就是间隔一段时间向服务器请求数据,此时服务器会立马给出应答。而轮询保持则是向服务器发送了请求(包括等待时间比如20秒),服务器接受到请求之后会立马查询消息队列是否有数据,有就立马返回,没有的话这个请求就进入阻塞状态,唤醒时间设置为20秒。20秒之后发现数据则立马返回,否则20秒结束之后再返回,此时客户端(浏览器)会再发起另一个请求。这样占用的服务器资源较少,但是达到了实时的目的。

二、服务器端配置

Web.xml

当客户端向服务器发送请求时,都会请求到这个servlet<servlet>    <servlet-name>AjaxServlet</servlet-name>    <servlet-class>org.apache.activemq.web.AjaxServlet</servlet-class></servlet><servlet-mapping>    <servlet-name>AjaxServlet</servlet-name>    <url-pattern>/amq/*</url-pattern></servlet-mapping>MQ的部署地址,用于服务器端访问消息队列<context-param>     <param-name>org.apache.activemq.brokerURL</param-name>     <param-value>tcp://127.0.0.1:61616</param-value></context-param>因为ajax+activemq需要servlet3.0的支持,而servlet3.0又只有在tomcat7中得到支持,所以加上jetty此包,就能在tomcat5,tomcat6运行了。<!-- 兼容tomcat7.0以下 --><filter>      <filter-name>session</filter-name>      <filter-class>org.eclipse.jetty.continuation.ContinuationFilter</filter-class>  </filter>  <filter-mapping>      <filter-name>session</filter-name>      <url-pattern>/*</url-pattern>  </filter-mapping> 

Pom.xml

<dependency>            <groupId>org.apache.activemq</groupId>        <artifactId>activemq-all</artifactId>        <version>5.8.0</version>   </dependency>   <dependency>        <groupId>org.apache.activemq</groupId>        <artifactId>activemq-web</artifactId>        <version>5.8.0</version>   </dependency>   <dependency><!-- 兼容tomcat7.0以下 -->    <groupId>org.eclipse.jetty.aggregate</groupId>    <artifactId>jetty-all-server</artifactId>    <version>7.6.7.v20120910</version></dependency>

三、客户端(浏览器)配置

1、引入js文件,jquery.js类库支持,amq_jquery_adapter.js封装amq的ajax和log方法,amq是消息交互处理的核心文件。

<script type="text/javascript" src="js/jquery.js"></script><script type="text/javascript" src="js/amq_jquery_adapter.js"></script><script type="text/javascript" src="js/amq.js"></script>

2、初始化请求参数

var amq = org.activemq.Amq;  amq.init({     uri: '/amq',     logging: true,    timeout: 20,    clientId:"123"    //clientId:(new Date()).getTime().toString()  });

Uri表示浏览器请求服务器端时的地址
Logging表示浏览器在与服务器端交互时是否打印js日志
Timeout表示轮询保持的时间
Clientid表示浏览器的身份,如果用同一个字符串,则只有一个窗口会生效;如果用时间做参数,那么每一个浏览器窗口就相当于不同的消费者。

3、获取消息之后回调函数处理

var myHandler ={    rcvMessage: function(message){        console.log(message.data);        console.log(message.nodeValue);        console.log(message.wholeText);        //var bidData = eval('('+ message.textContent+ ')');    }  };

这个函数是接收到消息之后的回调函数,至于回调函数的参数是一个js对象,取值的方法根据字符串和xml格式还不一样。最好的方式就是先研究一下amq.js的源代码,下面我直接给出不同的格式不同的取值方法。
消息队列中的消息是xml格式<ds><dd>xml格式1</dd><ss>xml格式2</ss></ds>
Message.nodeName = “ds”
Message.childNodes[0].nodeName = “dd”
Message.childNodes[0].textContent= “xml格式1”
Message.childNodes[1].nodeName = “ss”
Message.childNodes[1].textContent= “xml格式2”
消息队列中的消息是json格式"{'firstName':'Bill' , 'lastName':'Gates' }"
Message.data= "{'firstName':'Bill' , 'lastName':'Gates' }",这里data、nodeValue、wholeText、textContent均可取值。

4、客户端监听和发送消息

amq.addListener('topic_js','topic://topic_js2',myHandler.rcvMessage);amq.sendMessage(myDestination,myMessage);

浏览器向服务器端发送注册监听器和发送消息的请求。
topic_js表示消费者的一个ID,接受到消息回调时会用到作为标识
topic://topic_js2表示目的地,也可以为queue
myHandler.rcvMessage表示回调函数


最后附上一段查看源码之后的总结,具体的奥秘还是需要自己去体会,收获会很大。

首先服务器端启动的时候如果设置的自动启动<load-on-startup>1</load-on-startup>,那么就会初始化这个AjaxServlet并调用它的init方法。Init方法里面包含了ConnectionFactory的初始化。当客户端调用init()方法之后会不断给服务器发送请求,请求的保持时间是20秒。一旦收到服务器的响应之后,会解析里面的数据,如果有对应数据则判断客户端是否注册回调函数,有则会调用回调函数,否则抛出异常。当请求第一次到达服务器时,会根据sessionId+clientId组装成AjaxWebClient,这个AjaxWebClient包含了对应的监听器以及消费者,会立马获取一次消息,如果没有消息则会让这个请求挂起20秒,并且将这个异步挂起状态传递给监听器,当这个监听器收到ActiveMQ的消息时,会唤醒这个挂起的请求,然后进一步组装消息用来响应客户端。如果20秒之内,监听器都没有收到消息,那么这个请求会自动被唤醒,然后设置返回状态码为200,以及返回一些基本的数据给客户端,客户端会解析这个数据,发现没有想要的数据就不会调用回调函数,继续发起下一个请求。调用addListener,会向服务器发送一个POST请求,会组装和GET请求一样的AjaxWebClient,会根据topic://topic_js2来生成对应的Topic或者QUEUE,名称为topic_js2。然后会判断这个请求是要干嘛,当请求参数里面包含listen时,会创建一个消费者并且绑定监听事件,监听消息队列。

1 1
原创粉丝点击