activemq訂閱模式--java教程

activemq有訂閱模式,該模式是直接羣發,消息不保存。

生產者:

先寫個生成者的demo

package org.example.activemqtest;


import org.apache.activemq.ActiveMQConnectionFactory;
import javax.jms.*;
import java.util.Scanner;

public class Provider {
    public static String username = "admin";
    public static String password = "admin";
    public static String url ="tcp://localhost:61616";//採用openwire

    public static String name="test_topic_1";

    private ConnectionFactory connectionFactory;

    private Connection connection;

    private Session session;
    {

        try {
            /**
             * 1.創建連接工廠
             * 創建工廠,構造方法有三個參數:分別是用戶名、密碼、連接地址
             * 無參構造:有默認的連接地址,localhost
             * 一個參數:無驗證模式,無用戶的認證
             * 三個參數:有認證和連接地址
             */
            connectionFactory = new ActiveMQConnectionFactory(username,password,url);
            connection = connectionFactory.createConnection();
            /**
             * 3.啓動連接
             * 生產者可以不啓動,因爲在發送消息的時候回進行檢查
             * 如果未啓動連接,會自動啓動
             * 如果有特殊配置,需要配置完成後再啓動連接
             */
            connection.start();
            /**
             * 4.用連接創建會話
             * 有兩個參數:是否需要事務、消息確認機制
             * 如果支持事務,對於生產者來說第二個參數就無效了,建議傳入Session.SESSION_TRANSACTED
             * 如果不支持事務,第二個參數必須傳遞且有效
             *
             * AUTO_ACKNOWLEDGE:自動確認,消息處理後自動確認(商業開發不推薦)
             * CLIENT_ACKNOWLEDGE:客戶端手動確認,消費者處理後必須手動確認
             * DUPS_OK_ACKNOWLEDGE:有副本的客戶端手動確認,消息可以多次處理(不建議)
             */
            session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
            System.out.println("clientID = " + connection.getClientID());
        } catch (JMSException e) {
            e.printStackTrace();
        }
    }
    private void send(String text) throws JMSException {
        Destination queue = session.createTopic(name);
        MessageProducer producer = session.createProducer(queue);
        producer.send(session.createTextMessage(text));

    }

    public static void main(String[] args) throws Exception {
       Provider provider = new Provider();


        Scanner scan = new Scanner(System.in);

        // 判斷是否還有輸入
        while (scan.hasNextLine()) {
            String str2 = scan.nextLine();
            System.out.println("發送的數據爲:" + str2);
            provider.send(str2);
        }
        scan.close();
    }
}

可以看到,代碼實際上就是new Provicder().send(text)

普通代碼塊裏創建了連接,send方法往test_topic_1裏發送數據.然後發送者就結束了,就不再管了.

至於Scanner是爲了屏幕輸入然後發送

我們啓動這個main方法,發送一條數據

1111
發送的數據爲:1111

然後觀察active後臺控制檯裏:

 可以發現test_topic_1這個隊列裏已經有了一條數據。

 

消費者:

package org.example.activemqtest;

import org.apache.activemq.ActiveMQConnectionFactory;

import javax.jms.*;
import java.time.LocalDateTime;

public class Receiver {
    public static final String username ="admin";
    private static final String password ="admin";

    public static final String url ="tcp://localhost:61616";
    public static String name="test_topic_1";
    Connection connection;
    Session session;

    {

        try {
            /**
             * 1.創建連接工廠
             * 創建工廠,構造方法有三個參數:分別是用戶名、密碼、連接地址
             * 無參構造:有默認的連接地址,localhost
             * 一個參數:無驗證模式,無用戶的認證
             * 三個參數:有認證和連接地址
             */
            ConnectionFactory factory = new ActiveMQConnectionFactory(username,password,url);
            connection = factory.createConnection();
            /**
             * 3.啓動連接
             * 生產者可以不啓動,因爲在發送消息的時候回進行檢查
             * 如果未啓動連接,會自動啓動
             * 如果有特殊配置,需要配置完成後再啓動連接
             */
            connection.start();
            /**
             * 4.用連接創建會話
             * 有兩個參數:是否需要事務、消息確認機制
             * 如果支持事務,對於生產者來說第二個參數就無效了,建議傳入Session.SESSION_TRANSACTED
             * 如果不支持事務,第二個參數必須傳遞且有效
             *
             * AUTO_ACKNOWLEDGE:自動確認,消息處理後自動確認(商業開發不推薦)
             * CLIENT_ACKNOWLEDGE:客戶端手動確認,消費者處理後必須手動確認
             * DUPS_OK_ACKNOWLEDGE:有副本的客戶端手動確認,消息可以多次處理(不建議)
             */
            session = connection.createSession(false,Session.AUTO_ACKNOWLEDGE);
        } catch (JMSException e) {
            e.printStackTrace();
        }
    }

    public void receive() throws JMSException {
        Destination queue = session.createTopic(name);

        MessageConsumer consumer = session.createConsumer(queue);
        consumer.setMessageListener(new MessageListener() {
            @Override
            public void onMessage(Message message) {
                try{
                    TextMessage m = (TextMessage)message;
                    String text = m.getText();
                    System.out.println(LocalDateTime.now() +" : " +text);
                }catch (Exception e){
                    e.printStackTrace();
                }
            }
        });

    }

    public static void main(String[] args) throws JMSException {
        new Receiver().receive();
    }

}

可以看到,在連接到消息中間件後,客戶端就加了一個而監聽器而已,監聽器裏打印了發來的數據

然後我們運行,發現沒有打印任何數據,沒有獲得剛剛發的1111,因爲訂閱模式消息不保存,直接拋棄了。如果當時沒有訂閱就接不到。

我們再看到控制檯:

發現多了一個接收者,但是消息訂閱數還是0,並沒有增加。

 

進一步測試

我們再發一條222消息進行測試,發現消費者接到了消息。控制檯如下:

發現生產的消息多了一條,消費總數也多了一條。

由於訂閱模式特徵就是羣發,那麼再啓動一個消費者,然後再發一條333,發現兩個消費者都接到了。控制檯如下:

 

發現消費者多了一個,消息多了一個,但是消費總數居然多了兩個,原因在於消費總數就是消費總數,剛剛兩個消費者消費了所以+2,如果是3個消費者,那麼要加3

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