Spring Framework框架為集成消息系統(tǒng)提供了擴展(extensive) 支持:從使
用 JmsTemplate 簡化JMS API,到實現(xiàn)一個能夠異步接收消息的完整的底層設(shè)
施。Spring AMQP提供一個相似的用于'高級消息隊列協(xié)議'的特征集,并且Spring
Boot也為 RabbitTemplate 和RabbitMQ提供了自動配置選項。Spring Websocket
提供原生的STOMP消息支持,并且Spring Boot也提供了starters和自動配置支持。
JMS(Java Message Service)
JMS大致可以分為兩種功能區(qū)域,消息的生產(chǎn)和消費。JmsTemplate用于消息的生產(chǎn)和異步消息接收。Spring提供了許多消息監(jiān)聽器容器,您可以使用它們來創(chuàng)建消息驅(qū)動的POJO(MDP)。 Spring還提供了一種創(chuàng)建消息監(jiān)聽器的聲明方式。
org.springframework.jms.core包提供了使用JMS的核心功能。JmsTemplate對資源的使用和釋放就像JbdcTemplate一樣。JmsTemplate提供了多種方便的方法用于發(fā)送消息,異步消費消息,向用戶暴露JMS session和消息生產(chǎn)者。
org.springframework.jms.support包提供了JMSException異常的翻譯功能。
org.springframework.jms.support.converter包提供了Java對應(yīng)和JMS 消息之間的轉(zhuǎn)化。
org.springframework.jms.support.destination包提供了多種管理JMS目的端的策略。
org.springframework.jms.annotation包提供了必要的基礎(chǔ)框架以支持使用@JmsListener注解驅(qū)動。
org.springframework.jms.config包提供jms命名空間的解析器實現(xiàn)以及配置偵聽器容器和創(chuàng)建偵聽器端點的java配置支持。
org.springframework.jms.connection包提供了合適的ConnectionFacotry的實現(xiàn)用于獨立應(yīng)用程序。
JmsTemplate使用
JmsTemplate是JMS核心包中的中心類,為在發(fā)送和異步接受消息的對資源的創(chuàng)建和釋放簡化了操作。
編碼使用JmsTemplate僅僅需要實現(xiàn)一個明確定義高級別的回調(diào)接口。MessageCreator回調(diào)接口用JmsTemplate中提供的Session來創(chuàng)建消息;SessionCallback提供JMS session;ProducerCalback暴露一對一的Session和MessageProducer。
Jms接口提供兩種發(fā)送消息的方法,一種使用傳輸模式,優(yōu)先級和time-to-live作為服務(wù)質(zhì)量參數(shù)(QOS),另一種不是QOS參數(shù)而是默認值。
JmsTemplate是線程安全的類,所以可以配置一個并在多個地方引用。JmsTemplate是穩(wěn)定的,在內(nèi)部有一個到ConnectionFactory的引用,但是這種狀態(tài)不是構(gòu)建在會話之上。在Spring framework4.1中,JmsMessagingTemplate構(gòu)建在JmsTemplate之上提供org.springframework.messaging.Message消息抽象的集成。
連接
JmsTemplate需要引用ConnectionFactory。 ConnectionFactory是JMS規(guī)范的一部分,并作為使用JMS的入口點。 客戶端應(yīng)用程序?qū)⑵溆米鞴S以創(chuàng)建與JMS提供程序的連接,并封裝各種配置參數(shù),其中許多是特定于供應(yīng)商的,例如SSL配置選項。
使用SingleConnectionFactory
spring提供了connectionFactory接口的實現(xiàn),SingleConnectionFactory,通過調(diào)用createConnection方法返回同一個connection并忽略close的調(diào)用。
使用cachingConnectionFactory
cachingConnectionFactory繼承自SingleConnectionFactory并添加了session,Messageproducer和MessageConsumer實例的緩存。初始緩存大小設(shè)置為1.
消息監(jiān)聽容器
消息監(jiān)聽容器用來從消息隊列中接收消息并驅(qū)動MessageListener注入,負責所有消息的接收和分發(fā)對應(yīng)的linstener處理。兩種類型的消息監(jiān)聽容器:
SimpleMessageListenerContainer:在啟動時創(chuàng)建固定數(shù)量的JMS session和消費者,使用MessageConsumer.setMessageListener()標準方法注冊linstener,并由這個linstener處理回調(diào)。
DefaultMessageListenerContainer:對比于SimpleMessageListenerContainer,該容器允許在運行期間動態(tài)調(diào)整也能參與到外部事物管理。當時用JtaTransactionManager配置時每個接收的消息就會注冊為XA事務(wù)。
1,在測試環(huán)境安裝activemq,/usr/activemq/bin/activemq start 啟動
2,使用admin/admin登陸,并創(chuàng)建兩個用于測試的隊列,firstQueue,secondQueue
3,添加Spring boot對activemq的支持
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-activemq</artifactId>
</dependency>
4,注入隊列
@Bean
public Queue firstQueue(){
return new ActiveMQQueue("firstQueue");
}
@Bean
public Queue secondQueue(){
return new ActiveMQQueue("secondQueue");
}
5,配置MessageConverter
@Bean
public MessageConverter getMessageConverter(){
return new SimpleMessageConverter();
}
6,配置connectionFactory
@Bean
public ConnectionFactory getConnectionFactory(){
return new CachingConnectionFactory(getActiveMQConnectionFactory());
}
public ActiveMQConnectionFactory getActiveMQConnectionFactory(){
return new ActiveMQConnectionFactory("admin","admin","tcp://ip:61616");
}
7,配置JmsTemplate
@Bean
public JmsTemplate jmsTemplate(){
JmsTemplate jmsTemplate = new JmsTemplate(getConnectionFactory());
jmsTemplate.setMessageConverter(getMessageConverter());
return jmsTemplate;
}
8,定義生產(chǎn)者
@Component
public class Producer implements CommandLineRunner {
@Autowired
private Queue firstQueue;
@Autowired
private Queue secondQueue;
@Autowired
private JmsTemplate jmsTemplate;
@Override
public void run(String... args) throws Exception {
for (int i = 0; i < 20; i++) {
if(i%2 == 0){
this.jmsTemplate.convertAndSend(this.firstQueue,"activemq firstQueue"+i);
}else{
this.jmsTemplate.convertAndSend(this.secondQueue,"activemq secondQueue"+i);
}
Thread.sleep(2000);
}
}
}
9,定義消費者
@Component
public class Consumer {
@JmsListener(destination = "firstQueue",containerFactory = "myFactory")
public void receiveMessage(String text){
System.err.println("received firstQueue "+text);
}
@JmsListener(destination = "secondQueue")
public void receiveSecondQueue(String message){
System.err.println("received second queue "+ message);
}
}
運行程序可看到如下輸出:
received firstQueue activemq firstQueue4
received second queue activemq secondQueue5
received firstQueue activemq firstQueue6
received second queue activemq secondQueue7
received firstQueue activemq firstQueue8
received second queue activemq secondQueue9
received firstQueue activemq firstQueue10
received second queue activemq secondQueue11
received firstQueue activemq firstQueue12
received second queue activemq secondQueue13
received firstQueue activemq firstQueue14
received second queue activemq secondQueue15
received firstQueue activemq firstQueue16
received second queue activemq secondQueue17
received firstQueue activemq firstQueue18
received second queue activemq secondQueue19
activemq隊列有如下信息: