JMS

Java Message Service是java ee的規範之一,可以用來發送異步消息,在某些場景下,可以作爲不同系統,或者不同模塊之間的集成方式。 

可以類比爲通過數據庫來集成的方式,模塊A完成邏輯以後,往數據庫插入一條記錄,模塊B定時輪詢數據庫,如果查到相應的記錄,就進行處理。jms集成實際上思路是差不多的,只是功能更強,並且提供了標準的API支持,而且也可以避免反覆輪詢數據庫或者讀取文件的I/O操作,對系統的整體性能可能會有提升 

其主要優點,首先是可以使2個系統或模塊實現鬆耦合,模塊A不需要直接調用模塊B,只需要往jms provider上發送一條約定格式的消息,模塊B收到這條消息,進行後續的業務處理 

其次,jms方式是異步的,意味着模塊A發送消息之後,不需要等待模塊B或者jms provider的響應,自身的業務邏輯可以繼續 

jms技術對應的規範是jsr914,規範的實現稱爲jms provider,常見的實現有ActiveMQ、JBoss MQ、IBM Websphere MQ等。本文以ActiveMQ舉例 

一、ActiveMQ使用 

ActiveMQ(其他的jms provider也差不多)安裝之後,目錄結構是這樣的: 

 

運行bin目錄下的activemq.bat,會根據默認配置,啓動一個broker。各種jms實現,好像都有broker的概念 

啓動之後,會佔用至少2個端口,默認的是61616和8161 

61616是等待jms client的連接,8161是ActiveMQ自帶的一個web應用 

http://localhost:8161/demo,可以看到各種官方提供的例子 

http://localhost:8161/admin,是ActiveMQ的管理控制檯 



這裏可以對隊列進行各種操作,比如發送消息,查看消息,清空隊列等等 

ActiveMQ即使在不編程的情況下,也可以通過這種方式來使用,包括我之前的公司,是用Websphere MQ,有時也不編程,直接通過Websphere MQ,在兩地進行消息傳輸。當然,大部分情況,還是需要針對jms client進行編程的 

二、jms基本概念 

前面說過,jms的實現,稱爲jms provider,可以認爲是jms的服務器 

jms的客戶端,需要開發人員自行開發,稱爲jms client 

jms的消息機制有2種模型,一種是Point to Point,表現爲隊列的形式。發送的消息,只能被一個接收者取走 

另一種是Topic,可以被多個訂閱者訂閱,類似於羣發 



ConnectionFactory,用於jms client獲取與jms provider的連接。不同的jms產品,對這個接口有不同的實現,比如說ActiveMQ,這個接口的實現類是ActiveMQConnectionFactory 

Connection,是由ConnectionFactory產生的,表示jms client與jms provider的連接 

Session,是由Connection產生的,表示一個會話。Session是關鍵組件,Message、Producer/Consumer、Destination都是在Session上創建的 

Message,這個組件很好理解,就是傳輸的消息,裏面包括head、properties、body,其中head是必選的 

Destination,是消息源,對發送者來說,就是消息發到哪裏;對接收者來說,就是從哪裏取消息。Destination有2個子接口,Queue和Topic,分別對應上面提到的2種模型 

Message Producer,是消息發送者,創建這個組件的代碼類似: 
Java代碼  收藏代碼
  1. Destination dest = session.createQueue("dotaQueue");// 消息目的地  
  2.   
  3.         MessageProducer producer = session.createProducer(dest);// 消息發送者  

可以注意到,這裏需要把Destination作爲參數,傳入createProducer()方法,這說明消息發送者是綁定到Destination上的,這個發送者發送的消息,會發送到這個綁定的Destination上 

Message Consumer,是消息接收者,和Message Producer是相反的一種組件 

三、代碼實例 

這裏是基於ActiveMQ進行開發,所以需要導入ActiveMQ提供的jar包。不過開發時,應該儘量針對jms接口進行開發,不依賴特定的實現 

例子是用main函數跑的,沒有在java ee容器裏跑,所以沒有辦法依賴JNDI拿到ConnectionFactory的實例,只能手工創建ActiveMQConnectionFactory,所以和ActiveMQ的實現耦合了,沒有辦法連到別的jms實現上。如果實際的代碼,用JNDI或者spring來獲取ConnectionFactory的實例的話,那就可以僅針對接口編程,連接到任意jms provider了 

爲了簡單起見,例子也沒有用到spring,實際上spring對jms client提供了很好的支持,在後面再介紹 

開發環境只要導入activemq-all-5.6.0.jar就可以了 

 

裏面已經包括了jms API、activemq-core、javaee-management API等必須的class 

首先是Message Producer的例子: 
Java代碼  收藏代碼
  1. public class Main {  
  2.   
  3.     public static void main(String[] args) throws JMSException {  
  4.   
  5.         String jmsProviderAddress = "tcp://localhost:61616";// 地址  
  6.   
  7.         ConnectionFactory connectionFactory = new ActiveMQConnectionFactory(  
  8.                 jmsProviderAddress);// 連接器  
  9.   
  10.         Connection connection = connectionFactory.createConnection();// 創建連接  
  11.   
  12.         Session session = connection.createSession(false,  
  13.                 Session.AUTO_ACKNOWLEDGE);// 打開會話  
  14.   
  15.         Destination dest = session.createQueue("demoQueue");// 消息目的地  
  16.   
  17.         MessageProducer producer = session.createProducer(dest);// 消息發送者  
  18.   
  19.         Message message = session.createTextMessage("hello world");// 消息  
  20.   
  21.         producer.send(message);// 發送  
  22.   
  23.         producer.close();// 關閉  
  24.         session.close();  
  25.         connection.close();  
  26.   
  27.     }  
  28.   
  29. }  

代碼很簡單,可以參考上面的圖,各組件的關係是比較清楚的 

然後是Message Consumer的例子: 
Java代碼  收藏代碼
  1. public static void main(String[] args) throws JMSException {  
  2.   
  3.         String jmsProviderAddress = "tcp://localhost:61616";// 地址  
  4.   
  5.         ConnectionFactory connectionFactory = new ActiveMQConnectionFactory(  
  6.                 jmsProviderAddress);// 連接器  
  7.   
  8.         Connection connection = connectionFactory.createConnection();// 創建連接  
  9.   
  10.         Session session = connection.createSession(false,  
  11.                 Session.AUTO_ACKNOWLEDGE);// 打開會話  
  12.   
  13.         String destinationName = "demoQueue";  
  14.   
  15.         Destination dest = session.createQueue(destinationName);// 消息目的地  
  16.   
  17.         MessageConsumer consumer = session.createConsumer(dest);  
  18.   
  19.         connection.start();  
  20.   
  21.         Message message = consumer.receive();  
  22.   
  23.         TextMessage textMessage = (TextMessage) message;  
  24.   
  25.         String text = textMessage.getText();  
  26.   
  27.         System.out.println("從ActiveMQ取回一條消息: " + text);  
  28.   
  29.         consumer.close();  
  30.         session.close();  
  31.         connection.close();  
  32.   
  33.     }  
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章