Spring集成RabbitMQ消息队列

准备工作:需要有一个RabbitMQ服务,如果是本地电脑,自行上官网下载并安装RabbitMQ软件,在rabbitmq安装之前,童鞋们需要安装erlang,因为rabbitmq是用erlang写的。

1. maven配置

除了spring常用的基础包外,我们还需要下面这个包

<!--rabbitmq依赖 -->
<dependency>
	<groupId>org.springframework.amqp</groupId>
	<artifactId>spring-rabbit</artifactId>
	<version>1.3.5.RELEASE</version>
</dependency>
2. 创建几个生产者和消费者类

jar包加上去下载好之后我们可以进行下一步,创建几个类

  1. 消息生产者类
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.amqp.core.AmqpTemplate;
import org.springframework.stereotype.Service;
 
import javax.annotation.Resource;
import java.io.IOException;
 
/**
 * 消息生产者
 */
@Service
public class TestRabbitMQProducer {
 
    private Logger logger = LoggerFactory.getLogger(TestRabbitMQProducer.class);
 
    @Resource(name="amqpTemplate")
    private AmqpTemplate amqpTemplate;

 
    public void sendMessage(Object message) throws IOException {
        logger.info("to send message:{}", message);
        //下面这句是发送一条数据到对应队列,key是配置文件中exchange中配置的对应key
        amqpTemplate.convertAndSend("LeaveQueueKey", message);
        amqpTemplate.convertAndSend("UserinfoQueueKey", message);
    }
}
  1. 消费者一
    消费者一:处理用户信息
package cn.leave.task;
import java.io.ByteArrayInputStream;
import java.io.ObjectInputStream;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.core.MessageListener;

import cn.leave.weixinentity.UserInfo;
 
/**
 * 消息消费者一
 */
public class UserInfoMessageConsumer implements MessageListener {
 
    private Logger logger = LoggerFactory.getLogger(UserInfoMessageConsumer.class);
    /**
     * 实现MessageListener的消息接收接口
     */
    @Override
    public void onMessage(Message message, Channel channel) {
        logger.info("消费者接受消息 message------->:{}", message);
        try {
        	//消息转换为对象
	        UserInfo userInfo=(UserInfo) getObjectFromBytes(message.getBody());
	        //TODO 使用对象,加入业务逻辑
			......
			//完成任务 反馈给RabbitMQ,从队列删除
			channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);
        }
        catch (Exception e) {
	        // TODO Auto-generated catch block
	        e.printStackTrace();
        }
    }
    /**
     * //字节码转化为对象(反序列化)
     * @param objBytes
     * @return
     * @throws Exception
     */
    
    public  Object getObjectFromBytes(byte[] objBytes) throws Exception {
        if (objBytes == null || objBytes.length == 0) {
            return null;
        }
        ByteArrayInputStream bi = new ByteArrayInputStream(objBytes);
        ObjectInputStream oi = new ObjectInputStream(bi);
        return oi.readObject();
    }
}
  1. 消费者二
    消费者二:处理假单信息
package cn.leave.task;
import java.io.ByteArrayInputStream;
import java.io.ObjectInputStream;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.core.MessageListener;

import cn.leave.entity.Leave;
 
/**
 * 消息消费者一
 */
public class LeaveMessageConsumer implements MessageListener {
 
    private Logger logger = LoggerFactory.getLogger(LeaveMessageConsumer.class);
    /**
     * 实现MessageListener的消息接收接口
     */
    @Override
    public void onMessage(Message message, Channel channel) {
        logger.info("消费者接受消息 message------->:{}", message);
        try {
        	//消息转换为对象
	        Leave leave=(Leave) getObjectFromBytes(message.getBody());
	        //TODO 使用对象,此处加入业务逻辑....
			......
			//完成任务 反馈给RabbitMQ,从队列删除
			channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);
        }
        catch (Exception e) {
	        // TODO Auto-generated catch block
	        e.printStackTrace();
        }
    }
    /**
     * //字节码转化为对象(反序列化)
     * @param objBytes
     * @return
     * @throws Exception
     */
    
    public  Object getObjectFromBytes(byte[] objBytes) throws Exception {
        if (objBytes == null || objBytes.length == 0) {
            return null;
        }
        ByteArrayInputStream bi = new ByteArrayInputStream(objBytes);
        ObjectInputStream oi = new ObjectInputStream(bi);
        return oi.readObject();
    }
}
3.创建配置文件

