在使用原生的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()
需要傳入兩個參數,其作用:
- 是否使用事務:當消息發送者向消息提供者(即消息代理)發送消息時,消息發送者等待消息代理的確認,沒有迴應則拋出異常,消息發送程序負責處理這個錯誤。
- 消息的確認模式,其選項與其作用如下
- 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模式下,如果我們啓動多個消費者,然後再發送消息,這裏是如何接受的,如下我們啓動了兩個消費者進行消費
這裏我們發現每個消息只會被一個消費者消費,另外其多個消息的消費默認是通過輪詢消費者的方式去消費的。