Spring与ActiveMQ的集成

阅读更多
JMS与MQ详解: http://www.fx114.net/qa-48-91234.aspx
JMS(ActiveMQ) PTP和PUB/SUB模式实例: http://donald-draper.iteye.com/blog/2347445
ActiveMQ连接工厂、连接详解: http://donald-draper.iteye.com/blog/2348070
ActiveMQ会话初始化: http://donald-draper.iteye.com/blog/2348341
ActiveMQ生产者: http://donald-draper.iteye.com/blog/2348381
ActiveMQ消费者: http://donald-draper.iteye.com/blog/2348389
ActiveMQ启动过程详解 :http://donald-draper.iteye.com/blog/2348399
ActiveMQ Broker发送消息给消费者过程详解: http://donald-draper.iteye.com/blog/2348440
Spring与ActiveMQ的集成: http://donald-draper.iteye.com/blog/2347638
Spring与ActiveMQ的集成详解一: http://donald-draper.iteye.com/blog/2348449
Spring与ActiveMQ的集成详解二: http://donald-draper.iteye.com/blog/2348461
在前文中我们讲过ActiveMQ的PTP和PUB/SUB模式实例,今天我们来看一下ActiveMQ与Spring的集成,Spring为4.0.4,ActiveMQ为5.12.1,在做下面的测试之间,要先添加ActiveMQ的用户:
如下:
修改ActiveMQ安装目录下的配置文件夹下的jetty.xml
[root@zabbix conf]# vim jetty.xml 

 
        
        
        
        
    
    
        
        
         
        
    

保证authenticate属性为true;
再添加用户信息,修改jetty-realm.properties文件,我的如下:
[root@zabbix conf]# more jetty-realm.properties 
## ---------------------------------------------------------------------------
## Licensed to the Apache Software Foundation (ASF) under one or more
## contributor license agreements.  See the NOTICE file distributed with
## this work for additional information regarding copyright ownership.
## The ASF licenses this file to You under the Apache License, Version 2.0
## (the "License"); you may not use this file except in compliance with
## the License.  You may obtain a copy of the License at
## 
## http://www.apache.org/licenses/LICENSE-2.0
## 
## Unless required by applicable law or agreed to in writing, software
## distributed under the License is distributed on an "AS IS" BASIS,
## WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
## See the License for the specific language governing permissions and
## limitations under the License.
## ---------------------------------------------------------------------------

# Defines users that can access the web (console, demo, etc.)
# username: password [,rolename ...]
#用户名:密码,角色
admin: admin, admin
user: 123456, user
[root@zabbix conf]# 


重启ActiveMQ,即可;

需要引入的jar包,

Spring与ActiveMQ的集成_第1张图片

注意不要直接引入activemq-all-5.12.1,这种方式容易产生包冲突;

1.我们先来测试JMSTemplate,操纵ActiveMQ的方式
ActiveMQ属性配置文件activemq.properties
# ActiveMQ settings
activemq.brokerURL=tcp://192.168.126.128:61616
activemq.userName=user
activemq.password=123456
activemq.queueName=testQueue
activemq.topicName=testTopic

 
引入属性文件:
  
		  
			  
                 /WEB-INF/classes/jdbc.properties  
                 /WEB-INF/classes/redis.properties
                 /WEB-INF/classes/activemq.properties
                 
              
          
 

ActiveMQ配置文件activemq-context.xml



           
          
              
              
              
          
        
      
    
      
          
          
              
              
          
          
          
              
              
            
             
              
        	 
                   
          
          
              
              
          
          
          
              
              
              
              
            
              
               
        	
          
			 


引用配置文件:


新建订单实体类:

package com.enity;

import java.io.Serializable;

public class Order implements Serializable{
	
	/**
	 * 
	 */
	private static final long serialVersionUID = -343247274477730446L;
	private Integer id;//订单id
	private Double amount;
	private Integer goodsId;//商品id
	private Integer goodsAmount;//商品数量
	private Integer shopId;//店铺名
	public Integer getId() {
		return id;
	}
	public void setId(Integer id) {
		this.id = id;
	}
	public Double getAmount() {
		return amount;
	}
	public void setAmount(Double amount) {
		this.amount = amount;
	}
	public Integer getGoodsId() {
		return goodsId;
	}
	public void setGoodsId(Integer goodsId) {
		this.goodsId = goodsId;
	}
	public Integer getGoodsAmount() {
		return goodsAmount;
	}
	public void setGoodsAmount(Integer goodsAmount) {
		this.goodsAmount = goodsAmount;
	}
	public Integer getShopId() {
		return shopId;
	}
	public void setShopId(Integer shopId) {
		this.shopId = shopId;
	}
	public String toString(){
		return "订单id:"+this.id+","+"金额(元):"+this.amount+","+"商品id:"+
	          this.shopId+","+"商品数量:"+this.goodsAmount+","+"店铺id:"+this.shopId;
	}
	
}

