RabbitMq 结合Spring

背景:前期再学习RabbitMq时,只是基于main方法的形式进行学习,但是实际中使用是结合spring 或者是spring boot的,所以就搜索博客查看RabbitMq和Spring的整合方式,开始摸着石头过河,估计是运气不好,找了好多demo都是有bug,或者项目报错,基于看了好多博客,spring配置文件配置的方式大致相同,于是开始边摸索边参考一些文档敲出一下demo;以下demo经测试可以正常运行,直接上代码;

spirng-mq.xml配置文件

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns:rabbit="http://www.springframework.org/schema/rabbit"
	 xsi:schemaLocation="http://www.springframework.org/schema/beans
			http://www.springframework.org/schema/beans/spring-beans-4.1.xsd
			http://www.springframework.org/schema/rabbit
			http://www.springframework.org/schema/rabbit/spring-rabbit-1.0.xsd
			">

	<!-- 加载配置文件 -->
	<rabbit:connection-factory id="connectionFactory"
							   username="root"
							   password="root"
								virtual-host="/"
							   host="localhost"
							   port="5672"
							   />
    <!--定义mq管理-->
	<rabbit:admin connection-factory="connectionFactory"/>

	<!--声明队列-->
	<rabbit:queue name="queue_one" durable="true"/>
	<rabbit:queue name="queue_two" durable="true"/>

	<!--定义交换机绑定队列-->
	<rabbit:direct-exchange name="IExchange" id="IExchange">
		<rabbit:bindings>
			<rabbit:binding queue="queue_one" key="queue_one_key"></rabbit:binding>
			<rabbit:binding queue="queue_two" key="queue_two_key"></rabbit:binding>
		</rabbit:bindings>
	</rabbit:direct-exchange>

	<!--消息对象转json类-->
	<bean id="jsonMessageConverter" class="com.hsnn.medstgmini.drug.rabbitmq.FastJsonMessageConverter"/>

	<!--定义模板-->
	<rabbit:template id="rabbitTemplate" connection-factory="connectionFactory" exchange="IExchange" message-converter="jsonMessageConverter"/>

	<!--定义消费者-->
	<bean name="Consume1Handler" class="com.hsnn.medstgmini.drug.rabbitmq.Consume1Handler"/>
	<bean name="Consume2Handler" class="com.hsnn.medstgmini.drug.rabbitmq.Consume2Handler"/>

	<!--消费者监听队列-->
	<rabbit:listener-container
		connection-factory="connectionFactory">
		<rabbit:listener ref="Consume1Handler" queues="queue_one"/>
		<rabbit:listener ref="Consume2Handler"  queues="queue_two"/>
 	</rabbit:listener-container>
		

</beans>

消息对象转json类默认采用的fackjson,但是考虑到效率问题,修改成FastJson进行对象json转换操作,class类内容如下;

package com.hsnn.medstgmini.drug.rabbitmq;

import java.io.UnsupportedEncodingException;

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.AbstractMessageConverter;
import org.springframework.amqp.support.converter.MessageConversionException;

import com.alibaba.fastjson.JSONObject;

public class FastJsonMessageConverter extends AbstractMessageConverter {

    @SuppressWarnings("unused")
    private static Log log = LogFactory.getLog(FastJsonMessageConverter.class);

    public static final String DEFAULT_CHARSET = "UTF-8";

    private volatile String defaultCharset = DEFAULT_CHARSET;

    public FastJsonMessageConverter() {
        super();
    }

    public void setDefaultCharset(String defaultCharset) {
        this.defaultCharset = (defaultCharset != null) ? defaultCharset
                : DEFAULT_CHARSET;
    }

    public Object fromMessage(Message message)
            throws MessageConversionException {
        Object o = new CommonMessage();
        try{
            o = fromMessage(message, new CommonMessage());
        }catch(Exception e){
            log.error("queue message error : " + message);
            e.printStackTrace();
        }
        return o;
    }

