activemq ajax研究...
时间:2010-08-15 来源:shajunxing
Web中实现服务器推送的技术是很多的,比如Comet等等,开发框架也很多。能和消息中间件结合起来的有ActiveMQ、Kaazing等,我最终选择了ActiveMQ,因为它的支持是在是太广了,从C、C++到Java、C#,甚至Ajax、REST风格的接口,是我所喜欢的“万金油”类型。
学习了ActiveMQ官方的例子,自己也尝试了一下,下面是贴一些代码,比官方的例子要简单得多。
这是web.xml,配置了ActiveMQ的AjaxServlet,连接的是本机启动ActiveMQ的服务地址tcp://localhost:61616(ActiveMQ默认的)
<?xml version="1.0" encoding="UTF-8"?>
<web-app …>
<context-param>
<param-name>org.apache.activemq.brokerURL</param-name>
<param-value>tcp://localhost:61616</param-value>
<description>The URL of the Message Broker to connect to</description>
</context-param>
<servlet>
<servlet-name>AjaxServlet</servlet-name>
<servlet-class>org.apache.activemq.web.AjaxServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>AjaxServlet</servlet-name>
<url-pattern>/amq/*</url-pattern>
</servlet-mapping>
</web-app>
然后是页面:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title></title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<script type="text/javascript" src="amq/amq.js"></script>
<script type="text/javascript">amq.uri='amq';</script>
<script type="text/javascript" src="jquery/jquery-1.4.2.js"></script>
<script type="text/javascript">
function listener(message) {
jQuery("#receive").append("<p>" + message.nodeType + "." + message.nodeValue + "</p>");
};
function pollHandler(first) {
if (first) {
amq.addListener("test", "topic://test", listener);
}
};
jQuery(function(){
jQuery("#send").click(function(){
amq.sendMessage("topic://test", "[\"Hello\", \"Hello\"]");
});
jQuery("#clear").click(function(){
jQuery("#receive").html("");
});
amq.addPollHandler(pollHandler);
})
</script>
</head>
<body>
<button id="send">发送</button>
<button id="clear">清理</button>
<div id="receive"></div>
</body>
</html>
“发送”按钮发送消息到主题topic://test,接收到的消息直接填到div中。
同时我也写了一个Java程序来发送和接收消息,只贴发送消息的代码:
private static Destination destination;
private static String user = ActiveMQConnection.DEFAULT_USER;
private static String password = ActiveMQConnection.DEFAULT_PASSWORD;
private static String url = "tcp://localhost:61616";
private static String subject = "test";
public static void main(String[] args) {
Connection connection = null;
try {
ActiveMQConnectionFactory connectionFactory = new ActiveMQConnectionFactory(user, password, url);
connection = connectionFactory.createConnection();
connection.start();
// Create the session
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
destination = session.createTopic(subject);
// Create the producer.
MessageProducer producer = session.createProducer(destination);
// Start sending messages
producer.send(session.createTextMessage("<message>Hello</message>[\"Hello\", \"Hello\"]"));
} catch (Exception e) {
System.out.println("Caught: " + e);
e.printStackTrace(System.out);
} finally {
try {
connection.close();
} catch (Throwable ignore) {
}
}
}
使用Firefox+Firebug设置断点跟踪研究,通过Ajax发送的消息统统是纯文本的,Java程序发送的文本内容Ajax同样能够接收到,而Ajax发送的消息Java程序也能接收到,类型为TextMessage,但是Ajax中接收的消息比较要命,我倒腾了半天才发现其中的诀窍。
ActiveMQ Ajax是通过HTTP长连接接收消息的,接收到的原始消息格式大概是下面的样子:
<ajax-response>
<response id="test" destination="topic://test">消息内容</response>
</ajax-response>
id就是amq.addListener函数的第一个参数,标志Listener的,destination就是消息主题,这些都没问题,最要命的是ActiveMQ自动把消息内容解释成了DOM格式,也就是说Listener回调函数中的message参数是DOM结构的,如果是XML,那就得按照DOM的Element类型来解析,如果不是XML,那就是Text类型的,更有意思的是如果像这样一个消息:“<message>aaa</message><message>bbb</message>”,那么Listener回调函数会执行两次,因为里面包含了两个Element,如果是这样的消息:“<message>aaa</message>asdfasdfaksd”, Listener回调函数也会执行两次,““<message>aaa</message>”是Element,而“asdfasdfaksd”是Text,呵呵。
这就更加坚定了我使用Json的决心,解析由我自己做,省得和ActiveMQ撤不清。
参考:
http://activemq.apache.org/ajax.html
http://www.w3.org/TR/DOM-Level-3-Core/core.html