ActiveMQ Ajax研究

mallon 发布于 2010/08/16 18:22
阅读 3K+
收藏 9

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

加载中
0
风雨路

其实Web方式的推送,本质都是在客户端开启一个定期请求服务端的进程。这种特殊化的伺服模式的话,我觉得还是单独建立实现Http服务的应用为最好。如OSGI 。过多的参照标准的组件,会给已有的应有带来过重的负担。

0
mallon
mallon

引用来自#2楼“何应时”的帖子

其实Web方式的推送,本质都是在客户端开启一个定期请求服务端的进程。这种特殊化的伺服模式的话,我觉得还是单独建立实现Http服务的应用为最好。如OSGI 。过多的参照标准的组件,会给已有的应有带来过重的负担。

网络环境下的程序,无论是B/S还是C/S方式的,服务器端推送是必不可少的功能,原理是第一位的,而技术是第二位的,不管用什么技术实现(Comet长连接、还是最新的WebSocket),最终看的还是实现的效果和开发的难易程度,呵呵

0
风雨路

实现的效果和开发的难易程度,个人认为这是基于乙方的角度考虑,也就是开发商的角度考虑。如果基于整体考虑的话,后期的扩展以及运行的性能,这是甲方比较关注的,当然标准性是潜在的重要指标。

其实独立开发面向推送的应用,我主要也是基于这些方面考虑,新的应用模式,我还是建议在初期单独建立应用为好。呵呵

0
ulfl
ulfl

引用来自#3楼“mallon”的帖子

引用来自#2楼“何应时”的帖子

其实Web方式的推送,本质都是在客户端开启一个定期请求服务端的进程。这种特殊化的伺服模式的话,我觉得还是单独建立实现Http服务的应用为最好。如OSGI 。过多的参照标准的组件,会给已有的应有带来过重的负担。

网络环境下的程序,无论是B/S还是C/S方式的,服务器端推送是必不可少的功能,原理是第一位的,而技术是第二位的,不管用什么技术实现(Comet长连接、还是最新的WebSocket),最终看的还是实现的效果和开发的难易程度,呵呵

Comet长连接、还是最新的WebSocket这两种是什么呀,是Html5的元素吗

0
mallon
mallon

引用来自#5楼“曾雷”的帖子

引用来自#3楼“mallon”的帖子

引用来自#2楼“何应时”的帖子

其实Web方式的推送,本质都是在客户端开启一个定期请求服务端的进程。这种特殊化的伺服模式的话,我觉得还是单独建立实现Http服务的应用为最好。如OSGI 。过多的参照标准的组件,会给已有的应有带来过重的负担。

网络环境下的程序,无论是B/S还是C/S方式的,服务器端推送是必不可少的功能,原理是第一位的,而技术是第二位的,不管用什么技术实现(Comet长连接、还是最新的WebSocket),最终看的还是实现的效果和开发的难易程度,呵呵

Comet长连接、还是最新的WebSocket这两种是什么呀,是Html5的元素吗

WebSocket是HTML5的新技术,直接和服务器建立双工的套接字连接,完美实现了服务器的推送

返回顶部
顶部