在前面的几篇博客里面已经把RabbitMQ的一些理论详细了说明了,在这一篇中将记录下Spring整合RabbitMQ,本文只是简单一个整合介绍,属于抛砖引玉,具体实现还需大家深入研究哈..
代码我会上传到我的码云上,如需下载请在文章的末尾寻找下载地址
1、POM引入
com.rabbitmq
amqp-client
3.5.1
org.springframework.amqp
spring-rabbit
1.4.5.RELEASE
2、RabbitMQ配置信息
添加rabbitmq.properties配置文件
rabbit.hosts=127.0.0.1
rabbit.username=hrabbit
rabbit.password=123
rabbit.port=5672
rabbit.virtualHost=/hrabbit
# 统一XML配置中易变部分的命名
rabbit.queue=rabbitmq_test
3、添加FastJson转化类
spring amqp默认的是jackson 的一个插件,目的将生产者生产的数据转换为json存入消息队列,由于fastjson的速度快于jackson,这里替换为fastjson的一个实现
package www.hrabbit.cn.configer;
import com.alibaba.fastjson.JSON;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.core.MessageProperties;
import org.springframework.amqp.support.converter.*;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
/**
* @Auther: hrabbit
* @Date: 2018-07-02 下午6:35
* @Description:
*/
public class FastJsonMessageConverter extends AbstractJsonMessageConverter {
private static Log log = LogFactory.getLog(FastJsonMessageConverter.class);
private static ClassMapper classMapper = new DefaultClassMapper();
public FastJsonMessageConverter() {
super();
}
@Override
protected Message createMessage(Object object, MessageProperties messageProperties) {
byte[] bytes = null;
try {
String jsonString = JSON.toJSONString(object);
bytes = jsonString.getBytes(getDefaultCharset());
} catch (IOException e) {
throw new MessageConversionException("Failed to convert Message content", e);
}
messageProperties.setContentType(MessageProperties.CONTENT_TYPE_JSON);
messageProperties.setContentEncoding(getDefaultCharset());
if (bytes != null) {
messageProperties.setContentLength(bytes.length);
}
classMapper.fromClass(object.getClass(), messageProperties);
return new Message(bytes, messageProperties);
}
@Override
public Object fromMessage(Message message) throws MessageConversionException {
Object content = null;
MessageProperties properties = message.getMessageProperties();
if (properties != null) {
String contentType = properties.getContentType();
if (contentType != null && contentType.contains("json")) {
String encoding = properties.getContentEncoding();
if (encoding == null) {
encoding = getDefaultCharset();
}
try {
Class> targetClass = getClassMapper().toClass(message.getMessageProperties());
content = convertBytesToObject(message.getBody(), encoding, targetClass);
} catch (IOException e) {
throw new MessageConversionException("Failed to convert Message content", e);
}
} else {
log.warn("Could not convert incoming message with content-type [" + contentType + "]");
}
}
if (content == null) {
content = message.getBody();
}
return content;
}
private Object convertBytesToObject(byte[] body, String encoding, Class> clazz)
throws UnsupportedEncodingException {
String contentAsString = new String(body, encoding);
return JSON.parseObject(contentAsString, clazz);
}
}
4、添加amqp-application.xml
rabbitmq 连接服务配置
在这个项目中我的生产者和消费者是放到同一个项目中的。项目中的监听器,即为消费者。
5、生产者
注入AmqpTemplate
模板,调用convertAndSend ();
方法添加消息;
package www.hrabbit.cn.rabbitMq.service.impl;
import org.springframework.amqp.core.AmqpTemplate;
import org.springframework.stereotype.Service;
import www.hrabbit.cn.rabbitMq.service.SpittleService;
import javax.annotation.Resource;
import java.util.LinkedHashMap;
import java.util.Map;
/**
* @Auther: hrabbit
* @Date: 2018-07-02 下午4:26
* @Description:
*/
@Service("spittleService")
public class SpittleServiceImpl implements SpittleService {
@Resource
private AmqpTemplate amqpTemplate;
/**
* 生产消息
* @return
*/
public Map spittleMsg(){
Map dataList = new LinkedHashMap<>();
for (int i=0;i<10;i++){
dataList.put("order","msgResult:"+i);
amqpTemplate.convertAndSend("order","msgResult:"+i);
}
return dataList;
}
}
6、添加监听器(即消费者)
package www.hrabbit.cn.rabbitMq.listener;
import com.rabbitmq.client.Channel;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.core.ChannelAwareMessageListener;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import java.io.IOException;
/**
* @Auther: hrabbit
* @Date: 2018-07-02 下午4:47
* @Description:
*/
@Component
public class MessageListener implements ChannelAwareMessageListener {
private Logger logger= LoggerFactory.getLogger(MessageListener.class);
@Transactional
@Override
public void onMessage(Message message, Channel channel) throws Exception {
//业务处理,放到action层,并返回处理成功还是异常的flag
//boolean mqFlag=rabbitMaConsumerTaskAction.saveMq(arg0);
//还有一个点就是如何获取mq消息的报文部分message?
String result=new String(message.getBody(),"UTF-8");
System.out.println("消息:"+result);
if(true){
basicACK(message,channel);//处理正常--ack
}else{
basicNACK(message,channel);//处理异常--nack
}
}
//正常消费掉后通知mq服务器移除此条mq
private void basicACK(Message message,Channel channel){
try{
channel.basicAck(message.getMessageProperties().getDeliveryTag(),false);
}catch(IOException e){
logger.error("通知服务器移除mq时异常,异常信息:"+e);
}
}
//处理异常,mq重回队列
private void basicNACK(Message message,Channel channel) {
try {
channel.basicNack(message.getMessageProperties().getDeliveryTag(), false, true);
} catch (IOException e) {
logger.error("mq重新进入服务器时出现异常,异常信息:" + e);
}
}
}
7、启动项目,测试
访问地址:http://localhost:8080/amqp/spittleMsg
生产了10条消息,此时查看控制台10条消息都被消费了!
项目地址:https://gitee.com/hrabbit/spring-rabbitMQ
系列文章:
RabbitMQ:RabbitMQ-理论基础
RabbitMQ:RabbitMQ:快速入门hello word
RabbitMQ:RabbitMQ:work queues 工作队列(Round-robin/Fair dispatch)
RabbitMQ:RabbitMQ:消息应答与消息持久化
RabbitMQ:发布/订阅 Publish/Subscribe
RabbitMQ:路由Routing
RabbitMQ:Topic类型的exchange
RabbitMQ:RabbitMQ之消息确认机制(事务+Confirm)