RabbitMQ系列教程(十四)Spring Boot整合RabbitMQ

本文详细介绍如何在SpringBoot项目中整合RabbitMQ,包括构建消息生产者与消费者,配置消息确认与返回机制,实现消息的JSON序列化与反序列化。

1.构建消息生产者

  • 创建一个Spring Boot消息生产者(mqproducer)项目,在POM文件中引入依赖
<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>2.2.1.RELEASE</version>
		<relativePath/> <!-- lookup parent from repository -->
	</parent>
	<properties>
		<java.version>1.8</java.version>
	</properties>

	<dependencies>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-amqp</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>

		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-test</artifactId>
			<scope>test</scope>
			<exclusions>
				<exclusion>
					<groupId>org.junit.vintage</groupId>
					<artifactId>junit-vintage-engine</artifactId>
				</exclusion>
			</exclusions>
		</dependency>
		<dependency>
			<groupId>org.springframework.amqp</groupId>
			<artifactId>spring-rabbit-test</artifactId>
			<scope>test</scope>
		</dependency>
	</dependencies>
  • 配置RabbitMQ服务相关信息
spring.rabbitmq.host=127.0.0.1
spring.rabbitmq.port=5672
spring.rabbitmq.username=guest
spring.rabbitmq.password=guest
spring.rabbitmq.connection-timeout=5000
spring.rabbitmq.virtual-host=/
#消息confirm确认
spring.rabbitmq.publisher-confirm-type=correlated
# return消息
spring.rabbitmq.publisher-returns=true
#当mandatory标志位设置为true时,如果exchange根据自身类型和消息routingKey无法找到一个合适的queue存储消息,那么broker会调用basic.return方法将消息返还给生产者
# 如果为false,则直接丢弃消息
spring.rabbitmq.template.mandatory=true

配置说明:

  • spring.rabbitmq.template.mandatory 设置为true时,如果exchange根据自身类型和消息routingKey无法找到一个合适的queue存储消息,那么broker会调用basic.return方法将消息返还给生产者。为false,则直接丢弃消息
  • spring.rabbitmq.publisher-confirm-type 在最新版本的Spring Boot AMQP中 spring.rabbitmq.publisher-confirms 已被此属性取代,表示是否开启消息的Confirm

2.构建消息消费者

  • 创建一个Spring Boot消息消费者(mqconsumer)项目,POM文件与消息生产者一样。
  • 配置RabbitMQ服务相关信息
spring.rabbitmq.host=127.0.0.1
spring.rabbitmq.port=5672
spring.rabbitmq.username=guest
spring.rabbitmq.password=guest
spring.rabbitmq.connection-timeout=5000
spring.rabbitmq.virtual-host=/

#消息确认模式 手工模式
spring.rabbitmq.listener.simple.acknowledge-mode=manual
# 初始化链接
spring.rabbitmq.listener.simple.concurrency=5
# 最大链接
spring.rabbitmq.listener.simple.max-concurrency=10


#限流,同一时间只有一条消息消费
spring.rabbitmq.listener.simple.prefetch=1

3.消息发送与监听

3.1.消息生产者

  • RabbitTemplate 发送消息,并设置消息的Confirm与Return
@Component
public class RabbitMQSender {

    @Autowired
    private RabbitTemplate rabbitTemplate;


    //回调函数: confirm确认
    final ConfirmCallback confirmCallback = new RabbitTemplate.ConfirmCallback() {
        @Override
        public void confirm(CorrelationData correlationData, boolean ack, String cause) {
            System.err.println("correlationData: " + correlationData.getId());
            System.err.println("ack: " + ack);
            if(!ack){
                System.err.println("异常处理....");
            }
        }
    };

    //回调函数: return返回
    final RabbitTemplate.ReturnCallback returnCallback = new RabbitTemplate.ReturnCallback() {
        @Override
        public void returnedMessage(org.springframework.amqp.core.Message message, int replyCode, String replyText,
                                    String exchange, String routingKey) {
            System.err.println("return exchange: " + exchange + ", routingKey: "
                    + routingKey + ", replyCode: " + replyCode + ", replyText: " + replyText);
        }
    };

    /**
     * @param exchangeName
     * @param routeKey
     * @param contents
     * @param properties
     */
    public void sendMessage(String exchangeName,String routeKey,Object contents, Map<String, Object> properties){
        MessageHeaders headers=new MessageHeaders(properties);
        Message message= MessageBuilder.createMessage(contents,headers);
        rabbitTemplate.setConfirmCallback(confirmCallback);
        rabbitTemplate.setReturnCallback(returnCallback);
        //消息唯一性
        CorrelationData correlationData = new CorrelationData();
        correlationData.setId(UUID.randomUUID().toString());
        rabbitTemplate.convertAndSend(exchangeName,routeKey,message,correlationData);
    }
}

3.2.消息消费者

@RabbitListener 注解可以声明队列、交换机以及绑定订单与与交换机。当收到消息的时候,就交给 @RabbitHandler 的方法处理。

