Springboot 整合RabbitMQ (一)

本文整合MQ交换机类型为Direct,下面是各类交换机类型的大概介绍

Direct Exchange(直连交换机):消息会传送给绑定键与消息的路由键完全匹配的那个队列。

Fanout Exchange(扇形交换机):扇形交换机将消息路由给绑定到自身的所有消息队列,也就是说路由键在扇形交换机里没有作用,故消息队列绑定扇形交换机时,路由键可为空。这个模式类似于广播。

Topic Exchange(主题交换机):消息路由键—发送到主题交换机的消息所携带的路由键(routing_key)不能随意命名——它必须是一个用点号分隔的词列表。当中的词可以是任何单词,不过一般都会指定一些跟消息有关的特征作为这些单词。

* (星号) 能够替代一个单词。

# (井号) 能够替代零个或多个单词。

Headers Exchange(头交换机):头交换机类似与主题交换机,但是却和主题交换机有着很大的不同。主题交换机使用路由键来进行消息的路由,而头交换机使用消息属性来进行消息的分发,通过判断消息头的值能否与指定的绑定相匹配来确立路由规则。

整合springboot

<!--RabbitMQ 依赖-->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-amqp</artifactId>
</dependency>


<dependency>
     <groupId>org.projectlombok</groupId>
     <artifactId>lombok</artifactId>
</dependency>

yaml文件配置

spring:
  rabbitmq:
    host: 服务器地址
    port: 5672
    username: admin
    password: 123

创建对应的config配置

package com.example.myselfmq.config;

import org.springframework.amqp.core.Binding;
import org.springframework.amqp.core.BindingBuilder;
import org.springframework.amqp.core.DirectExchange;
import org.springframework.amqp.core.Queue;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * @author Maple
 * @description: TODO
 * @date 2022/8/12 20:31
 */
@Configuration
public class DirectConfig {
    // 交换机名称
    public static final String DIRECT_EXCHANGE_NAME = "direct_exchange";
    // 队列名称
    public static final String DIRECT_QUEUEQ_NAME = "direct_queue";
    // RoutingKey
    public static final String DIRECT_ROUTING_KEY = "key1";

    // 声明交换机
    @Bean
    public DirectExchange directExchange(){
        return new DirectExchange(DIRECT_EXCHANGE_NAME);
    }
    // 声明队列
    @Bean
    public Queue directQueue(){
        return new Queue(DIRECT_QUEUEQ_NAME);
    }
    // 绑定交换机和队列
    @Bean
    public Binding queueBindingExchange(@Qualifier("directExchange")DirectExchange directExchange,@Qualifier("directQueue")Queue directQueue){
        return BindingBuilder.bind(directQueue).to(directExchange).with(DIRECT_ROUTING_KEY);
    }
}

创建消息生产者

package com.example.myselfmq.Controller;

import com.example.myselfmq.config.DirectConfig;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

/**
 * @author Maple
 * @description: TODO
 * @date 2022/8/12 20:40
 */
@Slf4j
@RestController
@RequestMapping("producer")
public class ProducerController {

    @Autowired
    private RabbitTemplate rabbitTemplate;

    // 发消息
    @GetMapping("/sendMessage/{message}")
    public void sendMessage(@PathVariable String message){
        rabbitTemplate.convertAndSend(DirectConfig.DIRECT_EXCHANGE_NAME,DirectConfig.DIRECT_ROUTING_KEY, message);
        log.info("成功发送消息:{}",message);
    }
}

创建消费者

package com.example.myselfmq.consumer;

import com.example.myselfmq.config.DirectConfig;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component;

/**
 * @author Maple
 * @description: TODO
 * @date 2022/8/12 20:48
 */
@Slf4j
@Component
public class ConsumerReceiver {
    // 消费消息
    @RabbitListener(queues = DirectConfig.DIRECT_QUEUEQ_NAME)
    public void receiveConfirmMessage(Message message){
        log.info("接收到的队列消息为:{}",new String(message.getBody()));
    }
}

测试发送消息是否成功消费

消息被成功消费 

设置消息TTL以及配置死信队列

TTL RabbitMQ 中一个消息或者队列的属性,表明一条消息或者该队列中的所有消息的最大存活时间,如果一条消息设置了 TTL 属性或者进入了设置TTL 属性的队列,那么这 条消息如果在TTL 设置的时间内没有被消费,则会成为 " 死信 "
修改队列属性后需去mq后台删除队列,不然会报错
修改config配置代码,配置死信交换机与队列同时设置队列的TTL属性,声明新队列b并且将业务队列绑定死信交换机。
package com.example.myselfmq.config;

import org.springframework.amqp.core.*;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.HashMap;
import java.util.Map;

/**
 * @author Maple
 * @description: TODO
 * @date 2022/8/12 20:31
 * @email 576235959@qq.com
 */
