使用Spring JMS收发消息

来源:互联网 发布:北京和隆优化科技 编辑:程序博客网 时间:2024/06/05 17:50

       ActiveMQ学习笔记(四)http://my.oschina.net/xiaoxishan/blog/380446 中记录了如何使用原生的方式从ActiveMQ中收发消息。可以看出,每次收发消息都要写许多重复的代码,Spring 为我们提供了更为方便的方式,这就是Spring JMS。我们通过一个例子展开讲述。包括队列、主题消息的收发相关的Spring配置、代码、测试。

       本例中,消息的收发都写在了一个工程里。

1.使用maven管理依赖包

[xml] view plaincopy
  1. <dependencies>  
  2.     <dependency>  
  3.         <groupId>junit</groupId>  
  4.         <artifactId>junit</artifactId>  
  5.         <version>4.12</version>  
  6.         <scope>test</scope>  
  7.     </dependency>  
  8.     <dependency>  
  9.         <groupId>org.apache.activemq</groupId>  
  10.         <artifactId>activemq-all</artifactId>  
  11.         <version>5.11.0</version>  
  12.     </dependency>  
  13.     <dependency>  
  14.         <groupId>org.springframework</groupId>  
  15.         <artifactId>spring-jms</artifactId>  
  16.         <version>4.1.4.RELEASE</version>  
  17.     </dependency>  
  18.     <dependency>    
  19.         <groupId>org.springframework</groupId>    
  20.         <artifactId>spring-test</artifactId>    
  21.         <version>4.1.4.RELEASE</version>    
  22.     </dependency>   
  23. </dependencies>  


2.队列消息的收发

2.1Spring配置文件

[xml] view plaincopy
  1. <?xml version="1.0" encoding="UTF-8"?>  
  2. <beans xmlns="http://www.springframework.org/schema/beans"  
  3.     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
  4.     xsi:schemaLocation="http://www.springframework.org/schema/beans  
  5.         http://www.springframework.org/schema/beans/spring-beans.xsd">  
  6.   
  7.     <!-- 配置JMS连接工厂 -->  
  8.     <bean id="connectionFactory" class="org.apache.activemq.ActiveMQConnectionFactory">  
  9.         <property name="brokerURL" value="failover:(tcp://localhost:61616)" />  
  10.     </bean>  
  11.       
  12.     <!-- 定义消息队列(Queue) -->  
  13.     <bean id="queueDestination" class="org.apache.activemq.command.ActiveMQQueue">  
  14.         <!-- 设置消息队列的名字 -->  
  15.         <constructor-arg>  
  16.             <value>queue1</value>  
  17.         </constructor-arg>  
  18.     </bean>  
  19.       
  20.     <!-- 配置JMS模板(Queue),Spring提供的JMS工具类,它发送、接收消息。 -->  
  21.     <bean id="jmsTemplate" class="org.springframework.jms.core.JmsTemplate">  
  22.         <property name="connectionFactory" ref="connectionFactory" />  
  23.         <property name="defaultDestination" ref="queueDestination" />  
  24.         <property name="receiveTimeout" value="10000" />  
  25.     </bean>  
  26.       
  27.     <!--queue消息生产者 -->  
  28.     <bean id="producerService" class="guo.examples.mq02.queue.ProducerServiceImpl">  
  29.         <property name="jmsTemplate" ref="jmsTemplate"></property>  
  30.     </bean>  
  31.   
  32.     <!--queue消息消费者 -->  
  33.     <bean id="consumerService" class="guo.examples.mq02.queue.ConsumerServiceImpl">  
  34.         <property name="jmsTemplate" ref="jmsTemplate"></property>  
  35.     </bean>  


2.2消息生产者代码

从下面的代码可以出,使用Spring JMS,可以减少重复代码(接口类ProducerService代码省略)。