下面就是spring中配置RabbitMQ,我这单独写在了一个配置文件中

<?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.xsd
		  http://www.springframework.org/schema/context 
		  http://www.springframework.org/schema/context/spring-context.xsd
          http://www.springframework.org/schema/rabbit
          http://www.springframework.org/schema/rabbit/spring-rabbit-1.3.xsd">
	<!--1、创建工厂连接 -->
	<rabbit:connection-factory id="rabbitConnectionFactory" 
	   username="guest" password="guest" host="127.0.0.1" port="5672" />
	<!--定义rabbit template用于数据的接收和发送 -->
	<rabbit:template id="amqpTemplate" connection-factory="rabbitConnectionFactory" exchange="exchangeConfirmLeave" />
	<!--通过指定下面的admin信息,当前producer中的exchange和queue会在rabbitmq服务器上自动生成 -->
	<rabbit:admin connection-factory="rabbitConnectionFactory" />
	<!--定义queue  这里的name会在RabbitMQ服务那边创建对应名字的队列 -->
	<rabbit:queue name="LeaveQueue" durable="true" auto-delete="false" exclusive="false" />
	<rabbit:queue name="UserinfoQueue" durable="true" auto-delete="false" exclusive="false" />

	<!-- 定义direct exchange,绑定queueTest -->
	<rabbit:direct-exchange name="exchangeConfirmLeave" durable="true" auto-delete="false">
		<rabbit:bindings>
			<!--这里可以放多个dinding-->
			<!-- queue 是上面"定义queue"  key是发送消息时使用的key-->
			<rabbit:binding queue="LeaveQueue" key="LeaveQueueKey">
			</rabbit:binding>
			<rabbit:binding queue="UserinfoQueue" key="UserinfoQueueKey">
			</rabbit:binding>

		</rabbit:bindings>

	</rabbit:direct-exchange>

	<!-- 加载消息接收者 前面声明的监听器类-->
	<bean id="leaveMessageConsumer" class="cn.leave.task.LeaveMessageConsumer"></bean>
	<bean id="userInfoMessageConsumer" class="cn.leave.task.UserInfoMessageConsumer"></bean>

	<!-- queue litener 观察 监听模式 当有消息到达时会通知监听在对应的队列上的监听对象 -->
	<!-- acknowledge="manual" 为了保证数据不被丢失,RabbitMQ支持消息确认机制,即ack。为了保证数据能被正确处理而不仅仅是被Consumer收到, -->
	<rabbit:listener-container
		connection-factory="rabbitConnectionFactory" acknowledge="manual"
		prefetch="10">
		<!--定义监听器 这里可以放多个监听器
		 queues:监听的队列 多个可以","隔开;ref:监听器在spring中的引用 -->
		<rabbit:listener queues="LeaveQueue" ref="leaveMessageConsumer" />
		<rabbit:listener queues="UserinfoQueue" ref="userInfoMessageConsumer" />
	</rabbit:listener-container>
</beans>

下面一段一段解释一下

  1. connect-factory 管理 rabbitmq服务 的连接,这个参数不再解释
	<!--1、创建工厂连接 -->
	<rabbit:connection-factory id="rabbitConnectionFactory" 
	   username="guest" password="guest" host="127.0.0.1" port="5672" />
  1. rabbit:template 类似于mysql中的template ,对队列进行一些操作,如加入消息到队列
    connection-factory:使用的连接工厂
    exchange:使用的交换机
