目錄
1. JMS(JAVA消息服務)
1.1. JMS(JAVA Message Service,java消息服務)API是一個消息服務的標準或者說是規範,允許應用程序組件基於JavaEE平臺創建、發送、接收和讀取消息。它使分佈式通信耦合度更低,消息服務更加可靠以及異步性。
1.2. 消息模型:點對點和發佈訂閱模型
1.3. 涉及到的概念 :
消息隊列(Queue)
發送者(Sender)
接收者(Receiver)
每個消息都被髮送到一個特定的隊列,接收者從隊列中獲取消息。隊列保留着消息,直到他們被消費或超時。
1.4. JMS編程模型(重點)
(1) ConnectionFactory
創建Connection對象的工廠,針對兩種不同的jms消息模型,分別有QueueConnectionFactory和TopicConnectionFactory兩種。可以通過JNDI來查找ConnectionFactory對象。
(2) Destination
Destination的意思是消息生產者的消息發送目標或者說消息消費者的消息來源。對於消息生產者來說,它的Destination是某個隊列(Queue)或某個主題(Topic);對於消息消費者來說,它的Destination也是某個隊列或主題(即消息來源)。
所以,Destination實際上就是兩種類型的對象:Queue、Topic可以通過JNDI來查找Destination。
(3) Connection
Connection表示在客戶端和JMS系統之間建立的鏈接(對TCP/IP socket的包裝)。Connection可以產生一個或多個Session。跟ConnectionFactory一樣,Connection也有兩種類型:QueueConnection和TopicConnection。
(4) Session
Session是我們操作消息的接口。可以通過session創建生產者、消費者、消息等。Session提供了事務的功能。當我們需要使用session發送/接收多個消息時,可以將這些發送/接收動作放到一個事務中。同樣,也分QueueSession和TopicSession。
(5) 消息的生產者
消息生產者由Session創建,並用於將消息發送到Destination。同樣,消息生產者分兩種類型:QueueSender和TopicPublisher。可以調用消息生產者的方法(send或publish方法)發送消息。
(6) 消息消費者
消息消費者由Session創建,用於接收被髮送到Destination的消息。兩種類型:QueueReceiver和TopicSubscriber。可分別通過session的createReceiver(Queue)或createSubscriber(Topic)來創建。當然,也可以session的creatDurableSubscriber方法來創建持久化的訂閱者。
(7) MessageListener
消息監聽器。如果註冊了消息監聽器,一旦消息到達,將自動調用監聽器的onMessage方法。EJB中的MDB(Message-Driven Bean)就是一種MessageListener。
2. Active MQ
2.1. ActiveMQ是一個易於使用的消息中間件。下載地址:http://activemq.apache.org/
2.2. ActiveMQ默認使用的TCP連接端口是61616, 通過查看該端口的信息可以測試ActiveMQ是否成功啓動 netstat -an|find “61616” 監控ActiveMQ的應用網址:http://127.0.0.1:8161
2.3. Active MQ簡單實例
2.3.1. 開發時候,要將apache-activemq-5.11.1-bin.zip解壓縮后里面的activemq-all-5.11.1.jar包加入到classpath下面,這個包包含了所有jms接口api的實現
2.3.2. 點對點消息模型示例
建立java項目,編寫生產者和消費者
生產者代碼:
package com.tgb.activemq;
import javax.jms.Connection;
import javax.jms.ConnectionFactory;
import javax.jms.Destination;
import javax.jms.JMSException;
import javax.jms.MessageProducer;
import javax.jms.Session;
import javax.jms.TextMessage;
import org.apache.activemq.ActiveMQConnection;
import org.apache.activemq.ActiveMQConnectionFactory;
/** * 消息的生產者(發送者)* */
public class JMSProducer {
//連接工廠
ConnectionFactory connectionFactory;
//連接
Connection connection = null;
//會話 接受或者發送消息的線程
Session session;
//消息的目的地
Destination destination;
//消息生產者
MessageProducer messageProducer;
//實例化連接工廠
connectionFactory = new ActiveMQConnectionFactory(JMSProducer.USERNAME, JMSProducer.PASSWORD, JMSProducer.BROKEURL);
try {
//通過連接工廠獲取連接
connection = connectionFactory.createConnection();
//啓動連接
connection.start();
//創建
session session = connection.createSession(true, Session.AUTO_ACKNOWLEDGE);
//創建一個名稱爲HelloWorld的消息隊列
destination = session.createQueue("HelloWorld");
//創建消息生產者
messageProducer = session.createProducer(destination);
//發送消息
sendMessage(session, messageProducer); session.commit();
} catch (Exception e) {
e.printStackTrace();
}finally{
if(connection != null){
try { connection.close();
} catch (JMSException e) {
e.printStackTrace();
}
}
}
}
/** * 發送消息 * @param session * @param messageProducer 消息生產者 * @throws Exception */
public static void sendMessage(Session session,MessageProducer messageProducer) throws Exception{
for (int i = 0; i < JMSProducer.SENDNUM; i++) {
//創建一條文本消息
TextMessage message = session.createTextMessage("ActiveMQ 發送消息" +i); System.out.println("發送消息:Activemq 發送消息" + i);
//通過消息生產者發出消息
messageProducer.send(message);
}
}
}
消費者代碼:
package com.tgb.activemq;
import javax.jms.Connection;
import javax.jms.ConnectionFactory;
import javax.jms.Destination;
import javax.jms.JMSException;
import javax.jms.MessageConsumer;
import javax.jms.Session;
import javax.jms.TextMessage;
import org.apache.activemq.ActiveMQConnection;
import org.apache.activemq.ActiveMQConnectionFactory;
/** * 消息的消費者(接受者) ** */
public class JMSConsumer {
private static final String USERNAME = ActiveMQConnection.DEFAULT_USER;
//默認連接用戶名
private static final String PASSWORD = ActiveMQConnection.DEFAULT_PASSWORD;
//默認連接密碼
private static final String BROKEURL = ActiveMQConnection.DEFAULT_BROKER_URL;
//默認連接地址
public static void main(String[] args) {
ConnectionFactory connectionFactory;//連接工廠
Connection connection = null;//連接
Session session;//會話 接受或者發送消息的線程
Destination destination;//消息的目的地
MessageConsumer messageConsumer;//消息的消費者
//實例化連接工廠
connectionFactory = new ActiveMQConnectionFactory(JMSConsumer.USERNAME, JMSConsumer.PASSWORD, JMSConsumer.BROKEURL);
try {
//通過連接工廠獲取連接
connection = connectionFactory.createConnection();
//啓動連接
connection.start();
//創建session
session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
//創建一個連接HelloWorld的消息隊列
destination = session.createQueue("HelloWorld");
//創建消息消費者
messageConsumer = session.createConsumer(destination);
while (true) {
TextMessage textMessage = (TextMessage)messageConsumer.receive(100000);
if(textMessage != null){
System.out.println("收到的消息:" + textMessage.getText());
}else {
break;
}
}
} catch (JMSException e) {
e.printStackTrace();
} } }
2.4. Active MQ和Spring整合
配置activeMQ.xml步驟:配置ConnectionFactory—>配置生產者—>配置消費者
配置ConnectionFactory:
<!-- ActiveMQ 連接工廠 -->
<!-- 真正可以產生Connection的ConnectionFactory,由對應的 JMS服務廠商提供-->
<!-- 如果連接網絡:tcp://ip:61616;未連接網絡:tcp://localhost:61616 以及用戶名,密碼--> <amq:connectionFactory id="amqConnectionFactory" brokerURL="tcp://192.168.3.3:61616" userName="admin" password="admin" />
<!-- Spring Caching連接工廠 -->
<!-- Spring用於管理真正的ConnectionFactory的ConnectionFactory -->
<bean id="connectionFactory" class="org.springframework.jms.connection.CachingConnectionFactory">
<!-- 目標ConnectionFactory對應真實的可以產生JMS Connection的ConnectionFactory --> <property name="targetConnectionFactory" ref="amqConnectionFactory"></property>
<!-- 同上,同理 -->
<!-- <constructor-arg ref="amqConnectionFactory" /> -->
<!-- Session緩存數量 -->
<property name="sessionCacheSize" value="100" />
</bean>
配置生產者(用Spring爲我們提供的JmsTemplate類來實現的,所以配置生產者其實最核心的就是配置消息發送的JmsTemplate):
<!-- Spring JmsTemplate 的消息生產者 start-->
<!-- 定義JmsTemplate的Queue類型 -->
<bean id="jmsQueueTemplate" class="org.springframework.jms.core.JmsTemplate">
<!-- 這個connectionFactory對應的是我們定義的Spring提供的那個ConnectionFactory對象 -->
<constructor-arg ref="connectionFactory" />
<!-- 非pub/sub模型(發佈/訂閱),即隊列模式 -->
<property name="pubSubDomain" value="false" />
</bean>
<!-- 定義JmsTemplate的Topic類型 -->0
<bean id="jmsTopicTemplate" class="org.springframework.jms.core.JmsTemplate">
<!-- 這個connectionFactory對應的是我們定義的Spring提供的那個ConnectionFactory對象 -->
<constructor-arg ref="connectionFactory" />
<!-- pub/sub模型(發佈/訂閱) -->
<property name="pubSubDomain" value="true" />
</bean>
<!--Spring JmsTemplate 的消息生產者 end-->
配置消費者(每個消費者對應每個目的地都需要有對應的MessageListenerContainer):
<!-- 定義Queue監聽器 -->
<jms:listener-container destination-type="queue" container-type="default" connection-factory="connectionFactory" acknowledge="auto">
<jms:listener destination="test.queue" ref="queueReceiver1"/>
<jms:listener destination="test.queue" ref="queueReceiver2"/>
</jms:listener-container>
<!-- 定義Topic監聽器 -->
<jms:listener-container destination-type="topic" container-type="default" connection-factory="connectionFactory" acknowledge="auto">
<jms:listener destination="test.topic" ref="topicReceiver1"/>
<jms:listener destination="test.topic" ref="topicReceiver2"/>
</jms:listener-container>
<!-- 消息消費者 end -->
3. 參考鏈接
http://blog.csdn.net/jiuqiyuliang/article/details/46701559