简介
实战一 , 实战二介绍了ActiveMQ的基本概念和配置方式.
本篇将通过一个实例介绍使用spring发送,消费topic, queue类型消息的方法. 不懂topic和queue的google 之.
?
如图示, TOPIC和QUEUE分别代表一个topic和一个queue消息通道.
- TopicMessageProducer向topic发送消息, TopicConsumerA和TopicConsumerB则从topic消费消息.
- QueueMessageProducer向Queue发送消息, QueueConsumer从Queue中消费消息
Spring整合JMS
就像对orm, web的支持一样, spring同样支持jms, 为整合jms到已有的项目提供了很多便利的方法. 本篇主要讲实战, 是所以先从配置开始, spring配置jms基本上需要8个部分.
- ConnectionFactory. 和jms服务器的连接, 可以是外部的jms server, 也可以使用embedded ActiveMQ Broker.
- Destination. 有topic和queue两种方式.
- JmsTemplate. spring提供的jms模板.
- MessageConverter. 消息转换器.
- MessageProducer. 消息生产者.
- MessageConsumer. 消息消费者.
- MessageListener. 消息监听器
- MessageListenerContainer. 消息监听容器
下面以实例的方式介绍上面8个部分.
1. ConnectionFactory
- <amq:connectionFactory?id="jmsConnectionFactory"?brokerURL="vm://localhost"?/>??
<amq:connectionfactory id="jmsConnectionFactory" brokerurl="vm://localhost">
?brokerURL是指要连接的activeMQ server的地址, activeMQ提供了多种brokerURL, 集体可参见文档.一般我们使用嵌套的ActiveMQ server. 配置如下, 这个配置使用消息的存储机制, 服务器重启也不会丢失消息.
- ??
- ????<amq:broker?useJmx="false"?persistent="true">??
- ????????<amq:persistenceAdapter>??
- ????????????<amq:amqPersistenceAdapter?directory="d:/amq"/>??
- ????????amq:persistenceAdapter>??
- ????????<amq:transportConnectors>??
- ????????????<amq:transportConnector?uri="tcp://localhost:61616"?/>??
- ???????????????????????<amq:transportConnector?uri="vm://localhost:0"?/>??
- ????????amq:transportConnectors>??
- ????amq:broker>??
<amq:broker usejmx="false" persistent="true"> <amq:persistenceadapter> <amq:amqpersistenceadapter directory="d:/amq"> </amq:persistenceadapter> <amq:transportconnectors> <amq:transportconnector uri="tcp://localhost:61616"> <amq:transportconnector uri="vm://localhost:0"> </amq:transportconnectors> </amq:broker>
?2. Destination
?在实例中我们使用了两种destination
- ??
- ??
- <amq:topic?name="TOPIC"?physicalName="JMS-TEST-TOPIC"?/>??
- ??
- <amq:queue?name="QUEUE"?physicalName="JMS-TEST-QUEUE"?/>??
<amq:topic name="TOPIC" physicalname="JMS-TEST-TOPIC"> <amq:queue name="QUEUE" physicalname="JMS-TEST-QUEUE">
?3. JmsTemplate
- ??
- ????<bean?id="jmsTemplate"?class="org.springframework.jms.core.JmsTemplate">??
- ????????<property?name="connectionFactory">??
- ??????????????
- ????????????<bean?class="org.springframework.jms.connection.SingleConnectionFactory">??
- ????????????????<property?name="targetConnectionFactory"?ref="jmsConnectionFactory"?/>??
- ????????????bean>??
- ????????property>??
- ??????????
- ????????<property?name="messageConverter"?ref="defaultMessageConverter"?/>??
- ????bean>??
<bean id="jmsTemplate" class="org.springframework.jms.core.JmsTemplate"> <property name="connectionFactory"> <bean class="org.springframework.jms.connection.SingleConnectionFactory"> <property name="targetConnectionFactory" ref="jmsConnectionFactory"> </bean> </property> <property name="messageConverter" ref="defaultMessageConverter"> </bean>
? 4. MessageConverter
?? MessageConverter实现的是org.springframework.jms.support.converter.MessageConverter接口, 提供消息的转换功能. DefaultMessageConverter的实现见附件.
- <bean?id="defaultMessageConverter"?class="com.andyao.activemq.DefaultMessageConverter"?/>??
<bean id="defaultMessageConverter" class="com.andyao.activemq.DefaultMessageConverter">
? 5. MessageProducer
?? 实例拥有两个消息生产者, 消息生产者都是POJO, 实现见附件.
- ??
- ????<bean?id="topicMessageProducer"?class="com.andyao.activemq.TopicMessageProducer">??
- ????????<property?name="template"?ref="jmsTemplate"?/>??
- ????????<property?name="destination"?ref="TOPIC"?/>??
- ????bean>??
- ????<bean?id="queueMessageProducer"?class="com.andyao.activemq.QueuMessageProducer">??
- ????????<property?name="template"?ref="jmsTemplate"?/>??
- ????????<property?name="destination"?ref="QUEUE"?/>??
- ????bean>??
<bean id="topicMessageProducer" class="com.andyao.activemq.TopicMessageProducer"> <property name="template" ref="jmsTemplate"> <property name="destination" ref="TOPIC"> </bean> <bean id="queueMessageProducer" class="com.andyao.activemq.QueuMessageProducer"> <property name="template" ref="jmsTemplate"> <property name="destination" ref="QUEUE"> </bean>
?6. MessageConsumer
?TOPIC通道有两个消息消费者, QUEUE有一个消息消费者
- ??
- ??????
- ????<bean?id="topicConsumerA"?class="com.andyao.activemq.TopicConsumerA"?/>??
- ??????
- ????<bean?id="topicConsumerB"?class="com.andyao.activemq.TopicConsumerB"?/>??
- ??????
- ????<bean?id="queueConsumer"?class="com.andyao.activemq.QueueConsumer"?/>??
<bean id="topicConsumerA" class="com.andyao.activemq.TopicConsumerA"> <bean id="topicConsumerB" class="com.andyao.activemq.TopicConsumerB"> <bean id="queueConsumer" class="com.andyao.activemq.QueueConsumer">
? 7. MessageListener
每一个消息消费者都对应一个MessageListener
- <bean?id="topicListenerA"?class="org.springframework.jms.listener.adapter.MessageListenerAdapter">??
- ????????<constructor-arg?ref="topicConsumerA"?/>??
- ??????????
- ????????<property?name="defaultListenerMethod"?value="receive"?/>??
- ??????????
- ????????<property?name="messageConverter"?ref="defaultMessageConverter"?/>??
- ????bean>??
- ??
- ????<bean?id="topicListenerB"?class="org.springframework.jms.listener.adapter.MessageListenerAdapter">??
- ????????<constructor-arg?ref="topicConsumerB"?/>??
- ??????????
- ????????<property?name="defaultListenerMethod"?value="receive"?/>??
- ??????????
- ????????<property?name="messageConverter"?ref="defaultMessageConverter"?/>??
- ????bean>??
- ??
- ????<bean?id="queueListener"?class="org.springframework.jms.listener.adapter.MessageListenerAdapter">??
- ????????<constructor-arg?ref="queueConsumer"?/>??
- ??????????
- ????????<property?name="defaultListenerMethod"?value="receive"?/>??
- ??????????
- ????????<property?name="messageConverter"?ref="defaultMessageConverter"?/>??
- ????bean>??
<bean id="topicListenerA" class="org.springframework.jms.listener.adapter.MessageListenerAdapter"> <constructor-arg ref="topicConsumerA"> <property name="defaultListenerMethod" value="receive"> <property name="messageConverter" ref="defaultMessageConverter"> </bean> <bean id="topicListenerB" class="org.springframework.jms.listener.adapter.MessageListenerAdapter"> <constructor-arg ref="topicConsumerB"> <property name="defaultListenerMethod" value="receive"> <property name="messageConverter" ref="defaultMessageConverter"> </bean> <bean id="queueListener" class="org.springframework.jms.listener.adapter.MessageListenerAdapter"> <constructor-arg ref="queueConsumer"> <property name="defaultListenerMethod" value="receive"> <property name="messageConverter" ref="defaultMessageConverter"> </bean>
?8. MessageListenerContainer
?有几个MessageListener既有几个MessageListenerContainer
- <bean?id="topicListenerContainerA"?class="org.springframework.jms.listener.DefaultMessageListenerContainer">??
- ????????<property?name="connectionFactory"?ref="jmsConnectionFactory"?/>??
- ????????<property?name="destination"?ref="TOPIC"?/>??
- ????????<property?name="messageListener"?ref="topicListenerA"?/>??
- ????bean>??
- ??
- ????<bean?id="topicListenerContainerB"?class="org.springframework.jms.listener.DefaultMessageListenerContainer">??
- ????????<property?name="connectionFactory"?ref="jmsConnectionFactory"?/>??
- ????????<property?name="destination"?ref="TOPIC"?/>??
- ????????<property?name="messageListener"?ref="topicListenerB"?/>??
- ????bean>??
- ???? ??
- ????<bean?id="queueListenerContainer"?class="org.springframework.jms.listener.DefaultMessageListenerContainer">??
- ????????<property?name="connectionFactory"?ref="jmsConnectionFactory"?/>??
- ????????<property?name="destination"?ref="QUEUE"?/>??
- ????????<property?name="messageListener"?ref="queueListener"?/>??
- ????bean>??
<bean id="topicListenerContainerA" class="org.springframework.jms.listener.DefaultMessageListenerContainer"> <property name="connectionFactory" ref="jmsConnectionFactory"> <property name="destination" ref="TOPIC"> <property name="messageListener" ref="topicListenerA"> </bean> <bean id="topicListenerContainerB" class="org.springframework.jms.listener.DefaultMessageListenerContainer"> <property name="connectionFactory" ref="jmsConnectionFactory"> <property name="destination" ref="TOPIC"> <property name="messageListener" ref="topicListenerB"> </bean> <bean id="queueListenerContainer" class="org.springframework.jms.listener.DefaultMessageListenerContainer"> <property name="connectionFactory" ref="jmsConnectionFactory"> <property name="destination" ref="QUEUE"> <property name="messageListener" ref="queueListener"> </bean>
? Summary
写spring配置文件的时候, 要把MessageProducer, MessageConsumer,MessageListener,MessageListenerContainer几个地方弄清楚:
- 可以有一个或者多个消息生产者向同一个destination发送消息.
- queue类型的只能有一个消息消费者.
- topic类型的可以有多个消息消费者.
- 每个消费者对应一个MessageListener和一个MessageListenerContainer.
?