<!--定义rabbit template用于数据的接收和发送 -->
	<rabbit:template id="amqpTemplate" connection-factory="rabbitConnectionFactory" exchange="exchangeConfirmLeave" />
  1. exchange 交换机,用来控制消息发送到哪个队列
    direct-exchange:直连交换机,全名匹配
    durable:是否持久化
    auto_delete: 当所有消费客户端连接断开后,是否自动删除队列
    rabbit:binding:设置消息queue匹配的key,绑定其关系
<!-- 定义direct exchange,绑定queueTest -->
	<rabbit:direct-exchange name="exchangeConfirmLeave" durable="true" auto-delete="false">
		<rabbit:bindings>
			<!--这里可以放多个dinding-->
			<!-- queue 是上面"定义queue"  key是发送消息时使用的key-->
			<rabbit:binding queue="LeaveQueue" key="LeaveQueueKey"> </rabbit:binding>
			<rabbit:binding queue="UserinfoQueue" key="UserinfoQueueKey"> </rabbit:binding>
		</rabbit:bindings>
	</rabbit:direct-exchange>
  1. rabbit:queue 定义队列
    durable:是否持久化
    exclusive: 仅创建者可以使用的私有队列,断开后自动删除
    auto_delete: 当所有消费客户端连接断开后,是否自动删除队列
<!--定义queue  这里的name会在RabbitMQ服务那边创建对应名字的队列 -->
	<rabbit:queue name="LeaveQueue" durable="true" auto-delete="false" exclusive="false" />
	<rabbit:queue name="UserinfoQueue" durable="true" auto-delete="false" exclusive="false" />
  1. rabbit:admin通过指定下面的admin信息,当前producer中的exchange和queue会在rabbitmq服务器上自动生成
	<!--通过指定下面的admin信息,当前producer中的exchange和queue会在rabbitmq服务器上自动生成 -->
	<rabbit:admin connection-factory="rabbitConnectionFactory" />
  1. 配置监听器
	<!-- queue litener 观察 监听模式 当有消息到达时会通知监听在对应的队列上的监听对象 -->
	<!-- acknowledge="manual" 为了保证数据不被丢失,RabbitMQ支持消息确认机制,即ack。为了保证数据能被正确处理而不仅仅是被Consumer收到, -->
	<rabbit:listener-container
		connection-factory="rabbitConnectionFactory" acknowledge="manual"
		prefetch="10">
		<!--定义监听器 这里可以放多个监听器
		 queues:监听的队列 多个可以","隔开;ref:监听器在spring中的引用 -->
		<rabbit:listener queues="LeaveQueue" ref="leaveMessageConsumer" />
		<rabbit:listener queues="UserinfoQueue" ref="userInfoMessageConsumer" />
	</rabbit:listener-container>

剩下的spring基础配置就不放到这了,下面是一些名词的解释
connect-factory进行连接rabbitmq服务.

template用于连接factory并指定exchange, 这上面还能直接指定rout-key.

admin相当于一个管理员的角色…可以将exchange和queue进行管理,

queue和topic-exchange分别定义队列和路由器, 这里需要用declared-by指定管理员,从而连接到相应的factory.

listener-container用于消费者的监听,rabbit配置中是可以指定某个类的某个方法的,如下

<rabbit:listener-container message-converter="jackson2JsonMessageConverter">
     <rabbit:listener queue-names="RESPONSE_QUEUE1, RESPONSE_QUEUE2, RESPONSE_QUEUE3, RESPONSE_QUEUE4, RESPONSE_QUEUE5"
                      ref="responseMapConsumer" method="listenResponseMap"/>
 </rabbit:listener-container>

到此配置完成,启动项目,执行一下生产者的sendMessage()方法就可以把消息发送给RabbitMQ,然后监听器监听到消息就可以执行onMessage方法接受消息了

扫描二维码关注公众号,回复: 10558004 查看本文章
发布了8 篇原创文章 · 获赞 11 · 访问量 6405

猜你喜欢

转载自blog.csdn.net/u011783999/article/details/103053313