Java中使用AMQ的簡單實例

好了,接上一篇,在對JMS的概念以及AMQ的下載安裝有了一定認識之後,本篇就來學習一下AMQ在Java中的Hello World級使用(下文我將着重把重點寫在註釋裏面,請注意代碼註釋部分!!!)。

  1. 開發環境

AMQ 5.14.5 服務啓動運行
準備Java Maven項目

依賴jar包在apache-activemq-5.14.5根目錄下即可找到,或者直接Maven依賴:

org.apache.activemq
activemq-all
5.14.5

1
2
3
4
5
2. 點對點模型

2.1 隊列消息發送者

編寫 QueueProducer.java 如下:

package com.jastar.activemq.queue;

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

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

/**
* 隊列消息-發送(生產)者
*


* ClassName: QueueProducer
*



* Copyright: (c)2017 JASTAR·WANG,All rights reserved.
*






/** 默認用戶名 */
public static final String USERNAME = ActiveMQConnection.DEFAULT_USER;
/** 默認密碼 */
public static final String PASSWORD = ActiveMQConnection.DEFAULT_PASSWORD;
/** 默認連接地址(格式如:tcp://IP:61616) */
public static final String BROKER_URL = ActiveMQConnection.DEFAULT_BROKER_URL;
/** 隊列名稱 */
public static final String QUEUE_NAME = "hello amq";

// 連接工廠(在AMQ中由ActiveMQConnectionFactory實現)
private ConnectionFactory connectionFactory;

// 連接對象
private Connection connection;

// 會話對象
private Session session;

// 消息目的地(對於點對點模型,是Queue對象;對於發佈訂閱模型,是Topic對象;它們都繼承或實現了該接口)
private Destination destination;

// 消息發送(生產)者
private MessageProducer messageProducer;

public static void main(String[] args) {
    QueueProducer producer = new QueueProducer();
    producer.doSend();
}

public void doSend() {
    try {
        /**
         * 1.創建連接工廠<br>
         * 構造函數有多個重載,默認連接本地MQ服務器,也可以手動設置用戶名、密碼、連接地址信息<br>
         * new ActiveMQConnectionFactory(userName, password, brokerURL)
         */
        connectionFactory = new ActiveMQConnectionFactory();

        /**
         * 2.創建連接
         */
        connection = connectionFactory.createConnection();

        /**
         * 3.啓動連接
         */
        connection.start();

        /**
         * 4.創建會話<br>
         * param1:是否支持事務,若爲true,則會忽略第二個參數,默認爲SESSION_TRANSACTED<br>
         * param2:確認消息模式,若第一個參數爲false時,該參數有以下幾種狀態<br>
         * -Session.AUTO_ACKNOWLEDGE:自動確認。客戶端發送和接收消息不需要做額外的工作,即使接收端發生異常,
         * 也會被當作正常發送成功 <br>
         * -Session.CLIENT_ACKNOWLEDGE:客戶端確認。客戶端接收到消息後,必須調用message.
         * acknowledge() 方法給予收到反饋,JMS服務器纔會把該消息當做發送成功,並刪除<br>
         * -Session.DUPS_OK_ACKNOWLEDGE:副本確認。一旦接收端應用程序的方法調用從處理消息處返回,
         * 會話對象就會確認消息的接收,而且允許重複確認。
         */
        session = connection.createSession(true, Session.AUTO_ACKNOWLEDGE);

        /**
         * 5.創建(發送)消息目的地,即隊列,參數爲隊列名稱
         */
        destination = session.createQueue(QUEUE_NAME);

        /**
         * 6.創建一個消息生產者,並指定目的地
         */
        messageProducer = session.createProducer(destination);
        /**
         * 其他操作: 設置生產者的生產模式,默認爲持久化<br>
         * 參數有以下兩種狀態:<br>
         * -DeliveryMode.NON_PERSISTENT:消息不持久化,消息被消費之後或者超時之後將從隊列中刪除
         * -DeliveryMode.PERSISTENT:消息會持久化,即使接收端消費消息之後仍然會保存
         */
        messageProducer.setDeliveryMode(DeliveryMode.NON_PERSISTENT);

        /**
         * 其他操作:設置消息的存活時間(單位:毫秒)
         */
        messageProducer.setTimeToLive(60000);

        for (int i = 0; i < 5; i++) {
            /**
             * 7.創建文本消息<br>
             * 此外,還有多種類型的消息如對象,字節……都可以通過session.createXXXMessage()方法創建
             */
            TextMessage message = session.createTextMessage("send content:"
                    + i);

            /**
             * 8. 發送
             */
            messageProducer.send(message);

        }
        System.out.println("消息發送完成!");
        /**
         * 如果有事務操作也可以提交事務
         */
        session.commit();

        /**
         * 9.關閉生產者對象(即使關閉了程序也在運行)
         */
        messageProducer.close();
    } catch (Exception e) {
        e.printStackTrace();
    } finally {
        if (connection != null) {
            try {
                /**
                 * 10.關閉連接(將會關閉程序)
                 */
                connection.close();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

}

}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
2.2 隊列消息接收者

編寫 QueueConsumer.java 其他同上,注意註釋部分:

package com.jastar.activemq.queue;

import javax.jms.Connection;
import javax.jms.ConnectionFactory;
import javax.jms.Destination;
import javax.jms.Message;
import javax.jms.MessageConsumer;
import javax.jms.MessageListener;
import javax.jms.Session;
import javax.jms.TextMessage;

import org.apache.activemq.ActiveMQConnectionFactory;

/**
* 隊列消息-接收(消費)者
*


* ClassName: QueueConsumer
*



* Copyright: (c)2017 JASTAR·WANG,All rights reserved.
*






private ConnectionFactory connectionFactory;
private Connection connection;
private Session session;
private Destination destination;
// 注意這裏是消息接收(消費)者
private MessageConsumer messageConsumer;

public static void main(String[] args) {
    QueueConsumer consumer = new QueueConsumer();
    consumer.doReceive();
}

public void doReceive() {
    try {
        connectionFactory = new ActiveMQConnectionFactory();
        connection = connectionFactory.createConnection();
        connection.start();
        session = connection.createSession(true, Session.AUTO_ACKNOWLEDGE);
        destination = session.createQueue(QueueProducer.QUEUE_NAME);

        /**
         * 注意:這裏要創建一個消息消費,並指定目的地(即消息源隊列)
         */
        messageConsumer = session.createConsumer(destination);

        // 方式一:監聽接收
        receiveByListener();

        // 方式二:阻塞接收
        // receiveByManual();

        /**
         * 注意:這裏不能再關閉對象了
         */
        // messageConsumer.close();
    } catch (Exception e) {
        e.printStackTrace();
    } finally {
        /**
         * 注意:這裏不能再關閉Connection了
         */
        // connection.close();
    }

}