队列消息生产者:

package com.activemq.service.imp;

import java.util.Date;

import javax.annotation.Resource;
import javax.jms.Destination;
import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.Session;
import javax.jms.TextMessage;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.jms.core.JmsTemplate;
import org.springframework.jms.core.MessageCreator;
import org.springframework.stereotype.Service;

import com.activemq.service.QueueProducerService;
import com.enity.Order;
/**
 * 生产Queue
 * @author donald
 * @date 2016-12-27
 * @time 上午10:19:27
 */
@Service
public class QueueProducerServiceImp implements QueueProducerService{
	private static final Logger log = LoggerFactory.getLogger(QueueProducerServiceImp.class);
	@Resource(name="jmsQueueTemplate")
	JmsTemplate jmsTemplate;
	@Resource(name="testQueue")
	Destination testQueue;
	/**
	 * 发送队列消息
	 */
	public void send() {
		MessageCreator messageCreator = new MessageCreator() {
			public Message createMessage(Session session) throws JMSException {
				TextMessage message = session.createTextMessage();
				message.setText("QueueProducerService发送消息:" + new Date());
				return message;
			}
		};
		jmsTemplate.send(this.testQueue, messageCreator);
		log.info("========向ActiveMq testQueue发送信息");
	}
	/**
	 * 发送并转换队列消息
	 */
	@Override
	public void convertAndSend() {
		Order order = new Order();
		order.setId(1);
		order.setAmount(150.62);
		order.setGoodsId(15);
		order.setGoodsAmount(2);
		order.setShopId(5656);
		jmsTemplate.convertAndSend(this.testQueue, order);  
	}
}


package com.activemq.service;

public interface QueueProducerService {
	public void send();
	public void convertAndSend();
}


队列消息消费者:

package com.activemq.service.imp;

import javax.annotation.Resource;
import javax.jms.JMSException;
import javax.jms.TextMessage;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.jms.core.JmsTemplate;
import org.springframework.stereotype.Service;

import com.activemq.service.QueueConsumerService;
import com.enity.Order;
/**
 * Queue消费
 * @author donald
 * @date 2016-12-27
 * @time 上午10:16:58
 */
@Service
public class QueueConsumerServiceImp implements QueueConsumerService{
	private static final Logger log = LoggerFactory.getLogger(QueueConsumerServiceImp.class);
	@Resource(name="jmsQueueTemplate")
	JmsTemplate jmsTemplate;
	/**
	 * 接受队列消息
	 */
	public String receive() {
		String result = null;
		TextMessage message = (TextMessage) jmsTemplate.receive();
		try {
			log.info("======QueueConsumerService收到消息:" + message.getText());
			result = message.getText();
		} catch (JMSException e) {
			e.printStackTrace();
		}
		return result;
	}
	/**
	 * 接受并转换队列消息
	 */
	@Override
	public Object receiveAndConvert() {
		Order order = (Order)jmsTemplate.receiveAndConvert();
		return order;
	}
}

package com.activemq.service;

public interface QueueConsumerService {
	public String receive();
	public Object receiveAndConvert();
}


订阅主题消息发布者:

package com.activemq.service.imp;


import javax.annotation.Resource;
import javax.jms.Destination;
import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.ObjectMessage;
import javax.jms.Session;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.jms.core.JmsTemplate;
import org.springframework.jms.core.MessageCreator;
import org.springframework.stereotype.Service;

import com.activemq.service.TopicPublisherService;
import com.enity.Order;