@Component
public class ConsumberReceiver {
    @RabbitListener(bindings = @QueueBinding(
            value = @Queue(value = "queue-springboot-test",
                    durable="true"),
            exchange = @Exchange(value = "springboot_exchange_test",
                    durable="true",
                    type= "topic",
                    ignoreDeclarationExceptions = "true"),
            key = "springboot.test"
    ))
    @RabbitHandler
    public void onMessage(Message message, Channel channel) throws Exception {
        MessageHeaders messageHeaders=message.getHeaders();
        System.err.println("--------------------------------------");
        System.err.println("消费端接收到的消息: " + message.getPayload());
        Long deliveryTag = (Long)message.getHeaders().get(AmqpHeaders.DELIVERY_TAG);
        //手工ACK
        channel.basicAck(deliveryTag, false);
    }
}

说明:
@RabbitListener->bindings->@Exchange的type属性值有direct、topic、fanout、headers ,也是RabbitMQ支持的四种交换机类型。

4.Message 内容的JSON序列化与反序列化

创建一个Order实体类

public class Order implements Serializable{

    private Integer id;

    private String orderNum;

    private String title;

    private String desc;

    public Order() {
    }

    public Order(Integer id, String orderNum, String title, String desc) {
        this.id = id;
        this.orderNum = orderNum;
        this.title = title;
        this.desc = desc;
    }
-------------------------省略get set---------------------

4.1.消费者MessageConverter配置

RabbitMQ 提供了 Jackson2JsonMessageConverter 来支持消息内容 JSON 序列化与反序列化,消息消费者配置 MessageConverterJackson2JsonMessageConverter

@Configuration
public class RabbitMQConfig {

    @Bean
    public RabbitListenerContainerFactory<?> rabbitListenerContainerFactory(ConnectionFactory connectionFactory){
        SimpleRabbitListenerContainerFactory factory = new SimpleRabbitListenerContainerFactory();
        factory.setConnectionFactory(connectionFactory);
        Jackson2JsonMessageConverter jackson2JsonMessageConverter = new Jackson2JsonMessageConverter();
        DefaultJackson2JavaTypeMapper javaTypeMapper=new DefaultJackson2JavaTypeMapper();
        //添加信任包名称,不然会转化失败 
        javaTypeMapper.setTrustedPackages("com.warybee.mqconsumer.entity");
        jackson2JsonMessageConverter.setJavaTypeMapper(javaTypeMapper);
        factory.setMessageConverter(jackson2JsonMessageConverter);
        return factory;
    }
}

说明:

  • javaTypeMapper.setTrustedPackages(...) 默认只支持java.utiljava.lang 包下的类的反序列化,这里需要添加我们需要反序列实体所在的package

消息监听代码:

@RabbitListener(bindings = @QueueBinding(
            value = @Queue(value = "queue-springboot-test",
                    durable="true"),
            exchange = @Exchange(value = "springboot_exchange_test",
                    durable="true",
                    type= "topic",
                    ignoreDeclarationExceptions = "true"),
            key = "springboot.save"
    ))
    @RabbitHandler
    public void onMessage(Order order, Channel channel,
                          @Headers Map<String, Object> headers) throws IOException {
        System.out.println("接收的消息-订单号::"+order.getDesc());
        System.out.println("接收的消息-标题::"+order.getTitle());
        Long deliveryTag = (Long)headers.get(AmqpHeaders.DELIVERY_TAG);
        //手工应答
        channel.basicAck(deliveryTag,false);
    }

4.2.生产者MessageConverter配置

消息生产者也应配置 MessageConverterJackson2JsonMessageConverter

/**
     * String类型参数
     * @param exchangeName
     * @param routeKey
     * @param properties
     */
    public void sendMessage(String exchangeName, String routeKey, Order order, Map<String, Object> properties){
        MessageHeaders headers=new MessageHeaders(properties);
        Message message= MessageBuilder.createMessage(order,headers);
        rabbitTemplate.setConfirmCallback(confirmCallback);
        rabbitTemplate.setReturnCallback(returnCallback);
        //消息唯一性
        CorrelationData correlationData = new CorrelationData();
        correlationData.setId(UUID.randomUUID().toString()+"_"+System.currentTimeMillis());
        // 使用Jackson2JsonMessageConverter 消息转化
        rabbitTemplate.setMessageConverter(new Jackson2JsonMessageConverter());
        rabbitTemplate.convertAndSend(exchangeName,routeKey,order,correlationData);
    }

PS: rabbitTemplate.setMessageConverter(new Jackson2JsonMessageConverter()); 配置 MessageConverterJackson2JsonMessageConverter

RabbitMQ系列文章目录

1、RabbitMQ Windows/CentOS7平台安装手册
2、RabbitMQ中一些重要概念
3、RabbitMQ Exchange类型之Direct Exchange
4、RabbitMQ Exchange类型之Topic Exchange
5、RabbitMQ Exchange类型之fanout Exchange
6、RabbitMQ Exchange类型之headers Exchang
7、Confirm消息确认机制
8、RabbitMQ中ReturnListener的使用
9、RabbitMQ消费端限流
10、ACK确认机制与消息补偿
11、RabbitMQ队列/消息的生存时间(Time-To-Live)
12、RabbitMQ死信队列(Dead Letter Exchanges)
13、Spring AMQP API详解
14、Spring Boot整合RabbitMQ

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

warybee

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值