之前在前面的文章已經有對activemq的簡單介紹以及安裝部署,今天打算把空閒時寫的幾個關於以activemq 爲mom(中間件)實現jms的案例拿出來寫寫,今天的這個例子是不使用spring進行封裝的,
jms提供的api中有兩種消息傳遞的方式,點到點(queue隊列)和pub\sub訂閱(topic主題)方式;在之前的文章已經仔細講過兩種方式的不同了。
首先在寫demo之前,我們都需要創建一個maven工程,在pom中引入我們所需要和依賴的jar包,這裏用的是activemq-core5.7.0的版本jar
<span style="white-space:pre"> </span><dependency>
<span style="white-space:pre"> </span><groupId>org.apache.activemq</groupId>
<span style="white-space:pre"> </span><artifactId>activemq-core</artifactId>
<span style="white-space:pre"> </span><version>5.7.0</version>
</dependency>
(1)對於點對點模式的開發流程:
點對點(queue隊列)模式,必須要有一個Producer (生產者) 和一個Customer(消費者);
所以首先我們要先創建一個生產者類,
QueueProducer.java
/**
* 點到點
* @author leo
* Producer開發流程
* 1.1 創建Connection: 根據url,user和password創建一個jms Connection。
1.2 創建Session: 在connection的基礎上創建一個session,同時設置是否支持事務和ACKNOWLEDGE標識。
1.3 創建Destination對象: 需指定其對應的主題(subject)名稱,producer和consumer將根據subject來發送/接收對應的消息。
1.4 創建MessageProducer: 根據Destination創建MessageProducer對象,同時設置其持久模式。
1.5 發送消息到隊列(Queue): 封裝TextMessage消息,使用MessageProducer的send方法將消息發送出去。
*
*
*/
public class QueueProducer {
//user
private static String user =ActiveMQConnection.DEFAULT_USER;
//password
private static String password =ActiveMQConnection.DEFAULT_PASSWORD;
//url
private static String url ="tcp://localhost:61616";
public static void main(String[] args) {
//創建連接工廠
ConnectionFactory connectionFactory =new ActiveMQConnectionFactory(user, password, url);
try {
//創建連接 connection :JMS 客戶端到JMS Provider 的連接
Connection connection =connectionFactory.createConnection();
//開啓連接
connection.start();
System.out.println("啓動連接");
//創建session 一個發送或接收消息的線程
Session session =connection.createSession(true,Session.AUTO_ACKNOWLEDGE);
//創建Queue : 需指定其對應的主題(subject)名稱,producer和consumer將根據subject來發送/接收對應的消息。
Queue destination =session.createQueue("activemq-queue-test1");
// MessageProducer:消息發送者
MessageProducer producer = session.createProducer(destination);
//在此處不做持久化
producer.setDeliveryMode(DeliveryMode.PERSISTENT);
//
sendMsg(session,producer);
//
session.commit();
//關閉連接
connection.close();
} catch (JMSException e) {
e.printStackTrace();
}
}
/**
* 發送消息
* @param session
* @param producer
* @throws JMSException
*/
private static void sendMsg(Session session, MessageProducer producer) throws JMSException {
TextMessage message =session.createTextMessage("activemq 點到點消息:");
System.out.println(message.getText());
producer.send(message);
}
}
然後再創建一個消費者類:
QueueCustomer.java
/**
* @author leo
* Customer
*2.1 實現MessageListener接口: 消費者類必須實現MessageListener接口,然後在onMessage()方法中監聽消息的到達並處理。
2.2 創建Connection: 根據url,user和password創建一個jms Connection,如果是durable模式,還需要給connection設置一個clientId。
2.3 創建Session和Destination: 與ProducerTool.java中的流程類似,不再贅述。
2.4 創建replyProducer【可選】:可以用來將消息處理結果發送給producer。
2.5 創建MessageConsumer: 根據Destination創建MessageConsumer對象。
2.6 消費message: 在onMessage()方法中接收producer發送過來的消息進行處理,並可以通過replyProducer反饋信息給producer
*
*/
public class QueueCustomer {
//user
private static String user =ActiveMQConnection.DEFAULT_USER;
//password
private static String password =ActiveMQConnection.DEFAULT_PASSWORD;
//url
private static String url ="tcp://localhost:61616";
public static void main(String[] args) {
//創建連接工廠
ConnectionFactory connectionFactory =new ActiveMQConnectionFactory(user, password, url);
try {
//創建連接 connection :JMS 客戶端到JMS Provider 的連接
Connection connection =connectionFactory.createConnection();
//開啓連接
connection.start();
System.out.println("啓動連接");
//創建session 一個發送或接收消息的線程
final Session session =connection.createSession(true,Session.AUTO_ACKNOWLEDGE);
//創建Queue : 需指定其對應的主題(subject)名稱,producer和consumer將根據subject來發送/接收對應的消息。
Queue destination =session.createQueue("activemq-queue-test1");
//創建MessageConsumer: 根據Destination創建MessageConsumer對象。 用來接收消息
MessageConsumer consumer = session.createConsumer(destination);
//消費者實現監聽接口,消費信息
consumer.setMessageListener(new MessageListener() {
@Override
public void onMessage(Message arg0) {
try {
TextMessage textMessage=(TextMessage)arg0;
System.out.println(textMessage.getText());
} catch (JMSException e1) {
e1.printStackTrace();
}
try {
session.commit();
} catch (JMSException e) {
e.printStackTrace();
}
}
});
} catch (JMSException e) {
e.printStackTrace();
}
}
}
然後我們編譯生產者類看看是否信息被髮送到mq Queue隊列中;但是需要注意的是:編譯之前要先啓動activeMQ 服務,並且登錄http://localhost:8161/admin/queues.jsp,進行驗證一下。
發現新的隊列已經創建,並且有一條消息在隊列中。然後我們編譯消費者,看消息是否能被消費者消費
發現消息被取走,然後看queues 中的隊列已經沒有消息了。這樣一個簡單的queue模式的jms已經完成。
(2)對於topic模式,之前在前面也說過該模式的開發流程,一個topic要有一個發佈者(publisher),但是可以有多個訂閱者(Subscriber);那首先我們來創建一個
publisher類:
/*
*
*
* @author leo
* Publisher(發佈者)
* 2.1 實現MessageListener接口:在onMessage()方法中接收訂閱者的反饋消息。
2.2 創建Connection: 根據url,user和password創建一個jms Connection。
2.3 創建Session: 在connection的基礎上創建一個session,同時設置是否支持事務和ACKNOWLEDGE標識。
2.4 創建Topic: 創建2個Topic,topictest.messages用於向訂閱者發佈消息,topictest.control用於接 收訂閱者反饋的消息。這2個topic與訂閱者開發流程中的topic是一一對應的。
2.5 創建consumer和producer對象: 根據topictest.messages創建publisher; 根據topictest.control 創建consumer,同時監聽訂閱者反饋的消息。
2.6 給所有訂閱者發送消息,並接收反饋消息: 示例代碼中,一共重複10輪操作。 每輪先向所有訂閱者 發送2000個消息; 然後堵塞線程,開始等待; 最後通過onMessage()方法,接收到訂閱者反饋的“REPORT”類信息後,才print反饋信息並解除線程堵塞,進入下一輪。
*
*/
public class TopicPublisher {
//user
private static String user =ActiveMQConnection.DEFAULT_USER;
//password
private static String password =ActiveMQConnection.DEFAULT_PASSWORD;
//url
private static String url ="tcp://localhost:61616";
public static void main(String[] args) {
//創建連接工廠
ConnectionFactory connectionFactory =new ActiveMQConnectionFactory(user, password, url);
try {
//創建連接 connection :JMS 客戶端到JMS Provider 的連接
Connection connection =connectionFactory.createConnection();
//開啓連接
connection.start();
System.out.println("啓動連接");
//創建session 一個發送或接收消息的線程
Session session =connection.createSession(true,Session.AUTO_ACKNOWLEDGE);
//創建tipic : 需指定其對應的主題(subject)名稱,producer和consumer將根據subject來發送/接收對應的消息。
Topic destination =session.createTopic("activemq-topic-test");
// MessageProducer:消息發送者
MessageProducer producer = session.createProducer(destination);
//在此處不做持久化
producer.setDeliveryMode(DeliveryMode.PERSISTENT);
//
sendMsg(session,producer);
//
session.commit();
//關閉連接
connection.close();
} catch (JMSException e) {
e.printStackTrace();
}
}
private static void sendMsg(Session session, MessageProducer producer) throws JMSException {
for (int i = 0; i < 50; i++) {
TextMessage message =session.createTextMessage("activemq topic(pub/sub)的 消息:"+i);
System.out.println(message.getText());
producer.send(message);
}
}
}
還有創建一個訂閱該消息的訂閱者topicSubscriber:
/**
*
* @author leo
*Subscriber (訂閱者開發流程)
*1.1 實現MessageListener接口: 在onMessage()方法中監聽發佈者發出的消息隊列,並做相應處理。
1.2 創建Connection: 根據url,user和password創建一個jms Connection。
1.3 創建Session: 在connection的基礎上創建一個session,同時設置是否支持事務和ACKNOWLEDGE標識。
1.4 創建Topic: 創建2個Topic, topictest.messages用於接收發布者發出的消息,topictest.control 用於向發佈者發送消息,實現雙方的交互。
1.5 創建consumer和producer對象:根據topictest.messages創建consumer,根據topictest.control創建 producer。
1.6 接收處理消息:在onMessage()方法中,對收到的消息進行處理,可直接簡單在本地顯示消息,或者根 據消息內容不同處理對應的業務邏輯(比如:數據庫更新、文件操作等等),並且可以使用producer對象將處理結果返回給發佈者。
*/
public class TopicSubscriber {
//user
private static String user =ActiveMQConnection.DEFAULT_USER;
//password
private static String password =ActiveMQConnection.DEFAULT_PASSWORD;
//url
private static String url ="tcp://localhost:61616";
/**
* @param args
*/
public static void main(String[] args) {
ConnectionFactory connectionFactory =new ActiveMQConnectionFactory(user, password, url);
try {
//創建連接 connection :JMS 客戶端到JMS Provider 的連接
Connection connection =connectionFactory.createConnection();
//開啓連接
connection.start();
System.out.println("啓動連接");
//創建session 一個發送或接收消息的線程
final Session session =connection.createSession(true,Session.AUTO_ACKNOWLEDGE);
//創建Queue : 需指定其對應的主題(subject)名稱,producer和consumer將根據subject來發送/接收對應的消息。
Topic destination =session.createTopic("activemq-topic-test");
//創建MessageConsumer: 根據Destination創建MessageConsumer對象。 用來接收消息
MessageConsumer consumer = session.createConsumer(destination);
//實現監聽接口,消費信息
consumer.setMessageListener(new MessageListener() {
@Override
public void onMessage(Message arg0) {
try {
TextMessage message =(TextMessage) arg0;
System.out.println(message.getText());
session.commit();
} catch (JMSException e) {
e.printStackTrace();
}
}
});
} catch (JMSException e) {
e.printStackTrace();
}
}
}
和queue一樣,我們先啓動發佈者,會發現在mq管理員界面中的topic板塊中會有一個新的主題以及消息,然後再啓動訂閱者,會發現訂閱者沒有收到之前發佈者發佈的那些消息。所以Queue(點對點)方式和Topic(發佈/訂閱)方式 的運行結果有了區別是:在Queue(點對點)方式中先運行生產者,再運行消費者,消費者還能接受到消息;
而Topic(發佈/訂閱)方式就不同了,先運行發佈者,再運行訂閱者,訂閱者收到的消息可能沒有或者是不完全的。所以我們要先運行訂閱者,然後再去編譯發佈者。