@Service
public class TopicPublisherServiceImp implements TopicPublisherService {
	private static final Logger log = LoggerFactory
			.getLogger(TopicPublisherServiceImp.class);
	@Resource(name = "jmsTopicTemplate")
	JmsTemplate jmsTemplate;
	@Resource(name = "testTopic")
	Destination testTopic;
    /**
     * 发送订阅主题消息
     */
	public void send() {
		MessageCreator messageCreator = new MessageCreator() {
			public Message createMessage(Session session) throws JMSException {
				ObjectMessage message = session.createObjectMessage();
				Order order = new Order();
				order.setId(1);
				order.setAmount(150.62);
				order.setGoodsId(15);
				order.setGoodsAmount(2);
				order.setShopId(5656);
				// 我们也可以将Object转换为Json String,作为TextMessage来传送,
				//在消费再反Json String 为Obejct
				message.setObject(order);
				return message;
			}
		};
		jmsTemplate.send(this.testTopic, messageCreator);
		log.info("========向ActiveMq testTopic发送订单信息");
	}
	/**
	 * 发送并转换订阅主题消息
	 */
	@Override
	public void convertAndSend() {
		Order order = new Order();
		order.setId(1);
		order.setAmount(150.62);
		order.setGoodsId(15);
		order.setGoodsAmount(2);
		order.setShopId(5656);
		jmsTemplate.convertAndSend(this.testTopic, order);  
	}
}

package com.activemq.service;

public interface TopicPublisherService {
	public void send();
	public void convertAndSend();
}



订阅主题消息订阅者:

package com.activemq.service.imp;

import javax.annotation.Resource;
import javax.jms.JMSException;
import javax.jms.ObjectMessage;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.jms.core.JmsTemplate;
import org.springframework.stereotype.Service;

import com.activemq.service.TopicSubscriberService;
import com.enity.Order;
@Service
public class TopicSubscriberServiceImp implements TopicSubscriberService{
	private static final Logger log = LoggerFactory.getLogger(TopicSubscriberServiceImp.class);
	@Resource(name="jmsTopicTemplate")
	JmsTemplate jmsTemplate;
	/**
	 * 接受订阅主题消息
	 */
	public Order receive() {
		ObjectMessage objMessage = (ObjectMessage) jmsTemplate.receive();
		Order order = null;
		try {
			order = (Order)objMessage.getObject();
			log.info("==========TopicSubscriberService收到订单信息:"+ order.toString());
		} catch (JMSException e) {
			e.printStackTrace();
		}
		return order;
	}
	/**
	 * 接受并转换订阅主题消息
	 */
	@Override
	public Object receiveAndConvert() {
		Order order = (Order)jmsTemplate.receiveAndConvert();
		return order;
	}
}

package com.activemq.service;

import com.enity.Order;

public interface TopicSubscriberService {
	public Order receive();
	public Object receiveAndConvert();
}



消息转化器:

package com.activemq.help;

import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.Session;
import javax.jms.TextMessage;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.jms.support.converter.MessageConversionException;
import org.springframework.jms.support.converter.MessageConverter;

import util.JsonUtil;

import com.enity.Order;
/**
 * 消息转换器
 * @author donald
 * @date 2016-12-27
 * @time 上午11:46:06
 */
public class MsgConverterHelper implements MessageConverter{
	private static final Logger log = LoggerFactory.getLogger(MsgConverterHelper.class);
	@Override
	public Object fromMessage(Message mess) throws JMSException,
			MessageConversionException {
		Order order  = null;
		if(!(mess instanceof TextMessage)) {  
            throw new MessageConversionException("Message is not TextMessage");  
        }  
		else{
			TextMessage tMess = (TextMessage)mess;
			order = JsonUtil.fromJson(tMess.getText(), Order.class);
			log.info("=====转换JSON字符串为订单信息=======");
		}
		return order;
	}

	@Override
	public Message toMessage(Object obj, Session session) throws JMSException,
			MessageConversionException {
		TextMessage textMessage = null;  
		 if (!(obj instanceof Order)) {  
	            throw new MessageConversionException("Object is not Order");  
	       }  
		 else {
			    textMessage = session.createTextMessage();  
			    Order order = (Order) obj;  
		        textMessage.setText(JsonUtil.toJson(order));  
		        log.info("=====转换订单信息为JSON字符串======");
		 }
		return textMessage;
	}  
  
   
}  


测试主类:
package com.controller;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import com.activemq.service.QueueConsumerService;
import com.activemq.service.QueueProducerService;
import com.activemq.service.TopicPublisherService;
import com.activemq.service.TopicSubscriberService;
import com.controller.base.BaseController;
import com.enity.Order;

import util.JsonUtil;

/**
 * 测试PTP&PUB/SUB
 * @author donald
 * @date 2016-12-27
 * @time 上午11:03:57
 */
