目錄
2.4 發佈/訂閱(publish/subscribe)(pub/sub)
一.基本的使用
1.消息隊列的發送
1.1 建立maven工程
如下圖,新建maven工程(新建maven工程之前需要確保eclipse集成maven,可百度eclipse安裝maven)
默認當前工作空間
點擊quickstart
設置3個必要參數,組ID,骨架ID,包名:
一個新的maven項目:
修改pom.xml,新增依賴
<dependency>
<groupId>org.apache.activemq</groupId>
<artifactId>activemq-all</artifactId>
<version>5.9.0</version>
</dependency>
<dependency>
<groupId>org.apache.xbean</groupId>
<artifactId>xbean-spring</artifactId>
<version>3.16</version>
</dependency>
1.2 書寫發送方代碼
在jmstest中新建queue包,文件結構可以自定義,這裏沒有什麼要求,就是普通的java代碼。
新建發送類:QueueSender.java
import javax.jms.Connection;
import javax.jms.Destination;
import javax.jms.JMSException;
import javax.jms.MessageProducer;
import javax.jms.Queue;
import javax.jms.Session;
import javax.jms.TextMessage;
import org.apache.activemq.ActiveMQConnectionFactory;
/**
* 實踐生產者消費者模式,消息隊列
* @author Administrator
*
*/
public class QueueSender {
public static void main(String[] args) throws JMSException {
//建立工廠
ActiveMQConnectionFactory activeMQConnectionFactory = new ActiveMQConnectionFactory("tcp://192.168.239.129:61616");
//工廠模式獲取連接
Connection connection = activeMQConnectionFactory.createConnection();
//連接
connection.start();
//通過連接獲取會話
Session session = connection.createSession(Boolean.TRUE, Session.AUTO_ACKNOWLEDGE);
//Destination destination= session.createQueue("Hello ActiveMQ");
//通過會話獲取隊列,設置隊列名
Queue createQueue = session.createQueue("Hello ActiveMQ");
//通過會話獲取生產者
MessageProducer producer = session.createProducer(createQueue);
//通過會話設置需要發送的文本
TextMessage textMessage = session.createTextMessage("anakki");
//通過生產者發送文本
producer.send(textMessage);
//提交本次會話
session.commit();
//會話關閉
session.close();
//連接關閉
connection.close();
}
}
1.3 生產者發送消息
右鍵類名運行:
查看結果:我們在實戰(一)中登錄的管理頁面查看,消息已經被隊列接受了。
2. 消息隊列的接收
2.1 書寫接收方代碼
(我們可以看出發送方和接收方是完全解耦合的,因爲此時我們接受方的代碼都還未寫。可是發送方已經可以發送消息了。注意這裏提到的消息隊列重要的特點,解耦合)
import javax.jms.Connection;
import javax.jms.JMSException;
import javax.jms.MessageConsumer;
import javax.jms.Queue;
import javax.jms.Session;
import javax.jms.TextMessage;
import org.apache.activemq.ActiveMQConnectionFactory;
/**
* 實踐生產者消費者模式,消息隊列
* @author Administrator
* 消費者
*/
public class QueueReceiver {
public static void main(String[] args) throws JMSException {
//建立工廠
ActiveMQConnectionFactory activeMQConnectionFactory = new ActiveMQConnectionFactory("tcp://192.168.239.129:61616");
//工廠模式獲取連接
Connection connection = activeMQConnectionFactory.createConnection();
//連接
connection.start();
//通過連接獲取會話
Session session = connection.createSession(Boolean.TRUE, Session.AUTO_ACKNOWLEDGE);
//Destination destination= session.createQueue("Hello ActiveMQ");
//通過會話獲取隊列,設置隊列名
Queue createQueue = session.createQueue("Hello ActiveMQ");
//通過會話獲取消費者
MessageConsumer consumer = session.createConsumer(createQueue);//A
//消費者接受信息
TextMessage message = (TextMessage)consumer.receive();//B
//提交本次會話
session.commit();
System.out.println(message.getText());//C
//會話關閉
session.close();
//連接關閉
connection.close();
}
}
運行後可以看見接收到的結果
管理頁面
由於我測試了多次 所以發送方一共發送了8條消息,所以入隊8次enqueued8次,消費者消費8次,dequeued8次,當然消費者如果只消費了6次,那麼上面將是8和6,接收和發送都是異步的。當我們隊列裏沒有消息時,如果我們去運行消費者。那麼消費者會一直等待隊列裏有消息,並消費掉它。這裏會被Number of Consumers記錄。這裏表示有一個消費者在等待接收並消費隊列中的消息。
當然也有限定等待時間的receive方法,可以看見下圖還有不阻塞的receive方法。
那我們可以得出消息隊列在目前有三種接收方式:
receive()有消息接收,沒消息阻塞
receive(long timeout)有消息接收,無消息阻塞timeout毫秒數,會返回一個null給TextMessage message
receiveNoWait()立即接收不等待,這個之後會介紹。
我們這裏已經走完了消息的發送和接收過程。
二.功能的介紹(預瞭解)
2.1 同步
receive方法顯式的阻塞的去接收隊列消息。同步,這裏可以去聯想ajax中把async設爲false的情況,就是此線程需要阻塞到得到消息才繼續運行。
2.2 異步
註冊消息監聽器。當有消息到達時,再接收消息。不會阻塞消費者。之後會實踐listener(監聽器)的代碼
2.3 點對點
每條消息只有一個消費者。
消費者取出消息後,消息就無效了。
消費者的運行和生產者的運行沒有時間上的要求。即使沒有生產者生產消息。當隊列中有消息時消費者也能在隊列中取到消息,反之亦然。
2.4 發佈/訂閱(publish/subscribe)(pub/sub)
在上面點對點的消息傳遞中,目的地爲隊列(queue),而發佈訂閱消息傳遞中,目的地稱爲主題(topic)
有時間相關性,消費者這能收到訂閱主題之後的消息。之前的消息,消費者無法接受到生產者所發佈的消息。
但是有一種情況,topic又分持久訂閱,和非持久訂閱。
當爲持久訂閱時:消費者離線後,生產者發佈的消息,消費者上線後也能收到。
以上加粗的關鍵字需要熟悉一下,在這裏讓我們忘掉activemq,很多其他消息隊列依舊有以上功能上的要求已經對應不同的實現。因此我們需要學習消息隊列的基本運行模型和JMS規範。下一節我們繼續瞭解一下JMS相關的知識內容。