使用原生ActiveMQ的API編程

在使用原生的ActiveMQ的API編程時,首先我們需要引入其相關的依賴,如下:

<dependency>
    <groupId>org.apache.activemq</groupId>
    <artifactId>activemq-all</artifactId>
    <version>5.15.7</version>
</dependency>

然後我們就來看一看ActiveMQ的消息生產者,代碼如下:

public class Producer {
    //默認連接用戶名
    public static final String USERNAME = ActiveMQConnection.DEFAULT_USER;
    //默認連接密碼
    public static final String PASSWORD = ActiveMQConnection.DEFAULT_PASSWORD;
    //默認連接地址
    public 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;     //消息目的地
        MessageProducer messageProducer;    //消息生產者

        //實例化連接工廠
        connectionFactory = new ActiveMQConnectionFactory(USERNAME, PASSWORD, BROKERURL);
        try {
            //通過連接工作獲取連接
            connection = connectionFactory.createConnection();
            //啓動連接
            connection.start();
            //創建會話,第一個參數表示是否使用事務,第二個參數表示消息的確認模式
            session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
            //創建一個名爲DemoActiveMQ消息隊列
            destination = session.createTopic("DemoActiveMQ");
            //創建消息生產者
            messageProducer = session.createProducer(destination);

            //發送消息
            for (int i = 0; i < 3; i++) {
                String msg = "發送第" + i + "條消息";
                TextMessage textMessage = session.createTextMessage(msg);
                messageProducer.send(textMessage);
            }
        } catch (JMSException e) {
            e.printStackTrace();
        } finally {
            if (connection != null) {
                try {
                    connection.close();
                } catch (JMSException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

其中在創建會話時,即connection.createSession()需要傳入兩個參數,其作用:

  1. 是否使用事務:當消息發送者向消息提供者(即消息代理)發送消息時,消息發送者等待消息代理的確認,沒有迴應則拋出異常,消息發送程序負責處理這個錯誤。
  2. 消息的確認模式,其選項與其作用如下
    • AUTO_ACKNOWLEDGE :指定消息接收者在每次收到消息時自動發送確認。消息只向目標發送一次,但傳輸過程中可能因爲錯誤而丟失消息。
    • CLIENT_ACKNOWLEDGE :由消息接收者確認收到消息,通過調用消息的acknowledge()方法(會通知消息提供者收到了消息)
    • DUPS_OK_ACKNOWLEDGE :指定消息提供者在消息接收者沒有確認發送時重新發送消息(這種確認模式不在乎接收者收到重複的消息)

另外其實我們傳入的默認連接用戶名密碼都是null,默認配置其實是無需賬號密碼的,連接地址前還有個failover的配置,表示可以不斷去嘗試重新連接的配置,這裏其實在Dubbo中也是存在類似
在這裏插入圖片描述


然後再來看看消息的消費者,其實和消息生產者的代碼大部分的是相同的,如下:

public class Consumer {

    //默認連接用戶名
    public static final String USERNAME = ActiveMQConnection.DEFAULT_USER;
    //默認連接密碼
    public static final String PASSWORD = ActiveMQConnection.DEFAULT_PASSWORD;
    //默認連接地址
    public 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;    //消息消費者

        //實例化連接工廠
        connectionFactory = new ActiveMQConnectionFactory(USERNAME, PASSWORD, BROKERURL);
        try {
            //通過連接工作獲取連接
            connection = connectionFactory.createConnection();
            //啓動連接
            connection.start();
            //創建會話,第一個參數表示是否使用事務,第二個參數表示消息的確認模式
            session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
            //創建一個名爲DemoActiveMQ消息隊列
            destination = session.createTopic("DemoActiveMQ");
            //創建消息消費者
            messageConsumer = session.createConsumer(destination);

            //同步接受消息
            Message message = null;
            while ((message = messageConsumer.receive()) != null){
                TextMessage textMessage = (TextMessage) message;
                System.out.println(textMessage.getText());
            }
        } catch (JMSException e) {
            e.printStackTrace();
        } finally {
            if(connection != null){
                try {
                    connection.close();
                } catch (JMSException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

然後我們就可以來啓動代碼,進行測試,首先我們先啓動消息生產者,然後再啓動消息消費者,這時我們發現這時消息消費者沒有接受到任何消息,因爲在topic主題下,發送者在發送了消息之後,如果沒有接收者正在運行,那麼該消息就會丟失,這裏我們在JMS和ActiveMQ安裝 中介紹JMS消息模型時也提到過


這裏我們就來通過ActiveMQ的控制檯來驗證一下,我們就會發現在控制檯中的確顯示在DemoActiveMQ中,消息入隊了3個,出隊了0個,消息的確發生了丟失
在這裏插入圖片描述

所以這時,我們需要先啓動消息消費者,在啓動消息生成者,結果如下:
在這裏插入圖片描述
在這裏插入圖片描述


另外在topic模式下,我們如果啓動多個消息消費者,然後再啓動消息生產者,這時每個消息消費者都會收到一份由生產者發出的消息,這裏感興趣的可以自行測試。



這時我們再來做一個事情,就是把本地啓動了ActiveMQ關閉,然後再打開,然後再來訪問控制檯,看看其DemoActiveMQ的數據,發現其記錄的Message Enqueued和Messages Dequeued數據全部丟失了,所以該topic模式下,其數據是存儲在內存的,重啓後就會丟失的
在這裏插入圖片描述




上述我們消息消費者採用的是同步消費,我們在JMS和ActiveMQ安裝 介紹時,提到過消息的消費可以採用以下同步或者異步消費來處理。
在這裏插入圖片描述


那麼使用異步消費來處理,我們應該如何進行修改呢?其實非常的簡單,消息的生產者肯定無需修改,我們只需修改消息消費者接受消息的處理即可,如下:
在這裏插入圖片描述

注意: 我們在消費端使用異步消費消息時,這時我們就需要把finally代碼塊中的代碼刪除,因爲不然的話連接會被我們的主線程所關閉。




最後我們再來看一看消息的 Point-to-Point(P2P) /點對點模式,即Queue模式,其實也是非常的簡單,只需要在消息的生產者和消費者參加消息隊列的時候,將createTopic()替換爲createQueue()方法即可
在這裏插入圖片描述
在這裏插入圖片描述

然後我們就可以進行測試了,因爲我們說過在點對點的Queue模式下,就算髮送消息時沒有消費者消費,消費也不會丟失的,我們先啓動消息的生產者
在這裏插入圖片描述

這時我們還未啓動消息的消費者,我們在ActiveMQ的管理控制檯中發現,在Queue模式下多了一個Number Of Pending Messages的數據,就是我們待處理的消息,這時就算我們把ActiveMQ服務關閉,然後再打開,其消息也不會丟失,這裏我們在打開消息的消費者,這時還可以收到消息的

在這裏插入圖片描述


最後我們再來在點對點的Queue模式下,如果我們啓動多個消費者,然後再發送消息,這裏是如何接受的,如下我們啓動了兩個消費者進行消費
在這裏插入圖片描述
在這裏插入圖片描述

這裏我們發現每個消息只會被一個消費者消費,另外其多個消息的消費默認是通過輪詢消費者的方式去消費的。

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