JMS即Java消息服務(Java Message Service)應用程序接口,是一個Java平臺中關于面向消息中間件(MOM)的API,用于在兩個應用程序之間,或分布式系統中發送消息,進行異步通信。Java消息服務是一個與具體平臺無關的API,絕大多數MOM提供商都對JMS提供支持。
基于之前一篇“一個故事告訴你什么是消息隊列”,了解了消息隊列的使用場景以及相關的特性。本文主要講述消息服務在 JAVA 中的使用。
市面上的有關消息隊列的技術選型非常多,如果我們的代碼框架要支持不同的消息實現,在保證框架具有較高擴展性的前提下,我們勢必要進行一定的封裝。
在 JAVA 中,大可不必如此。因為 JAVA 已經制定了一套標準的 JMS 規范。該規范定義了一套通用的接口和相關語義,提供了諸如持久、驗證和事務的消息服務,其最主要的目的是允許Java應用程序訪問現有的消息中間件。就和 JDBC 一樣。
在介紹具體的使用之前,先簡單介紹一下 JMS 的一些基本知識。這里我打算分為 3 部分來介紹,即 消息隊列(MQ)的連接、消息發送與消息接收。
這里我們的技術選型是 SpringBoot、JMS、ActiveMQ
為了更好的理解 JMS,這里沒有使用 SpringBoot 零配置來搭建項目
使用 MQ 的第一步一定是先連接 MQ。因為這里使用的是 JMS 規范,對于任何遵守 JMS 規范的 MQ 來說,都會實現相應的ConnectionFactory接口,因此我們只需要創建一個ConnectionFactory工廠類,由它來實現 MQ 的連接,以及封裝一系列特性的 MQ 參數。
例子:這里我們以 ActiveMQ 為例,
maven 依賴:
org.springframework.bootspring-boot-starter-parent1.5.3.RELEAseorg.springframework.bootspring-boot-starter-activemq
創建 ActiveMQ 連接工廠:
@BeanpublicConnectionFactoryconnectionFactory(){ActiveMQConnectionFactoryconnectionFactory=newActiveMQConnectionFactory();connectionFactory.setBrokerURL(ActiveMQ_URL);connectionFactory.setUserName(ActiveMQ_USER);connectionFactory.setPassword(ActiveMQ_PASSWORD);returnconnectionFactory;}
關于消息的發送,是通過 JMS 核心包中的JmsTemplate類來實現的,它簡化了 JMS 的使用,因為在發送或同步接收消息時它幫我們處理了資源的創建和釋放。從它的作用也不難推測出,它需要引用我們上面創建的連接工廠,具體代碼如下:
@BeanpublicJmsTemplatejmsQueueTemplate(){returnnewJmsTemplate(connectionFactory());}
JmsTemplate創建完成后,我們就可以調用它的方法來發送消息了。這里有兩個概念需要注意:
代碼示例:
@AutowiredprivateJmsTemplatejmsQueueTemplate;/***發送原始消息Message*/publicvoidsend(){jmsQueueTemplate.send("queue1",newMessageCreator(){@OverridepublicMessagecreateMessage(Sessionsession)throwsJMSException{returnsession.createTextMessage("我是原始消息");}});}
優化:當然,我們不用每次都通過MessageCreator匿名類的方式來創建Message對象,JmsTemplate類中提供了對象實體自動轉換為Message對象的方法,convertAndSend(String destinationName, final Object message)。
優化代碼示例:
/***發送消息自動轉換成原始消息*/publicvoidconvertAndSend(){jmsQueueTemplate.convertAndSend("queue1","我是自動轉換的消息");}
注:關于消息轉換,還可以通過實現MessageConverter接口來自定義轉換內容
講完了消息發送,我們最后來說說消息是如何接收的。消息既然是以Message對象的形式發送到指定的目的地,那么消息的接收勢必會去指定的目的地上去接收消息。這里采用的是監聽者的方式來監聽指定地點的消息,采用注解@JmsListener來設置監聽方法。
代碼示例:
@ComponentpublicclassListener1{@JmsListener(destination="queue1")publicvoidreceive(Stringmsg){System.out.println("監聽到的消息內容為:"+msg);}}
有了監聽的目標和方法后,監聽器還得和 MQ 關聯起來,這樣才能運作起來。這里的監聽器可能不止一個,如果每個都要和 MQ 建立連接,肯定不太合適。所以需要一個監聽容器工廠的概念,即接口JmsListenerContainerFactory,它會引用上面創建好的與 MQ 的連接工廠,由它來負責接收消息以及將消息分發給指定的監聽器。當然也包括事務管理、資源獲取與釋放和異常轉換等。
代碼示例:
@BeanpublicDefaultJmsListenerContainerFactoryjmsQueueListenerContainerFactory(){DefaultJmsListenerContainerFactoryfactory=newDefaultJmsListenerContainerFactory();factory.setConnectionFactory(connectionFactory());//設置連接數factory.setConcurrency("3-10");//重連間隔時間factory.setRecoveryInterval(1000L);returnfactory;}
代碼地址:https://github.com/jasonGeng88/springboot-jms
對 JMS 有了基本的理解后,我們就來在具體的場景中使用一下。
首先,我們需要先啟動 ActiveMQ,這里我們以 Docker 容器化的方式進行啟動。
啟動命令:
dockerrun-d-p8161:8161-p61616:61616--nameactivemqwebcenter/activemq
啟動成功后,在 ActiveMQ 可視化界面查看效果(http://localhost:8161):
點對點模式(單消費者)
下面介紹消息隊列中最常用的一種場景,即點對點模式?;靖拍钊缦?
代碼實現(為簡化代碼,部分代碼沿用上面所述): 啟動文件(Application.java)
@SpringBootApplication@EnableJmspublicclassApplication{.../***JMS隊列的模板類*connectionFactory()為ActiveMQ連接工廠*/@BeanpublicJmsTemplatejmsQueueTemplate(){returnnewJmsTemplate(connectionFactory());}publicstaticvoidmain(String[]args){SpringApplication.run(Application.class,args);}}
注解@EnableJms設置在@Configuration類上,用來聲明對 JMS 注解的支持。
@ComponentpublicclassPtpProducer{@AutowiredprivateJmsTemplatejmsQueueTemplate;/***發送消息自動轉換成原始消息*/publicvoidconvertAndSend(){jmsQueueTemplate.convertAndSend("ptp","我是自動轉換的消息");}}
@RestController@RequestMapping(value="/ptp")publicclassPtpController{@AutowiredprivatePtpProducerptpProducer;@RequestMapping(value="/convertAndSend")publicObjectconvertAndSend(){ptpProducer.convertAndSend();return"success";}}
@SpringBootApplication@EnableJmspublicclassApplication{.../***JMS隊列的監聽容器工廠*/@Bean(name="jmsQueueListenerCF")publicDefaultJmsListenerContainerFactoryjmsQueueListenerContainerFactory(){DefaultJmsListenerContainerFactoryfactory=newDefaultJmsListenerContainerFactory();factory.setConnectionFactory(connectionFactory());//設置連接數factory.setConcurrency("3-10");//重連間隔時間factory.setRecoveryInterval(1000L);returnfactory;}...}
@ComponentpublicclassPtpListener1{/***消息隊列監聽器*destination隊列地址*containerFactory監聽器容器工廠,若存在2個以上的監聽容器工廠,需進行指定*/@JmsListener(destination="ptp",containerFactory="jmsQueueListenerCF")publicvoidreceive(Stringmsg){System.out.println("點對點模式1:"+msg);}}
啟動項目啟動后,通過 REST 接口的方式來調用消息生產者發送消息,請求如下:
curl-XGET127.0.0.1:8080/ptp/convertAndSend
消費者控制臺信息:
ActiveMQ 控制臺信息:
列表說明:
基于上面一個消費者消費的模式,因為生產者可能會有很多,同時像某個隊列發送消息,這時一個消費者可能會成為瓶頸。所以需要多個消費者來分攤消費壓力(消費線程池能解決一定壓力,但畢竟在單機上,做不到分布式分布,所以多消費者是有必要的),也就產生了下面的場景。
添加新的監聽器
@ComponentpublicclassPtpListener2{@JmsListener(destination=Constant.QUEUE_NAME,containerFactory="jmsQueueListenerCF")publicvoidreceive(Stringmsg){System.out.println("點對點模式2:"+msg);}}
演示 這里我們發起 10 次請求,來觀察消費者的消費情況:
這里因為監聽容器設置了線程池的緣故,在實際消費過程中,監聽器消費的順序會有所差異。
發布訂閱模式
除了點對點模式,發布訂閱模式也是消息隊列中常見的一種使用。試想一下,有一個即時聊天群,你在群里發送一條消息。所有在這個群里的人(即訂閱了該群的人),都會收到你發送的信息。
基本概念:
代碼實現 修改 JmsTemplate 模板類,使其支持發布訂閱功能
@SpringBootApplication@EnableJmspublicclassApplication{...@BeanpublicJmsTemplatejmsTopicTemplate(){JmsTemplatejmsTemplate=newJmsTemplate(connectionFactory());jmsTemplate.setPubSubDomain(true);returnjmsTemplate;}...}
消息生產者(PubSubProducer.java)
@ComponentpublicclassPtpProducer{@AutowiredprivateJmsTemplatejmsTopicTemplate;publicvoidconvertAndSend(){jmsTopicTemplate.convertAndSend("topic","我是自動轉換的消息");}}
生產者調用類(PubSubController.java)
@RestController@RequestMapping(value="/pubsub")publicclassPtpController{@AutowiredprivatePubSubProducerpubSubProducer;@RequestMapping(value="/convertAndSend")publicStringconvertAndSend(){pubSubProducer.convertAndSend();return"success";}}
修改 DefaultJmsListenerContainerFactory 類,使其支持發布訂閱功能
@SpringBootApplication@EnableJmspublicclassApplication{.../***JMS隊列的監聽容器工廠*/@Bean(name="jmsTopicListenerCF")publicDefaultJmsListenerContainerFactoryjmsTopicListenerContainerFactory(){DefaultJmsListenerContainerFactoryfactory=newDefaultJmsListenerContainerFactory();factory.setConnectionFactory(connectionFactory());factory.setConcurrency("1");factory.setPubSubDomain(true);returnfactory;}...}
消息監聽器(這里設置2個訂閱者)
@ComponentpublicclassPubSubListener1{@JmsListener(destination="topic",containerFactory="jmsTopicListenerCF")publicvoidreceive(Stringmsg){System.out.println("訂閱者1-"+msg);}}@ComponentpublicclassPubSubListener2{@JmsListener(destination="topic",containerFactory="jmsTopicListenerCF")publicvoidreceive(Stringmsg){System.out.println("訂閱者2-"+msg);}}
演示
curl-XGET127.0.0.1:8080/pubSub/convertAndSend
消費者控制臺信息:
ActiveMQ 控制臺信息:
看完了這篇文章,相信你對“JMS是什么意思”有了一定的了解,如果想了解更多相關知識,歡迎關注本站行業資訊頻道,感謝各位的閱讀!
本文由 貴州做網站公司 整理發布,部分圖文來源于互聯網,如有侵權,請聯系我們刪除,謝謝!
c語言中正確的字符常量是用一對單引號將一個字符括起表示合法的字符常量。例如‘a’。數值包括整型、浮點型。整型可用十進制,八進制,十六進制。八進制前面要加0,后面...
2022年天津專場考試原定于3月19日舉行,受疫情影響確定延期,但目前延期后的考試時間推遲。 符合報名條件的考生,須在規定時間登錄招考資訊網(www.zha...
:喜歡聽,樂意看。指很受歡迎?!巴卣官Y料”喜聞樂見:[ xǐ wén lè jiàn ]詳細解釋1. 【解釋】:喜歡聽,樂意看。指很受歡迎。2. 【示例】:這是...
和輝申購什么時候上市?新股申購完成后,一般過8-14天(自然日)上市交易,根據計算可得和輝光電688538上市時間可能會在5月26日-6月1日。就是說一般新股中簽后6天左右就可以上市了,當然新股中簽之后也會出現延遲上市的情況,但是一般不會超過14天。在新股中簽之后,投資者只需要保證賬戶當中有足夠的申購資金就可以了,接下來就是耐心等待7天左右的時間等待新股正式上市交易吧。和輝光電公司簡介上海和輝【光...
網易理財的現金寶產品有風險嗎?現金寶是網易理財平臺精選的合作方提供的一款具有較高收益且保證資金隨取隨用的貨幣基金產品,貨幣市場基金是證券投資基金中的低風險品種,歷史上未曾出現負收益情況。網易現金寶是互聯網公司網易和知名的基金公司匯添富基金合作推出的理財產品,購買后即可享受貨幣基金收益。一分錢起存。收益高于銀行活期存款,又具有很好的流動性,隨取隨用,支持7*24小時申請即時取現,取現資金實時到賬。和...
什么是農業銀行惠農卡?金穗惠農卡和金穗借記卡有什么區別?金穗惠農卡就是中國農業銀行基于金穗借記卡業務平臺開發的,面向廣大農民的綜合性銀行卡產品,惠農卡作為借記卡產品之一, 具備現金存取、轉賬結算、消費、理財等基礎金融功能,可以在線操作,實時核算。金穗惠農卡和金穗借記卡的區別一、性質不同.1、金穗惠農卡金穗惠農卡是中國農業銀行基于金穗借記卡業務平臺研發的,面向全體農戶發行的綜合性銀行卡產品。2、金穗...