[java] view plaincopy
  1. package guo.examples.mq02.queue;  
  2.   
  3. import javax.jms.Destination;  
  4. import javax.jms.JMSException;  
  5. import javax.jms.Message;  
  6. import javax.jms.Session;  
  7.   
  8. import org.springframework.jms.core.JmsTemplate;  
  9. import org.springframework.jms.core.MessageCreator;  
  10.   
  11. public class ProducerServiceImpl implements ProducerService {  
  12.   
  13.   private JmsTemplate jmsTemplate;  
  14.     
  15.   /** 
  16.    * 向指定队列发送消息 
  17.    */  
  18.   public void sendMessage(Destination destination, final String msg) {  
  19.     System.out.println("向队列" + destination.toString() + "发送了消息------------" + msg);  
  20.     jmsTemplate.send(destination, new MessageCreator() {  
  21.       public Message createMessage(Session session) throws JMSException {  
  22.         return session.createTextMessage(msg);  
  23.       }  
  24.     });  
  25.   }  
  26.   
  27. /** 
  28.  * 向默认队列发送消息 
  29.  */  
  30.   public void sendMessage(final String msg) {  
  31.     String destination =  jmsTemplate.getDefaultDestination().toString();  
  32.     System.out.println("向队列" +destination+ "发送了消息------------" + msg);  
  33.     jmsTemplate.send(new MessageCreator() {  
  34.       public Message createMessage(Session session) throws JMSException {  
  35.         return session.createTextMessage(msg);  
  36.       }  
  37.     });  
  38.   
  39.   }  
  40.   
  41.   public void setJmsTemplate(JmsTemplate jmsTemplate) {  
  42.     this.jmsTemplate = jmsTemplate;  
  43.   }  
  44.   
  45. }  

2.3消息消费者代码

[java] view plaincopy
  1. package guo.examples.mq02.queue;  
  2.   
  3. import javax.jms.Destination;  
  4. import javax.jms.JMSException;  
  5. import javax.jms.TextMessage;  
  6.   
  7. import org.springframework.jms.core.JmsTemplate;  
  8.   
  9. public class ConsumerServiceImpl implements ConsumerService {  
  10.   
  11.     private JmsTemplate jmsTemplate;  
  12.   
  13.     /** 
  14.      * 接受消息 
  15.      */  
  16.     public void receive(Destination destination) {  
  17.         TextMessage tm = (TextMessage) jmsTemplate.receive(destination);  
  18.         try {  
  19.             System.out.println("从队列" + destination.toString() + "收到了消息:\t"  
  20.                     + tm.getText());  
  21.         } catch (JMSException e) {  
  22.             e.printStackTrace();  
  23.         }  
  24.     }  
  25.   
  26.     public void setJmsTemplate(JmsTemplate jmsTemplate) {  
  27.         this.jmsTemplate = jmsTemplate;  
  28.     }  
  29.   
  30. }  


2.4队列消息监听

接受消息的时候,可以不用2.3节中的方式,Spring JMS同样提供了消息监听的模式,下面给出对应的配置和代码。

Spring配置

[xml] view plaincopy
  1. <!-- 定义消息队列(Queue),我们监听一个新的队列,queue2 -->  
  2.     <bean id="queueDestination2" class="org.apache.activemq.command.ActiveMQQueue">  
  3.         <!-- 设置消息队列的名字 -->  
  4.         <constructor-arg>  
  5.             <value>queue2</value>  
  6.         </constructor-arg>  
  7.     </bean>  
  8.       
  9.     <!-- 配置消息队列监听者(Queue),代码下面给出,只有一个onMessage方法 -->  
  10.     <bean id="queueMessageListener" class="guo.examples.mq02.queue.QueueMessageListener" />  
  11.       
  12.     <!-- 消息监听容器(Queue),配置连接工厂,监听的队列是queue2,监听器是上面定义的监听器 -->  
  13.     <bean id="jmsContainer"  
  14.         class="org.springframework.jms.listener.DefaultMessageListenerContainer">  
  15.         <property name="connectionFactory" ref="connectionFactory" />  
  16.         <property name="destination" ref="queueDestination2" />  
  17.         <property name="messageListener" ref="queueMessageListener" />  
  18.     </bean>  

监听类代码

[java] view plaincopy
  1. package guo.examples.mq02.queue;  
  2.   
  3. import javax.jms.JMSException;  
  4. import javax.jms.Message;  
  5. import javax.jms.MessageListener;  
  6. import javax.jms.TextMessage;  
  7.   
  8. public class QueueMessageListener implements MessageListener {  
  9.         //当收到消息时,自动调用该方法。  
  10.     public void onMessage(Message message) {  
  11.         TextMessage tm = (TextMessage) message;  
  12.         try {  
  13.             System.out.println("ConsumerMessageListener收到了文本消息:\t"  
  14.                     + tm.getText());  
  15.         } catch (JMSException e) {  
  16.             e.printStackTrace();  
  17.         }  
  18.     }  
  19.   
  20. }  



