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