java系統之間的消息通訊使用最多的是基於RMI的RPC和基於JMS的RPC,這兩種的消息傳輸方式雖然都能夠起到通訊的作用,但是在筆者看來,二者之間的差別還是非常大的。首先RMI是同步傳輸,而JMS是異步傳輸,另外二者的使用場景也是大不相同。在系統集成平臺這個項目中讓我能夠有機會更加深入的認識這兩種消息通訊機制。基礎系統與考試系統之間的數據傳輸我們採用的是將ejb發佈成webservice,然後再通過esb將客戶端和webservice進行連接,這種方式在本質上是ejb之間的相互調用,屬於RMI方式的消息通訊,最明顯的特點是當我們執行遠程調用之後不得不等到webservice將數據全部傳輸完畢之後才能進行相關操作(當然根據業務,也必須選擇這種方式,因爲我們接下來的所有操作都是基於返回數據的),而JMS則是通過第三方的broker提供消息服務,這個broker相當於一個郵局,客戶端發送消息只管將消息內容送到broker並告知broker投送地址,剩下的事情就有broker進行了,客戶端完全不必等待,可以進行其他任何操作,而broker所擔負的主要職責就是確保消息投送,我們的消息接收這則只管監聽broker就可以了。經過對比相信大家已經對這兩種方式有了初步的認識,接下來我們重點講解一下基於JMS的消息中間件---ActiveMQ。
1.首先我們要搭建ActiveMQ服務器,這個服務器就相當於我們前面提到broker,搭建的過程很簡單,可上官網查詢,這裏不再多說。
2.創建queue隊列,然後創建發送端測試代碼,代碼如下:
public static void main(String[] args) {
// ConnectionFactory :連接工廠,JMS 用它創建連接
ConnectionFactory connectionFactory;
// Connection :JMS 客戶端到JMS Provider 的連接
Connection connection = null;
// Session: 一個發送或接收消息的線程
Session session;
// Destination :消息的目的地;消息發送給誰.
Destination destination;
// MessageProducer:消息發送者
MessageProducer producer;
// TextMessage message;
// 構造ConnectionFactory實例對象,此處採用ActiveMq的實現jar
connectionFactory = new ActiveMQConnectionFactory(
ActiveMQConnection.DEFAULT_USER,
ActiveMQConnection.DEFAULT_PASSWORD,
"tcp://localhost:61616");
try {
// 構造從工廠得到連接對象
connection = connectionFactory.createConnection();
// 啓動
connection.start();
// 獲取操作連接
session = connection.createSession(Boolean.TRUE,
Session.AUTO_ACKNOWLEDGE);
// 獲取session注意參數值xingbo.xu-queue是一個服務器的queue,須在在ActiveMq的console配置
//destination = session.createQueue("FirstQueue");
//destination = session.createTopic("SecondTopic");
destination = session.createQueue("myqueue");
// 得到消息生成者【發送者】
producer = session.createProducer(destination);
// 設置不持久化,此處學習,實際根據項目決定
producer.setDeliveryMode(DeliveryMode.NON_PERSISTENT);
// 構造消息,此處寫死,項目就是參數,或者方法獲取
sendMessage(session, producer);
session.commit();
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if (null != connection)
connection.close();
} catch (Throwable ignore) {
}
}
}
public static void sendMessage(Session session, MessageProducer producer)
throws Exception {
TextMessage message = session
.createTextMessage("hello changshou");
// 發送消息到目的地方
System.out.println("發送消息:" +message.getText());
producer.send(message);
}
執行該方法,發送端輸出結果如下:
3.創建接收端測試代碼,如下:
package com.xuwei.activemq;
import javax.jms.Connection;
import javax.jms.ConnectionFactory;
import javax.jms.Destination;
import javax.jms.MessageConsumer;
import javax.jms.Session;
import javax.jms.TextMessage;
import org.apache.activemq.ActiveMQConnection;
import org.apache.activemq.ActiveMQConnectionFactory;
public class Receiver {
public static void main(String[] args) {
// ConnectionFactory :連接工廠,JMS 用它創建連接
ConnectionFactory connectionFactory;
// Connection :JMS 客戶端到JMS Provider 的連接
Connection connection = null;
// Session: 一個發送或接收消息的線程
Session session;
// Destination :消息的目的地;消息發送給誰.
Destination destination;
// 消費者,消息接收者
MessageConsumer consumer;
connectionFactory = new ActiveMQConnectionFactory(
ActiveMQConnection.DEFAULT_USER,
ActiveMQConnection.DEFAULT_PASSWORD,
"tcp://localhost:61616");
try {
// 構造從工廠得到連接對象
connection = connectionFactory.createConnection();
// 啓動
connection.start();
// 獲取操作連接
session = connection.createSession(Boolean.FALSE,
Session.AUTO_ACKNOWLEDGE);
// 獲取session注意參數值xingbo.xu-queue是一個服務器的queue,須在在ActiveMq的console配置
//destination = session.createQueue("FirstQueue");
//destination = session.createTopic("SecondTopic");
destination = session.createQueue("myqueue");
consumer = session.createConsumer(destination);
while (true) {
//設置接收者接收消息的時間,爲了便於測試,這裏誰定爲100s
TextMessage message = (TextMessage) consumer.receive(100000);
if (null != message) {
System.out.println("收到消息" + message.getText());
} else {
break;
}
}
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if (null != connection)
connection.close();
} catch (Throwable ignore) {
}
}
}
}
接收端輸出結果如下:
結果顯示執行發送消息和接收消息是沒有問題的,但是在這裏我們應該很明確消息隊列和消息主題的區別,當我們創建了一個消息隊列,將消息發送到消息隊列中,這時針對這個消息的接收者很可能是多個,當這個消息被其中的任何一個接收這接收的到的時候這個消息就被消費掉了,其他人將不會再接到此消息,而當我們創建一個主題的時候,同樣是將這個消息發送到這個主題中,所有的接收者都會接收到這個消息,並根據消息做出自己的相應處理,原理上很類似於qq的單人間消息傳輸和討論組,這兩個區別的驗證代碼也十分的簡單,只要發送者創建一個隊列,然後建立兩個接收者,分別執行發送者的發送方法和接收者的接收方法,如果只有一個接收者能夠接收到消息則驗證成功,主題的驗證也是相同的道理,發送者創建一個主題,然後再創建兩個接收這者,仍然執行各自的方法,如果此時兩個接收者都能接收到消息則說明主題的驗證也成功,有興趣的同學可以親自實驗一下。