    @SuppressWarnings("unchecked")
    public <T> T fromMessage(Message message, T t) {
        String json = "";
        try {
            json = new String(message.getBody(), defaultCharset);
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        return (T) JSONObject.parseObject(json, t.getClass());
    }

    protected Message createMessage(Object objectToConvert,
                                    MessageProperties messageProperties)
            throws MessageConversionException {
        byte[] bytes = null;
        try {
            String jsonString = JSONObject.toJSONString(objectToConvert);
            bytes = jsonString.getBytes(this.defaultCharset);
        } catch (UnsupportedEncodingException e) {
            throw new MessageConversionException(
                    "Failed to convert Message content", e);
        }
        messageProperties.setContentType(MessageProperties.CONTENT_TYPE_JSON);
        messageProperties.setContentEncoding(this.defaultCharset);
        if (bytes != null) {
            messageProperties.setContentLength(bytes.length);
        }
        return new Message(bytes, messageProperties);

    }
}

message 消息模型类如下:

package com.hsnn.medstgmini.drug.rabbitmq;
 
import org.apache.commons.lang.builder.ToStringBuilder;
import org.apache.commons.lang.builder.ToStringStyle;
 
/**
 * 消息模型
 *
 */
public class CommonMessage {
	/**
	 * 约定的几个消息源名称
	 */
	private String source;
	/**
	 * 实体表名
	 */
	private String table;
	/**
	 * 主键
	 */
	private String primaryKey;
	/**
	 * 消息实体bean
	 */
	private Object message;
 
	public String getSource() {
		return source;
	}
 
	public void setSource(String source) {
		this.source = source;
	}
 
	public String getTable() {
		return table;
	}
 
	public void setTable(String table) {
		this.table = table;
	}
 
 
	public String getPrimaryKey() {
		return primaryKey;
	}
 
	public void setPrimaryKey(String primaryKey) {
		this.primaryKey = primaryKey;
	}
 
	public Object getMessage() {
		return message;
	}
 
	public void setMessage(Object message) {
		this.message = message;
	}
 
	@Override
	public String toString() {
		return ToStringBuilder.reflectionToString(this,
				ToStringStyle.DEFAULT_STYLE);
	}
	
}

定义两个消费者:进行消费

package com.hsnn.medstgmini.drug.rabbitmq;

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.core.MessageListener;

import java.io.IOException;

/*
*消费者1
*
*/
public class Consume1Handler implements MessageListener {
    private static final ObjectMapper mapper = new ObjectMapper();

    @Override
    public void onMessage(Message message) {
        try {
            JsonNode jsonNode =mapper.readTree(message.getBody());
            System.out.println(jsonNode.get("id").asText()+":"+jsonNode.get("name").asText());
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
package com.hsnn.medstgmini.drug.rabbitmq;

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.core.MessageListener;

import java.io.IOException;
/*
*消费者2
*/
public class Consume2Handler implements MessageListener {
    private static final ObjectMapper mapper = new ObjectMapper();

    @Override
    public void onMessage(Message message) {
        try {
            JsonNode jsonNode =mapper.readTree(message.getBody());
            System.out.println(jsonNode.get("id").asText()+":"+jsonNode.get("name").asText());
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

测试类:

  @RequestMapping("toCheckList")
    public String toCheckList() {
        Map map = new HashMap();
        map.put("id","001");
        map.put("name","酒鬼");
        rabbitTemplate.convertAndSend("queue_one_key",map);

        map.put("id","002");
        map.put("name","撕家");
        rabbitTemplate.convertAndSend("queue_two_key",map);
        return MODEL_PATH + "checkList";

    }

项目启动后,访问相应路径,会在控制台打印:

001:酒鬼

002:撕家

到这里配置就结束了,但是在配置过程中也踩过了一些坑,这里也贴出来,共勉

遇到的坑:启动过程中出现报错,错误信息如下:

org.springframework.amqp.AmqpIOException: java.io.IOException
	at org.springframework.amqp.rabbit.support.RabbitExceptionTranslator.convertRabbitAccessException(RabbitExceptionTranslator.java:65)
	at org.springframework.amqp.rabbit.connection.AbstractConnectionFactory.createBareConnection(AbstractConnectionFactory.java:218)

遇到问题后百度吗,但是结果都不是我想要的,百度的结果都是RabbitMq权限问题,只需要登录RabbitMq进行重置权限,如下

但是我重置后还是报错,然后开始排查问题,去RabbitMq官网查看,发现是连接时端口号配置错误导致的异常,RabbitMq的端口号信息如下:

4369 -- erlang发现口

5672 --client端通信口   --RabbitMq cliean连接端口号,及spring 配置中连接的prot值

15672 -- 管理界面ui端口  --RabbitMq管理访问端口

25672 -- server间内部通信口

猜你喜欢

转载自blog.csdn.net/qq_34125349/article/details/83548092