1. 程式人生 > >spring boot 整合activemq 進行服務端訊息推送(web頁面)

spring boot 整合activemq 進行服務端訊息推送(web頁面)

最近公司的專案裡有需要服務端向web端實時推送訊息的需求,網上搜索了一番,有前端頁面通過定時任務向後臺傳送ajax請求重新整理,有使用第三方提供的訊息服務(GoEasy),前者因為會有很多請求是無用的,容易加大伺服器負荷造成宕機,後者現在收費了(免費的也只能用一年並且使用上有所限制)。後來在網上看到activemq可以通過ajax請求訪問訂閱訊息,於是便想到用activemq來實現此功能並記錄下來,供自己以及需要幫助的程式設計師朋友參考學習。

1. 我專案使用的spring boot並且maven依賴的,下面貼出activemq的maven依賴:
<dependency>
            <groupId
>
org.apache.activemq</groupId> <artifactId>activemq-broker</artifactId> <version>5.15.2</version> <scope>system</scope> <systemPath>${project.basedir}/lib/activemq-broker-5.15.2.jar</systemPath> </dependency
>
<dependency> <groupId>org.apache.activemq</groupId> <artifactId>activemq-client</artifactId> <version>5.15.2</version> <scope>system</scope> <systemPath>${project.basedir}/lib/activemq-client-5.15.2.jar</systemPath
>
</dependency> <dependency> <groupId>org.apache.activemq</groupId> <artifactId>activemq-kahadb-store</artifactId> <version>5.15.2</version> <scope>system</scope> <systemPath>${project.basedir}/lib/activemq-kahadb-store-5.15.2.jar</systemPath> </dependency> <dependency> <groupId>org.apache.activemq</groupId> <artifactId>activemq-spring</artifactId> <version>5.15.2</version> <scope>system</scope> <systemPath>${project.basedir}/lib/activemq-spring-5.15.2.jar</systemPath> </dependency> <dependency> <groupId>org.apache.activemq</groupId> <artifactId>hawtbuf</artifactId> <version>1.11</version> <scope>system</scope> <systemPath>${project.basedir}/lib/hawtbuf-1.11.jar</systemPath> </dependency> <dependency> <groupId>org.apache.activemq</groupId> <artifactId>activemq-web</artifactId> <version>5.15.2</version> <scope>system</scope> <systemPath>${project.basedir}/lib/activemq-web-5.15.2.jar</systemPath> </dependency> <dependency> <groupId>javax.jms</groupId> <artifactId>jms</artifactId> <version>1.1</version> </dependency>
這裡要說明一下,我這裡是把activemq的jar包放在了本地,所以採用這種本地依賴方式。

2.  接著是後臺向activemq傳送訊息的程式碼:
public class ActiveMQUtil {
    /**
         * 傳送訊息至mq
         * @param topic     主題
         * @param message   訊息內容
         */
        public static void sendMessage(String topic, String message){
            ConnectionFactory connectionFactory; 
            Connection connection = null;
            Session session; 
            Destination destination; 
            MessageProducer producer; 
            // 構造ConnectionFactory例項物件,此處採用ActiveMq的實現jar
            connectionFactory = new ActiveMQConnectionFactory(
                    ActiveMQConnection.DEFAULT_USER,
                    ActiveMQConnection.DEFAULT_PASSWORD, Const.MQ_BROKEN_URL);

            try { // 構造從工廠得到連線物件
                connection = connectionFactory.createConnection();
                // 啟動
                connection.start();
                // 獲取操作連線
                session = connection.createSession(Boolean.TRUE,
                        Session.AUTO_ACKNOWLEDGE); 
                destination = session.createTopic(topic);
                // 得到訊息生成者【傳送者】
                producer = session.createProducer(destination);   
                // 設定不持久化,實際根據專案決定
    //            producer.setDeliveryMode(DeliveryMode.NON_PERSISTENT);
                // 構造訊息
                TextMessage textMsg = session.createTextMessage();
                textMsg.setText(message);
                producer.send(destination, textMsg);
                session.commit();
            } catch (Exception e) { 
                e.printStackTrace();
            } finally {
                try {
                    if (null != connection)
                        connection.close();
                } catch (Throwable ignore) {
                }
            }
        }
}
3 向spring boot中注入activemq處理ajax請求的servlet,程式碼片段如下:
   /**
     * 注入activemq的ajax控制器
       @Bean
    public ServletRegistrationBean ajaxServletRegistration() {
    ServletRegistrationBean registration = new ServletRegistrationBean(new AjaxServlet());
    registration.setEnabled(true);
        registration.addUrlMappings("/amq/*");
        return registration;
    }
    //向servletContext中初始化activemq的訊息訪問url
    @Bean
    public ServletContextInitializer initializer() {
        return new ServletContextInitializer() {

            @Override
            public void onStartup(ServletContext servletContext) throws ServletException {
                servletContext.setInitParameter("org.apache.activemq.brokerURL",    "tcp://localhost:61616");
            }
        };
    }

4 程式碼裡呼叫傳送訊息的工具類方法,比如商品下架了,要給商戶傳送通知訊息:

    //msg為topic,可根據專案實際情況自由決定
    ActiveMQUtil.sendMessage("msg","您的商品被下架了");

5 前臺頁面ajax呼叫:
5.1 先要引入activemq的ajax外掛:
由於我使用的是基於jQuery的adapter,所以還要引入jQuery,另外amq_jquery_adapter.js和amq.js在下載的activemq的壓縮包中\webapps-demo\demo\js目錄下有(ajax功能好像是5.6以後版本才有的)。

<script src="jquery.min.js?v=2.1.4"></script>
<script src="amq_jquery_adapter.js"></script>
<script src="amq.js"></script>

5.2 接著是js呼叫:

window.onload = function() {
            var amq = org.activemq.Amq;
            amq.init({ uri: '/amq', logging: false, timeout: 45, clientId:'test1' });
            var myHandler ={
                rcvMessage: function(message){
                    //接收到訊息後,自己的業務處理邏輯
                }
            };
            amq.addListener('test1','topic://msg',myHandler.rcvMessage);
            //test1為消費者的一個ID,接受到訊息回撥時會用到作為標識 
            //topic://msg表示主題訂閱目的地
};

說明:
uri為前面注入activemq的ajax控制器時定義的訪問url;
Clientid表示瀏覽器的身份,如果用同一個字串,則只有一個視窗會生效;如果用時間或者登陸的使用者id或其他唯一值做引數時,那麼每一個瀏覽器視窗就相當於不同的消費者。
myHandler接收到訊息之後的回撥函式

以上就是專案中使用activemq進行訊息推送接收的程式碼片段,目前已經在生產環境完美執行,當後臺傳送訊息到activemq時,前端頁面都能實時的讀取到並執行相應的業務邏輯。