@Controller
@RequestMapping(value="/activemq")
public class ActiveMqController extends BaseController{
	private static final Logger log = LoggerFactory.getLogger(ActiveMqController.class);
	@Autowired
	private QueueProducerService queueProducerService;
	@Autowired
	private QueueConsumerService queueConsumerService;
	@Autowired
	private TopicPublisherService topicPublisherService;
	@Autowired
	private TopicSubscriberService topicSubscriberService;
     
	/**
	 * 发送队列消息
	 * @return
	 */
	@RequestMapping("/qsend")
	@ResponseBody
	public String queueSend(){
		queueProducerService.send();
		return "queueProducerService send message ok!";
	}
	/**
	 * 接受队列消息
	 * @return
	 */
	@RequestMapping("/qrecevie")
	@ResponseBody
	public String queueRecevie(){
		String message = queueConsumerService.receive();
		return message;
	}
	/**
	 * 发送队列消息(消息转化器)
	 * @return
	 */
	@RequestMapping("/qsendConver")
	@ResponseBody
	public String queueSendConver(){
		queueProducerService.convertAndSend();
		return "queueProducerService convertAndSend message ok!";
	}
	/**
	 * 接受队列消息(消息转化器)
	 * @return
	 */
	@RequestMapping("/qrecevieConver")
	@ResponseBody
	public String queueRecevieConver(){
		Order order  = (Order) queueConsumerService.receiveAndConvert();
		return JsonUtil.toJson(order);
	}
	/**
	 * 发送订阅主题消息
	 * @return
	 */
	@RequestMapping("/tsend")
	@ResponseBody
	public String topicSend(){
		topicPublisherService.send();
		return "topicPublisherService send order info ok!";
	}
	/**
	 * 接受订阅主题的消息
	 * @return
	 */
	@RequestMapping("/trecevie")
	@ResponseBody
	public String topicRecevie(){
		Order order = topicSubscriberService.receive();
		return JsonUtil.toJson(order);
	}
	/**
	 * 发送订阅主题消息(消息转化器)
	 * @return
	 */
	@RequestMapping("/tsendConver")
	@ResponseBody
	public String topicSendConver(){
		topicPublisherService.convertAndSend();
		return "topicPublisherService convertAndSend order info ok!";
	}
	/**
	 * 接受订阅主题的消息(消息转化器)
	 * @return
	 */
	@RequestMapping("/trecevieConver")
	@ResponseBody
	public String topicRecevieConver(){
		Order order = (Order) topicSubscriberService.receiveAndConvert();
		return JsonUtil.toJson(order);
	}
}


package com.controller.base;

public abstract class BaseController {
  
}

启动应用测试,我们用RestClient测试:

访问http://localhost:8080/test/activemq/qsend

RestClient ReponseBody 显示:
queueProducerService send message ok!
控制台输出:
[ INFO] 2016-12-27 16:51:11  QueueProducerServiceImp:42 :========向ActiveMq testQueue发送信息

访问http://localhost:8080/test/activemq/qrecevie

RestClient ReponseBody 显示:
QueueProducerService发送消息:Tue Dec 27 16:51:11 CST 2016
控制台输出:
[ INFO] 2016-12-27 16:51:31  QueueConsumerServiceImp:32 :======QueueConsumerService收到消息:QueueProducerService发送消息:Tue Dec 27 16:51:11 CST 2016


访问http://localhost:8080/test/activemq/qsendConver

RestClient ReponseBody 显示:
queueProducerService convertAndSend message ok!
控制台输出:
[ INFO] 2016-12-27 16:53:50  MsgConverterHelper:50 :=====转换订单信息为JSON字符串======

访问http://localhost:8080/test/activemq/qrecevieConver

RestClient ReponseBody 显示:
{"id":1,"amount":150.62,"goodsId":15,"goodsAmount":2,"shopId":5656}
控制台输出:
[ INFO] 2016-12-27 16:55:42  MsgConverterHelper:34 :=====转换JSON字符串为订单信息=======

访问http://localhost:8080/test/activemq/tsend

RestClient ReponseBody 显示:
topicPublisherService send order info ok!
控制台输出:
[ INFO] 2016-12-27 16:56:46  TopicPublisherServiceImp:48 :========向ActiveMq testTopic发送订单信息

访问http://localhost:8080/test/activemq/trecevie