3.主题消息收发

     在使用Spring JMS的时候,主题(Topic)和队列消息的主要差异体现在JmsTemplate中"pubSubDomain"是否设置为True。如果为True,则是Topic;如果是false或者默认,则是queue。

[xml] view plaincopy
  1. <property name="pubSubDomain" value="true" />  


3.1Spring配置

[xml] view plaincopy
  1. <!-- 定义消息主题(Topic) -->  
  2.     <bean id="topicDestination" class="org.apache.activemq.command.ActiveMQTopic">  
  3.         <constructor-arg>  
  4.             <value>guo_topic</value>  
  5.         </constructor-arg>  
  6.     </bean>  
  7.     <!-- 配置JMS模板(Topic),pubSubDomain="true"-->  
  8.     <bean id="topicJmsTemplate" class="org.springframework.jms.core.JmsTemplate">  
  9.         <property name="connectionFactory" ref="connectionFactory" />  
  10.         <property name="defaultDestination" ref="topicDestination" />  
  11.         <property name="pubSubDomain" value="true" />  
  12.         <property name="receiveTimeout" value="10000" />  
  13.     </bean>  
  14.     <!--topic消息发布者 -->  
  15.     <bean id="topicProvider" class="guo.examples.mq02.topic.TopicProvider">  
  16.         <property name="topicJmsTemplate" ref="topicJmsTemplate"></property>  
  17.     </bean>  
  18.     <!-- 消息主题监听者 和 主题监听容器 可以配置多个,即多个订阅者 -->  
  19.     <!-- 消息主题监听者(Topic) -->  
  20.     <bean id="topicMessageListener" class="guo.examples.mq02.topic.TopicMessageListener" />  
  21.     <!-- 主题监听容器 (Topic) -->  
  22.     <bean id="topicJmsContainer"  
  23.         class="org.springframework.jms.listener.DefaultMessageListenerContainer">  
  24.         <property name="connectionFactory" ref="connectionFactory" />  
  25.         <property name="destination" ref="topicDestination" />  
  26.         <property name="messageListener" ref="topicMessageListener" />  
  27.     </bean>  

3.2消息发布者

[java] view plaincopy
  1. package guo.examples.mq02.topic;  
  2.   
  3. import javax.jms.Destination;  
  4. import javax.jms.JMSException;  
  5. import javax.jms.Message;  
  6. import javax.jms.Session;  
  7.   
  8. import org.springframework.jms.core.JmsTemplate;  
  9. import org.springframework.jms.core.MessageCreator;  
  10.   
  11. public class TopicProvider {  
  12.   
  13.     private JmsTemplate topicJmsTemplate;  
  14.   
  15.     /** 
  16.      * 向指定的topic发布消息 
  17.      *  
  18.      * @param topic 
  19.      * @param msg 
  20.      */  
  21.     public void publish(final Destination topic, final String msg) {  
  22.   
  23.         topicJmsTemplate.send(topic, new MessageCreator() {  
  24.             public Message createMessage(Session session) throws JMSException {  
  25.                 System.out.println("topic name 是" + topic.toString()  
  26.                         + ",发布消息内容为:\t" + msg);  
  27.                 return session.createTextMessage(msg);  
  28.             }  
  29.         });  
  30.     }  
  31.   
  32.     public void setTopicJmsTemplate(JmsTemplate topicJmsTemplate) {  
  33.         this.topicJmsTemplate = topicJmsTemplate;  
  34.     }  
  35.   
  36. }  

3.3消息订阅者(监听)

[java] view plaincopy
  1. package guo.examples.mq02.topic;  
  2.   
  3. import javax.jms.JMSException;  
  4. import javax.jms.Message;  
  5. import javax.jms.MessageListener;  
  6. import javax.jms.TextMessage;  
  7. /** 
  8.  *和队列监听的代码一样。 
  9.  */  
  10. public class TopicMessageListener implements MessageListener {  
  11.   
  12.     public void onMessage(Message message) {  
  13.         TextMessage tm = (TextMessage) message;  
  14.         try {  
  15.             System.out.println("TopicMessageListener \t" + tm.getText());  
  16.         } catch (JMSException e) {  
  17.             e.printStackTrace();  
  18.         }  
  19.     }  
  20.   
  21. }  