/**
 * 通過註冊監聽器的方式接收消息,屬於被動監聽
 */
private void receiveByListener() {
    try {
        messageConsumer.setMessageListener(new MessageListener() {

            @Override
            public void onMessage(Message message) {
                if (message instanceof TextMessage) {
                    try {
                        TextMessage msg = (TextMessage) message;
                        System.out.println("Received:“" + msg.getText()
                                + "”");
                        // 可以通過此方法反饋消息已收到
                        msg.acknowledge();
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }

            }
        });
    } catch (Exception e) {
        e.printStackTrace();
    }
}

/**
 * 通過手動去接收消息的方式,屬於主動獲取
 */
private void receiveByManual() {
    while (true) {
        try {
            /**
             * 通過receive()方法阻塞接收消息,參數爲超時時間(單位:毫秒)
             */
            TextMessage message = (TextMessage) messageConsumer
                    .receive(60000);
            if (message != null) {
                System.out.println("Received:“" + message.getText() + "”");
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

    }
}

}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
3. 發佈訂閱模型

3.1 主題消息發送者

和點對點模型的發送者唯一不同的是——創建目的地Destination的時候是通過 session.createTopic(); 來創建,其他的使用套路如同 QueueProducer.java ,在此不再貼代碼,最後我會留下示例代碼地址,需要的可以去down下看看。

3.2 主題消息接收者

編寫 TopicConsumer.java ,如下:

package com.jastar.activemq.topic;

import javax.jms.Connection;
import javax.jms.ConnectionFactory;
import javax.jms.Destination;
import javax.jms.Message;
import javax.jms.MessageConsumer;
import javax.jms.MessageListener;
import javax.jms.Session;
import javax.jms.TextMessage;

import org.apache.activemq.ActiveMQConnectionFactory;

/**
* 主題消息-接收(消費)者
*


* ClassName: TopicConsumer
*



* Copyright: (c)2017 JASTAR·WANG,All rights reserved.
*











public static void main(String[] args) {
    /**
     * Pub/Sub模型中,消息可被多個對象接收,不同於P2P模型
     */
    TopicConsumer consumer1 = new TopicConsumer();
    consumer1.doReceive();
    TopicConsumer consumer2 = new TopicConsumer();
    consumer2.doReceive();
}

public void doReceive() {
    try {
        connectionFactory = new ActiveMQConnectionFactory();
        connection = connectionFactory.createConnection();
        connection.start();
        session = connection.createSession(true, Session.AUTO_ACKNOWLEDGE);
        destination = session.createTopic(TopicProducer.TOPIC_NAME);
        messageConsumer = session.createConsumer(destination);

        // 方式一:監聽接收
        receiveByListener();

        // 方式二:阻塞接收
        // receiveByManual();

    } catch (Exception e) {
        e.printStackTrace();
    }

}

/**
 * 通過註冊監聽器的方式接收消息,屬於被動監聽
 */
private void receiveByListener() {
    try {
        messageConsumer.setMessageListener(new MessageListener() {

            @Override
            public void onMessage(Message message) {
                if (message instanceof TextMessage) {
                    try {
                        TextMessage msg = (TextMessage) message;
                        System.out.println("Received:“" + msg.getText()
                                + "”");
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }

            }
        });
    } catch (Exception e) {
        e.printStackTrace();
    }
}

/**
 * 通過手動去接收消息的方式,屬於主動獲取
 */
private void receiveByManual() {
    while (true) {
        try {
            /**
             * 通過receive()方法阻塞接收消息,參數爲超時時間(單位:毫秒)
             */
            TextMessage message = (TextMessage) messageConsumer
                    .receive(60000);
            if (message != null) {
                System.out.println("Received:“" + message.getText() + "”");
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

    }
}

}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
4.最後說幾句

以上代碼全部經過我的測試,絕對保證可靠運行
瀏覽器訪問ActiveMQ的Web控制檯(http://localhost:8161/admin),即可看到消息、隊列、主題等等信息,在此不再上圖了,懶死了真是……
示例代碼項目地址:https://gitee.com/jastar-wang/demo-amq

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