@Configuration
public class DirectConfig {
    // 交换机名称
    public static final String DIRECT_EXCHANGE_NAME = "direct_exchange";
    // 队列名称
    public static final String DIRECT_QUEUEQ_NAME = "direct_queue";
    // 队列b
    public static final String DIRECT_QUEUEQ_B_NAME = "direct_b_queue";
    // RoutingKey
    public static final String DIRECT_ROUTING_KEY = "key1";
    // 队列bRoutingKey
    public static final String DIRECT_B_ROUTING_KEY = "key2";
    // 死信交换机
    public static final String DEAD_LETTER_EXCHANGE = "dead_exchange";
    // 死信队列
    public static final String DEAD_LETTER_QUEUE = "dead_queue";
    // 死信RoutingKey
    public static final String DEAD_LETTER_ROUTING_KEY = "dead_queue";
    // 声明交换机
    @Bean
    public DirectExchange directExchange(){
        return new DirectExchange(DIRECT_EXCHANGE_NAME);
    }
    // 声明队列
    @Bean
    public Queue directQueue(){
        Map<String,Object> arguments = new HashMap<>();
        // 设置死信交换机
        arguments.put("x-dead-letter-exchange",DEAD_LETTER_EXCHANGE);
//        设置死信RoutingKey
        arguments.put("x-dead-letter-routing-key",DEAD_LETTER_ROUTING_KEY);
        // 设置TTL
        arguments.put("x-message-ttl",10000);
        // 业务队列绑定死信交换机
        return QueueBuilder.durable(DIRECT_QUEUEQ_NAME).withArguments(arguments).build();
    }
    @Bean
    public Queue directBQueue(){
        Map<String,Object> arguments = new HashMap<>();
        // 设置死信交换机
        arguments.put("x-dead-letter-exchange",DEAD_LETTER_EXCHANGE);
//        设置死信RoutingKey
        arguments.put("x-dead-letter-routing-key",DEAD_LETTER_ROUTING_KEY);
        // 设置TTL
        arguments.put("x-message-ttl",40000);
        // 业务队列绑定死信交换机
        return QueueBuilder.durable(DIRECT_QUEUEQ_B_NAME).withArguments(arguments).build();
    }
    // 绑定交换机和队列
    @Bean
    public Binding queueBindingExchange(@Qualifier("directExchange")DirectExchange directExchange,
                                        @Qualifier("directQueue")Queue directQueue){
        return BindingBuilder.bind(directQueue).to(directExchange).with(DIRECT_ROUTING_KEY);
    }
    @Bean
    public Binding queueBBindingExchange(@Qualifier("directExchange")DirectExchange directExchange,
                                        @Qualifier("directBQueue")Queue directBQueue){
        return BindingBuilder.bind(directBQueue).to(directExchange).with(DIRECT_B_ROUTING_KEY);
    }
    // 声明死信交换机
    @Bean
    public DirectExchange deadExchange(){
        return new DirectExchange(DEAD_LETTER_EXCHANGE);
    }
    // 声明死信队列
    @Bean
    public Queue deadQueue(){
        return new Queue(DEAD_LETTER_QUEUE);
    }
    // 绑定死信交换机和队列
    @Bean
    public Binding deadBindingExchange(@Qualifier("deadExchange")DirectExchange deadExchange,
                                        @Qualifier("deadQueue")Queue deadQueue){
        return BindingBuilder.bind(deadQueue).to(deadExchange).with(DEAD_LETTER_ROUTING_KEY);
    }
}

配置死信消费者监听

package com.example.myselfmq.consumer;

import com.example.myselfmq.config.DirectConfig;
import com.rabbitmq.client.Channel;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component;

import java.io.IOException;
import java.util.Date;

/**
 * @author Maple
 * @description: TODO
 * @date 2022/8/12 21:37
 * @email 576235959@qq.com
 * 死信消费者
 */
@Component
@Slf4j
public class DeadLetterReceiver {
    @RabbitListener(queues = DirectConfig.DEAD_LETTER_QUEUE)
    public void receiveD(Message message, Channel channel) throws IOException {
        String msg = new String(message.getBody());
        log.info("当前时间:{},收到死信队列信息{}", new Date(), msg);

    }
}

注释消费者监听

修改生产者发送消息代码测试消息过期是否会进入死信队列

 @GetMapping("/sendMessage/{message}")
    public void sendMessage(@PathVariable String message){
        rabbitTemplate.convertAndSend(DirectConfig.DIRECT_EXCHANGE_NAME,DirectConfig.DIRECT_ROUTING_KEY, "消息来自ttl为10s的队列:"+message);
        rabbitTemplate.convertAndSend(DirectConfig.DIRECT_EXCHANGE_NAME,DirectConfig.DIRECT_B_ROUTING_KEY, "消息来自ttl为40s的队列:"+message);
        log.info("成功发送消息:{}",message);
    }

 结果:

在等待10s和40s后,消息先后进入死信队列消费 

代码优化,不写死ttl改为手动添加

注释config中b队列的ttl属性

修改生产者代码

  // 发消息
    @GetMapping("/sendMessage/{message}/{ttlTime}")
    public void sendMessage(@PathVariable String message,@PathVariable String ttlTime){
        rabbitTemplate.convertAndSend(DirectConfig.DIRECT_EXCHANGE_NAME,DirectConfig.DIRECT_ROUTING_KEY, "消息来自ttl为10s的队列:"+message);
        rabbitTemplate.convertAndSend(DirectConfig.DIRECT_EXCHANGE_NAME,DirectConfig.DIRECT_B_ROUTING_KEY,
                "消息来自ttl为"+ttlTime+"s的队列:"+message, correlationData ->{
            correlationData.getMessageProperties().setExpiration(ttlTime);
            return correlationData;
        });
        log.info("成功发送消息:{}",message);
    }

 将ttl改为参数获取,然后在生产者这边设置队列的ttl属性.

结果:

Springboot 整合 RabbitMQ(二)_Maplelhw的博客-CSDN博客

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值