4.测试

4.1 测试代码

[java] view plaincopy
  1. package guo.examples.mq02;  
  2.   
  3. import javax.jms.Destination;  
  4.   
  5. import guo.examples.mq02.queue.ConsumerService;  
  6. import guo.examples.mq02.queue.ProducerService;  
  7. import guo.examples.mq02.topic.TopicProvider;  
  8.   
  9. import org.junit.Test;  
  10. import org.junit.runner.RunWith;  
  11. import org.springframework.beans.factory.annotation.Autowired;  
  12. import org.springframework.beans.factory.annotation.Qualifier;  
  13. import org.springframework.test.context.ContextConfiguration;  
  14. import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;  
  15.   
  16. /** 
  17.  * 测试Spring JMS 
  18.  *  
  19.  * 1.测试生产者发送消息 
  20.  *  
  21.  * 2. 测试消费者接受消息 
  22.  *  
  23.  * 3. 测试消息监听 
  24.  *  
  25.  * 4.测试主题监听 
  26.  * 
  27.  */  
  28. @RunWith(SpringJUnit4ClassRunner.class)  
  29. // ApplicationContext context = new  
  30. // ClassPathXmlApplicationContext("applicationContext.xml");  
  31. @ContextConfiguration("/applicationContext.xml")  
  32. public class SpringJmsTest {  
  33.   
  34.     /** 
  35.      * 队列名queue1 
  36.      */  
  37.     @Autowired  
  38.     private Destination queueDestination;  
  39.   
  40.     /** 
  41.      * 队列名queue2 
  42.      */  
  43.     @Autowired  
  44.     private Destination queueDestination2;  
  45.   
  46.     /** 
  47.      * 主题 guo_topic 
  48.      */  
  49.     @Autowired  
  50.     @Qualifier("topicDestination")  
  51.     private Destination topic;  
  52.   
  53.     /** 
  54.      * 主题消息发布者 
  55.      */  
  56.     @Autowired  
  57.     private TopicProvider topicProvider;  
  58.   
  59.     /** 
  60.      * 队列消息生产者 
  61.      */  
  62.     @Autowired  
  63.     @Qualifier("producerService")  
  64.     private ProducerService producer;  
  65.   
  66.     /** 
  67.      * 队列消息生产者 
  68.      */  
  69.     @Autowired  
  70.     @Qualifier("consumerService")  
  71.     private ConsumerService consumer;  
  72.   
  73.     /** 
  74.      * 测试生产者向queue1发送消息 
  75.      */  
  76.     @Test  
  77.     public void testProduce() {  
  78.         String msg = "Hello world!";  
  79.         producer.sendMessage(msg);  
  80.     }  
  81.   
  82.     /** 
  83.      * 测试消费者从queue1接受消息 
  84.      */  
  85.     @Test  
  86.     public void testConsume() {  
  87.         consumer.receive(queueDestination);  
  88.     }  
  89.   
  90.     /** 
  91.      * 测试消息监听 
  92.      *  
  93.      * 1.生产者向队列queue2发送消息 
  94.      *  
  95.      * 2.ConsumerMessageListener监听队列,并消费消息 
  96.      */  
  97.     @Test  
  98.     public void testSend() {  
  99.         producer.sendMessage(queueDestination2, "Hello China~~~~~~~~~~~~~~~");  
  100.     }  
  101.   
  102.     /** 
  103.      * 测试主题监听 
  104.      *  
  105.      * 1.生产者向主题发布消息 
  106.      *  
  107.      * 2.ConsumerMessageListener监听主题,并消费消息 
  108.      */  
  109.     @Test  
  110.     public void testTopic() throws Exception {  
  111.         topicProvider.publish(topic, "Hello T-To-Top-Topi-Topic!");  
  112.     }  
  113.   
  114. }  

4.2 测试结果

topic name 是topic://guo_topic,发布消息内容为:Hello T-To-Top-Topi-Topic!TopicMessageListener Hello T-To-Top-Topi-Topic!向队列queue://queue2发送了消息------------Hello China~~~~~~~~~~~~~~~ConsumerMessageListener收到了文本消息:Hello China~~~~~~~~~~~~~~~向队列queue://queue1发送了消息------------Hello world!从队列queue://queue1收到了消息:Hello world!
0 0
原创粉丝点击