ActiveMQ消息隊列demo

前言

什麼是消息隊列?
消息是指在兩個獨立的系統間傳遞的數據,這兩個系統可以是兩臺計算機,也可以是兩個進程。
消息可以非常簡單,可以是簡單的字符串,也可以是保存了數據持久化的各種類型的文檔集合。
隊列是在消息的傳輸過程中的通道,是保存消息的容器,根據不同的情形,可以有先進先出,優先級隊列等區別 。
爲什麼要使用消息隊列?
我個人的理解是主要對業務的解耦,操作異步處理,還有流量削鋒等等問題,最終實現高性能,高可用,可伸縮和最終一致性。大家可參考這篇博客:https://blog.csdn.net/seven__________7/article/details/70225830

開始

整合準備工作:先去官網http://activemq.apache.org/activemq-5154-release.html 下載開發包,我下載的是windows版本的,得到apache-activemq-5.15.4-bin.zip這樣一個壓縮文件,解壓後,打開bin目錄下的win32或者win64文件夾(根據自己windows版本),運行activemq.bat(請確保java環境變量無誤,否則將閃退 ),保持運行窗口,打開瀏覽器訪問http://127.0.0.1:8161/admin,輸入用戶名密碼(默認均爲admin),得到下面的消息隊列控制檯頁面,即完成準備工作。
這裏寫圖片描述

下面開始代碼工作:
新建一個java工程,將開發包中的activemq-all-5.15.4.jar引入項目後即可開始。

(1)使用點對點模式,不可重複消費
創建消息發佈者JMSProducer

import javax.jms.Connection;
import javax.jms.ConnectionFactory;
import javax.jms.Destination;
import javax.jms.JMSException;
import javax.jms.MessageProducer;
import javax.jms.Session;
import javax.jms.TextMessage;

import org.apache.activemq.ActiveMQConnection;
import org.apache.activemq.ActiveMQConnectionFactory;

/**
 * 消息發佈者
 * @author zxy
 *
 */
public class JMSProducer {

    private static final String USERNAME = ActiveMQConnection.DEFAULT_USER;

    private static final String PASSWORD = ActiveMQConnection.DEFAULT_PASSWORD;

    private static final String BROKERURL = ActiveMQConnection.DEFAULT_BROKER_URL;

    private static final int SENDNUM = 10;