RestClient ReponseBody 显示:
{"id":1,"amount":150.62,"goodsId":15,"goodsAmount":2,"shopId":5656}
控制台输出:
[ INFO] 2016-12-27 16:58:30  TopicSubscriberServiceImp:27 :==========TopicSubscriberService收到订单信息:订单id:1,金额(元):150.62,商品id:5656,商品数量:2,店铺id:5656

访问http://localhost:8080/test/activemq/tsendConver

RestClient ReponseBody 显示:
topicPublisherService convertAndSend order info ok!
控制台输出:
[ INFO] 2016-12-27 17:06:37  MsgConverterHelper:50 :=====转换订单信息为JSON字符串======

访问http://localhost:8080/test/activemq/trecevieConver

RestClient ReponseBody 显示:
{"id":1,"amount":150.62,"goodsId":15,"goodsAmount":2,"shopId":5656}
控制台输出:
[ INFO] 2016-12-27 17:09:41  MsgConverterHelper:34 :=====转换JSON字符串为订单信息=======

上面的测试只能,进行手动接受队列和订阅主题消息,如何自动接受队列和订阅主题消息,这就要用到MessageListener、org.springframework.jms.listener.DefaultMessageListenerContainer,
实现MessageListener并配置DefaultMessageListenerContainer的消息监听器messageListener即可

2.消息监听器

队列消息监听器:

package com.activemq.listener;

import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.MessageListener;
import javax.jms.TextMessage;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Queue监听器
 * @author donald
 * @date 2016-12-27
 * @time 上午10:15:57
 */
public class QueueConsumerMessageListener implements MessageListener {
	private static final Logger log = LoggerFactory.getLogger(QueueConsumerMessageListener.class);
	public void onMessage(Message msg) {
		if (msg instanceof TextMessage) {
			TextMessage textMessage = (TextMessage) msg;
			try {
				log.info("--队列 MessageListener收到信息:"+ textMessage.getText());
			} catch (JMSException e) {
				e.printStackTrace();
			}
		}
	}
}


订阅主题消息监听器:


package com.activemq.listener;

import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.MessageListener;
import javax.jms.ObjectMessage;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.enity.Order;

/**
 * Topic 监听器
 * @author donald
 * @date 2016-12-27
 * @time 上午10:16:02
 */
public class TopicSubscriberMessageListener implements MessageListener {
	private static final Logger log = LoggerFactory.getLogger(TopicSubscriberMessageListener.class);
	public void onMessage(Message msg) {
		if (msg instanceof ObjectMessage) {
			ObjectMessage objMessage = (ObjectMessage) msg;
			try {
				Order order = (Order)objMessage.getObject();
				log.info("--订阅者 MessageListener收到订单信息:"+ order.toString());
			} catch (JMSException e) {
				e.printStackTrace();
			}
		}
	}
}


ActiveMQ配置文件activemq-context.xml:



           
          
              
              
               
          
          
        
          
          
              
              
          
          
          
              
              
            
             
              
        	  
          
          
         
          
              
              
              
              
          
          
          
              
              
          
          
          
              
              
              
              
            
             
              
        	  
          
        
          
          
              
              
              
              
              
          
			


启动应用,测试消息监听器:

访问http://localhost:8080/test/activemq/tsend

RestClient ReponseBody 显示:
topicPublisherService send order info ok!
控制台输出:
[ INFO] 2016-12-27 17:20:25  TopicSubscriberMessageListener:26 :--订阅者 MessageListener收到订单信息:订单id:1,金额(元):150.62,商品id:5656,商品数量:2,店铺id:5656
[ INFO] 2016-12-27 17:20:25  TopicPublisherServiceImp:48 :========向ActiveMq testTopic发送订单信息

访问http://localhost:8080/test/activemq/qsend

RestClient ReponseBody 显示:
queueProducerService send message ok!
控制台输出:
[ INFO] 2016-12-27 16:51:11  QueueProducerServiceImp:42 :========向ActiveMq testQueue发送信息
[ INFO] 2016-12-27 17:20:41  QueueConsumerMessageListener:23 :--队列 MessageListener收到信息:QueueProducerService发送消息:Tue Dec 27 17:20:41 CST 2016
[ INFO] 2016-12-27 17:20:41  QueueProducerServiceImp:42 :========向ActiveMq testQueue发送信息
  • Spring与ActiveMQ的集成_第2张图片
  • 大小: 35.5 KB
  • 查看图片附件

你可能感兴趣的:(activemq,spring)