    public static void main(String[] args) {
        ConnectionFactory connectionFactory = null; //連接工廠
        Connection connection = null; //連接
        Session session = null; //會話接收或者發送消息的線程
        Destination destination = null; //消息的目的地
        MessageProducer messageProducer = null; //消息生產者

        //實例化連接工廠
        connectionFactory = new ActiveMQConnectionFactory(USERNAME, PASSWORD, BROKERURL);

        try {
            //通過連接工廠獲取連接
            connection = connectionFactory.createConnection();

            connection.start();

            //Boolean.TRUE表示開啓事務
            session = connection.createSession(Boolean.TRUE, Session.AUTO_ACKNOWLEDGE);

            //創建消息隊列
            destination = session.createQueue("FirstQueue1");

            //創建消息生產者
            messageProducer = session.createProducer(destination);

            //發送消息 
            sendMessage(session, messageProducer);

            //事務提交
            session.commit();
        } catch (JMSException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } finally {
            if(connection != null){
                try {
                    connection.close();
                } catch (JMSException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
        }
    }

    public static void sendMessage(Session session, MessageProducer messageProducer){
        for(int i=0;i<SENDNUM;i++){
            try {
                TextMessage textMessage = session.createTextMessage("ActiveMQ 發送的消息" + i);
                System.out.println("發送消息:ActiveMQ發送的消息" + i);
                messageProducer.send(textMessage);
            } catch (JMSException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    }

}

創建消息消費者JMSConsumer,兩種消費方式:

import javax.jms.Connection;
import javax.jms.ConnectionFactory;
import javax.jms.Destination;
import javax.jms.JMSException;
import javax.jms.MessageConsumer;
import javax.jms.Session;
import javax.jms.TextMessage;

import org.apache.activemq.ActiveMQConnection;
import org.apache.activemq.ActiveMQConnectionFactory;

/**
 * 消息消費者一
 * 不斷從隊列出口獲取消息
 * @author zxy
 *
 */
public class JMSConsumer {

private static final String USERNAME = ActiveMQConnection.DEFAULT_USER;

    private static final String PASSWORD = ActiveMQConnection.DEFAULT_PASSWORD;

    private static final String BROKERURL = ActiveMQConnection.DEFAULT_BROKER_URL;

    public static void main(String[] args) {
        ConnectionFactory connectionFactory = null; //連接工廠
        Connection connection = null; //連接
        Session session = null; //會話接收或者發送消息的線程
        Destination destination = null; //消息的目的地
        MessageConsumer messageConsumer = null; //消息消費者

        //實例化連接工廠
        connectionFactory = new ActiveMQConnectionFactory(USERNAME, PASSWORD, BROKERURL);
        try {
            //通過連接工廠獲取連接
            connection = connectionFactory.createConnection();
            connection.start();
            session = connection.createSession(Boolean.FALSE, Session.AUTO_ACKNOWLEDGE);

            //創建消息隊列
            destination = session.createQueue("FirstQueue1");

            //創建消息生產者
            messageConsumer = session.createConsumer(destination);

            while(true){
                TextMessage message = (TextMessage)messageConsumer.receive(100000);
                if(message != null){
                    System.out.println("收到的消息:" + message.getText());
                }else{
                    break;
                }
            }

        } catch (JMSException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } finally {
            if(connection != null){
                try {
                    connection.close();
                } catch (JMSException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
        }
    }

}
import javax.jms.Connection;
import javax.jms.ConnectionFactory;
import javax.jms.Destination;
import javax.jms.JMSException;
import javax.jms.MessageConsumer;
import javax.jms.Session;

import org.apache.activemq.ActiveMQConnection;
import org.apache.activemq.ActiveMQConnectionFactory;

/**
 * 消息消費者二
 * 通過消息監聽獲取消息
 * @author Administrator
 *
 */
public class JMSConsumer2 {

    private static final String USERNAME = ActiveMQConnection.DEFAULT_USER;

    private static final String PASSWORD = ActiveMQConnection.DEFAULT_PASSWORD;

    private static final String BROKERURL = ActiveMQConnection.DEFAULT_BROKER_URL;

    public static void main(String[] args) {
        ConnectionFactory connectionFactory = null; //連接工廠
        Connection connection = null; //連接
        Session session = null; //會話接收或者發送消息的線程
        Destination destination = null; //消息的目的地
        MessageConsumer messageConsumer = null; //消息消費者

        // 實例化連接工廠
        connectionFactory=new ActiveMQConnectionFactory(USERNAME, PASSWORD, BROKERURL);

        try {
            //通過連接工廠獲取連接
            connection = connectionFactory.createConnection();
            connection.start();
            session = connection.createSession(Boolean.FALSE, Session.AUTO_ACKNOWLEDGE);

            //創建消息隊列
            destination = session.createQueue("FirstQueue1");

            // 創建消息消費者
            messageConsumer=session.createConsumer(destination); 

            // 註冊消息監聽
            messageConsumer.setMessageListener(new Listener()); 
        } catch (JMSException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } 
    }
}

消費方式一:
先開啓JMSProducer,再開啓JMSConsumer,消費結果如下:
這裏寫圖片描述

消費方式二:
將JMSConsumer2複製一份重命名爲JMSConsumer3,將兩個先開啓,監聽消息發佈,然後再開啓JMSProducer,消費結果如下:
JMSConsumer2:
這裏寫圖片描述
JMSConsumer3:
這裏寫圖片描述

瀏覽器控制檯Queues菜單項下可以找到如下結果,消息發佈數量與消息消費數量始終保持一致:
這裏寫圖片描述

(2)使用發佈/訂閱模式,可重複消費
創建消息發佈者JMSProducer,與上述消息發佈者其他代碼全部一致,將創建消息隊列的代碼改動即可

import javax.jms.Connection;
import javax.jms.ConnectionFactory;
import javax.jms.Destination;
import javax.jms.JMSException;
import javax.jms.MessageProducer;
import javax.jms.Session;
import javax.jms.TextMessage;

import org.apache.activemq.ActiveMQConnection;
import org.apache.activemq.ActiveMQConnectionFactory;

public class JMSProducer {

    private static final String USERNAME = ActiveMQConnection.DEFAULT_USER;

    private static final String PASSWORD = ActiveMQConnection.DEFAULT_PASSWORD;

    private static final String BROKERURL = ActiveMQConnection.DEFAULT_BROKER_URL;

    private static final int SENDNUM = 10;

    public static void main(String[] args) {
        ConnectionFactory connectionFactory = null; //連接工廠
        Connection connection = null; //連接
        Session session = null; //會話接收或者發送消息的線程
        Destination destination = null; //消息的目的地
        MessageProducer messageProducer = null; //消息生產者

        //實例化連接工廠
        connectionFactory = new ActiveMQConnectionFactory(USERNAME, PASSWORD, BROKERURL);

        try {
            //通過連接工廠獲取連接
            connection = connectionFactory.createConnection();
            connection.start();
            session = connection.createSession(Boolean.TRUE, Session.AUTO_ACKNOWLEDGE);

            //創建消息隊列
            destination = session.createTopic("FirstTopic1");
            //創建消息生產者
            messageProducer = session.createProducer(destination);

            //發送消息 
            sendMessage(session, messageProducer);

            session.commit();
        } catch (JMSException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } finally {
            if(connection != null){
                try {
                    connection.close();
                } catch (JMSException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
        }
    }

    public static void sendMessage(Session session, MessageProducer messageProducer){
        for(int i=0;i<SENDNUM;i++){
            try {
                TextMessage textMessage = session.createTextMessage("ActiveMQ 發送的消息" + i);
                System.out.println("發送消息:ActiveMQ發佈的消息" + i);
                messageProducer.send(textMessage);
            } catch (JMSException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    }

}

創建消息消費者JMSConsumer,與消息發佈者代碼改動一致:

import javax.jms.Connection;
import javax.jms.ConnectionFactory;
import javax.jms.Destination;
import javax.jms.JMSException;
import javax.jms.MessageConsumer;
import javax.jms.Session;

import org.apache.activemq.ActiveMQConnection;
import org.apache.activemq.ActiveMQConnectionFactory;

/**
 * 消息消費者
 * @author Administrator
 *
 */
public class JMSConsumer {

    private static final String USERNAME = ActiveMQConnection.DEFAULT_USER;

    private static final String PASSWORD = ActiveMQConnection.DEFAULT_PASSWORD;

    private static final String BROKERURL = ActiveMQConnection.DEFAULT_BROKER_URL;

    public static void main(String[] args) {
        ConnectionFactory connectionFactory = null; //連接工廠
        Connection connection = null; //連接
        Session session = null; //會話接收或者發送消息的線程
        Destination destination = null; //消息的目的地
        MessageConsumer messageConsumer = null; //消息消費者

        // 實例化連接工廠
        connectionFactory=new ActiveMQConnectionFactory(USERNAME, PASSWORD, BROKERURL);

        try {
            //通過連接工廠獲取連接
            connection = connectionFactory.createConnection();
            connection.start();
            session = connection.createSession(Boolean.FALSE, Session.AUTO_ACKNOWLEDGE);

            //創建消息隊列
            destination = session.createTopic("FirstTopic1");

            // 創建消息消費者
            messageConsumer=session.createConsumer(destination); 

            // 註冊消息監聽
            messageConsumer.setMessageListener(new Listener()); 
        } catch (JMSException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } 
    }
}

將JMSConsumer複製一份重命名爲JMSConsumer2,將兩個先開啓,監聽消息發佈,然後再開啓JMSProducer,消費結果如下:
兩者均爲一個結果:
這裏寫圖片描述
瀏覽器控制檯Topics菜單項下可以找到如下結果,消息發佈了10條,卻消費了20次,即兩個消費者重複消費了消息:
這裏寫圖片描述

總結:以上即爲所有過程,完成了ActiveMQ兩種模式小demo 的整合,如有不足,歡迎指正。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章