Spring boot整合RabbitMQ

Spring boot整合RabbitMQ

在阅读这篇之前请先完成RabbitMQ的基础知识学习。

依赖

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

配置

spring:
  rabbitmq:
    host: MQ服务器地址
    port: 端口号
    username: 账号
    password: 密码

基础发送和接受消息

创建队列、交换机、绑定信息

@Configuration
public class Demo1QueueConfig {

    /**
     * 创建一个队列,这里是最基础的创建队列只指定了队列名称
     */
    @Bean
    public Queue getDemo1Consumer() {
        return new Queue("hello");
    }
}

生产者

/**
 * 注入Springboot的MQ操作模板
 */
@Resource
private RabbitTemplate rabbitTemplate;

@GetMapping("/demo1")
public String demo1(String message) {
    //发送消息
    rabbitTemplate.send("hello", new Message(message.getBytes()));
    log.info("发送消息成功:{}", message);
    return "发送成功";
}

消费者

@Slf4j
@Component
public class Demo1Consumer {

    /**
     * 创建消费者接收消息,并指定队列名称
     */
    @RabbitListener(queues = "hello")
    public void message(String message) {
        log.info("消费者收到消息:{}", message);
    }
}

手动应答

配置

spring:
  rabbitmq:
    #消费者手动确认
    listener:
      simple:
        acknowledge-mode: manual

创建队列、交换机、绑定信息

@Configuration
public class Demo2QueueConfig {

    /**
     * 创建一个队列,这里是最基础的创建队列只指定了队列名称
     */
    @Bean
    public Queue getDemo2QueueConfig() {
        return new Queue("ack_queue");
    }
}

生产者

/**
 * 注入Springboot的MQ操作模板
 */
@Resource
private RabbitTemplate rabbitTemplate;

/**
 * demo2
 */
@GetMapping("/demo2")
public String demo2(String message) {
    //发送消息
    rabbitTemplate.send("ack_queue", new Message(message.getBytes()));
    log.info("手动应答发送消息成功:{}", message);
    return "发送成功";
}

消费者

@Slf4j
@Component
public class Demo2Consumer {

    /**
     * 手动应答消费者
     */
    @RabbitListener(queues = "ack_queue")
    public void message(Channel channel, Message message) throws Exception {
        log.info("手动应答消费者收到消息:{}", message.getBody());
        Thread.sleep(10000);
        /*
         用于肯定确认应答,告诉MQ已经处理完成
         1.消息标记 tag
         2.是否批量应答未应答消息,true 代表批量应答比如说channe上有传送tag的消息5,6,7,8当前tag是8那么此时5-8的这些还未应答的消息都会被确认收到消息应答;false同上面相比只会应答tag=8的消息5,6,7这三个消息依然不会被确认收到消息应答。下面的批量否认确定同此。
         */
        channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);

        /*
         用于否定确认
         1.消息标记 tag
         2.指定是否批量否定确认
         3.决定被否定确认的消息是否应重新入队(requeue)供其他消费者再次消费
         */
//        channel.basicNack(message.getMessageProperties().getDeliveryTag(), false, false);
        log.info("手动应答消费应答了消息");
    }
}

队列持久化

创建队列、交换机、绑定信息

@Configuration
public class Demo3QueueConfig {

    /**
     * 创建一个队列,true让其持久化
     */
    @Bean
    public Queue getDemo3QueueConfig() {
        return new Queue("durable_queue", true);
    }
}

消息持久化

生产者

/**
 * 注入Springboot的MQ操作模板
 */
@Resource
private RabbitTemplate rabbitTemplate;

/**
 * demo3 消息持久化
 */
@GetMapping("/demo3")
public String demo3(String message) {
    //设置消息持久化
    MessageProperties messageProperties = new MessageProperties();
    messageProperties.setContentType(MessageProperties.CONTENT_TYPE_TEXT_PLAIN);
    //发送消息
    rabbitTemplate.send("ack_queue", new Message(message.getBytes(), messageProperties));
        log.info("消息持久化发送消息成功:{}", message);
        return "发送成功";
}

不公平分发和预取值

消费者

@Slf4j
@Component
public class Demo4Consumer {


    @RabbitListener(queues = "demo4_queue")
    public void message(Channel channel, Message message) throws Exception {
        log.info("消费者收到消息:{}", message.getBody());
        /**
         * 只能处理一条消息,在未应答前MQ不会给该消费者发送下一条消息
         */
        channel.basicQos(1);
        log.info("手动应答消费应答了消息");
    }
}

发布确认

配置

spring:
  rabbitmq:
    #开启发布确认,异步回调
    publisher-confirm-type: correlated

生产者

/**
 * 注入Springboot的MQ操作模板
 */
@Resource
private RabbitTemplate rabbitTemplate;

/**
 * demo5 发布确认
 * 注入发布确认回调
 */
@Resource
private Demo5CallBack demo5CallBa
/**
 * 依赖注入 rabbitTemplate 之后再设置它的回调对象
 */
@PostConstruct
public void init() {
    //设置发布确认回调
    rabbitTemplate.setConfirmCallback(demo5CallBack);

/**
 * demo5 发布确认
 */
@GetMapping("/demo5")
public String demo5(String message) {
        //发送消息
        CorrelationData correlationData1 = new CorrelationData(UUID.randomUUID().toString());
        rabbitTemplate.convertAndSend("ack_queue", new Message(message.getBytes()), correlationData1);
        log.info("发布确认发送消息成功:{}", message);
        return "发送成功";
    }

监听回调

@Component
@Slf4j
public class Demo5CallBack implements RabbitTemplate.ConfirmCallback {

    /**
     * 交换机不管是否收到消息的一个回调方法
     * @param correlationData 消息相关数据
     * @param ack 交换机是否收到消息
     * @param cause 未收到原因
     */
    @Override
    public void confirm(CorrelationData correlationData, boolean ack, String cause) {
        String id=correlationData!=null?correlationData.getId():"";
        if(ack){
            log.info("交换机已经收到 id 为:{}的消息",id);
        }else{
            log.info("交换机还未收到 id 为:{}消息,由于原因:{}",id,cause);
        }
    }
}

消息回退

配置

spring:
  rabbitmq:
    host: 192.168.10.100
    port: 5672
    username: admin
    password: 123
    #开启发布确认,异步回调
    publisher-confirm-type: correlated
    #开启消息退回
    publisher-returns: true
    template:
      mandatory: true

生产者

/**
 * 注入Springboot的MQ操作模板
 */
@Resource
private RabbitTemplate rabbitTemplate;

 /**
  * demo6 发布回退
  * 注入发布回退回调
  */
 @Resource
 private Demo6CallBack demo6CallBac
 /**
  * 依赖注入 rabbitTemplate 之后再设置它的回调对象
  */
 @PostConstruct
 public void init() {
     //设置发布确认回调
     rabbitTemplate.setReturnCallback(demo6CallBack);
 
 /**
  * demo6 发布回退
  */
 @GetMapping("/demo6")
 public String demo6(String message) {
     //发送消息
     CorrelationData correlationData1 = new CorrelationData(UUID.randomUUID().toString());
        rabbitTemplate.convertAndSend("ddddd", new Message(message.getBytes()), correlationData1);
        log.info("发布回退发送消息成功:{}", message);
        return "发送成功";
    }

监听回调

@Component
@Slf4j
public class Demo6CallBack implements RabbitTemplate.ReturnCallback {

    /**
     * 当消息无法路由的时候的回调方法
     *
     * @param message    退回的消息对象本身
     * @param replyCode  RabbitMQ返回的错误码
     * @param replyText  RabbitMQ返回的错误信息
     * @param exchange   消息原本试图发送到的交换器名称
     * @param routingKey 消息发送时附带的路由键
     */
    @Override
    public void returnedMessage(Message message, int replyCode, String replyText, String exchange, String routingKey) {
        log.error(" 消 息 {}, 被交换机 {} 退回,退回原因 :{}, 路 由 key:{}", new String(message.getBody()), exchange,
                replyText, routingKey);
    }
}

fanout(广播类型)交换机

创建队列、交换机、绑定信息

@Configuration
public class Demo7QueueConfig {

    /**
     * 创建一个fanout交换机
     */
    @Bean
    FanoutExchange fanoutExchange() {
        return new FanoutExchange("FanoutExchange", false, false);
    }

    /**
     * 创建三个队列
     */
    @Bean
    Queue fanoutQueueA() {
        return new Queue("FanoutA", false, false, false);
    }

    @Bean
    Queue fanoutQueueB() {
        return new Queue("FanoutB", false, false, false);
    }

    @Bean
    Queue fanoutQueueC() {
        return new Queue("FanoutC", false, false, false);
    }

    /**
     * 将创建的队列绑定到创建的交换机上
     */
    @Bean
    Binding fanoutBindingA() {
        return BindingBuilder.bind(fanoutQueueA()).to(fanoutExchange());
    }

    @Bean
    Binding fanoutBindingB() {
        return BindingBuilder.bind(fanoutQueueB()).to(fanoutExchange());
    }

    @Bean
    Binding fanoutBindingC() {
        return BindingBuilder.bind(fanoutQueueC()).to(fanoutExchange());
    }

}

生产者

/**
 * demo7 fanout(广播类型)
 */
@GetMapping("/demo7")
public String demo7(String message) {
    //发送消息
    CorrelationData correlationData1 = new CorrelationData(UUID.randomUUID().toString());
    rabbitTemplate.convertAndSend("FanoutExchange", "", new Message(message.getBytes()),
            correlationData1);
    log.info("fanout(广播类型)发送消息成功:{}", message);
    return "发送成功";
}

消费者

@Slf4j
@Component
public class Demo7Consumer {


    @RabbitListener(queues = "FanoutA")
    public void messageFanoutA(Message message) throws Exception {
        log.info("FanoutA消费者收到消息:{}", message.getBody());
    }

    @RabbitListener(queues = "FanoutB")
    public void messageFanoutB(Message message) throws Exception {
        log.info("FanoutB消费者收到消息:{}", message.getBody());
    }

    @RabbitListener(queues = "FanoutC")
    public void messageFanoutC(Message message) throws Exception {
        log.info("FanoutC消费者收到消息:{}", message.getBody());
    }
}

direct(直接类型)交换机

创建队列、交换机、绑定信息

/**
 * direct(直接类型)交换机
 *
 * @author zjy
 * @date 2024/04/20  17:00
 */
@Configuration
public class Demo8QueueConfig {

    /**
     * 创建一个direct交换机
     */
    @Bean
    DirectExchange directExchange() {
        return new DirectExchange("DirectExchange", false, false);
    }

    /**
     * 创建两个队列
     */
    @Bean
    Queue directQueueA() {
        return new Queue("directA", false, false, false);
    }

    @Bean
    Queue directQueueB() {
        return new Queue("directB", false, false, false);
    }

    /**
     * 将创建的队列绑定到创建的交换机上
     */
    @Bean
    Binding directBindingA() {
        return BindingBuilder.bind(directQueueA()).to(directExchange()).with("a");
    }

    @Bean
    Binding directBindingB() {
        return BindingBuilder.bind(directQueueB()).to(directExchange()).with("b");
    }


}

生产者

/**
 * demo8 direct(直接类型)
 */
@GetMapping("/demo8")
public String demo8(String message) {
    //发送消息
    CorrelationData correlationData1 = new CorrelationData(UUID.randomUUID().toString());
    rabbitTemplate.convertAndSend("DirectExchange", "a", new Message(message.getBytes()),
            correlationData1);
    log.info("direct(直接类型)发送消息成功:{}", message);
    return "发送成功";
}

消费者

@Slf4j
@Component
public class Demo8Consumer {


    @RabbitListener(queues = "directA")
    public void messageDirectA(Message message) throws Exception {
        log.info("DirectA消费者收到消息:{}", message.getBody());
    }

    @RabbitListener(queues = "directB")
    public void messageDirectB(Message message) throws Exception {
        log.info("DirectB消费者收到消息:{}", message.getBody());
    }
}

Topics(复杂匹配)交换机

创建队列、交换机、绑定信息

@Configuration
public class Demo9QueueConfig {

    /**
     * 创建一个Topics(复杂匹配)交换机
     */
    @Bean
    TopicExchange topicsExchange() {
        return new TopicExchange("TopicExchange", false, false);
    }

    /**
     * 创建两个队列
     */
    @Bean
    Queue topicQueueA() {
        return new Queue("TopicA", false, false, false);
    }

    @Bean
    Queue topicQueueB() {
        return new Queue("TopicB", false, false, false);
    }

    /**
     * 将创建的队列绑定到创建的交换机上
     */
    @Bean
    Binding topicBindingA() {
        return BindingBuilder.bind(topicQueueA()).to(topicsExchange()).with("*.a");
    }

    @Bean
    Binding topicBindingB() {
        return BindingBuilder.bind(topicQueueB()).to(topicsExchange()).with("#");
    }


}

生产者

@GetMapping("/demo9")
public String demo9(@RequestParam String routingKey, @RequestParam String message) {
    //发送消息
    CorrelationData correlationData1 = new CorrelationData(UUID.randomUUID().toString());
    rabbitTemplate.convertAndSend("TopicExchange", routingKey, new Message(message.getBytes()),
            correlationData1);
    log.info("Topics(复杂匹配)发送消息成功:{}", message);
    return "发送成功";
}

消费者

@Slf4j
@Component
public class Demo9Consumer {


    @RabbitListener(queues = "TopicA")
    public void messageDirectA(Message message) throws Exception {
        log.info("TopicA消费者收到消息:{}", message.getBody());
    }

    @RabbitListener(queues = "TopicB")
    public void messageDirectB(Message message) throws Exception {
        log.info("TopicB消费者收到消息:{}", message.getBody());
    }
}

死信队列

创建队列、交换机、绑定信息

@Configuration
public class Demo10QueueConfig {

    /**
     * 创建一个正常交换机
     */
    @Bean
    DirectExchange normalExchange() {
        return new DirectExchange("NormalExchange", false, false);
    }

    /**
     * 创建一个死信交换机
     */
    @Bean
    DirectExchange deathExchange() {
        return new DirectExchange("DeathExchange", false, false);
    }

    /**
     * 创建死信队列
     */
    @Bean
    Queue deathQueue() {
        return new Queue("deathQueue", false, false, false);
    }

    /**
     * 将死信队列绑定到创建的死信交换机
     */
    @Bean
    Binding deathBinding() {
        return BindingBuilder.bind(deathQueue()).to(deathExchange()).with("death");
    }

    /**
     * 创建正常队列并绑定死信交换机
     */
    @Bean
    Queue normalQueue() {
        //交换机设置死信交换机
        Map<String, Object> arguments = new HashMap<>();
        arguments.put("x-dead-letter-exchange", "DeathExchange");
        //正常队列设置死信 routing-key 参数 key 是固定值
        arguments.put("x-dead-letter-routing-key", "death");
        return new Queue("normalQueue", false, false, false, arguments);
    }

    /**
     * 将正常队列绑定到创建的正常交换机
     */
    @Bean
    Binding normalBinding() {
        return BindingBuilder.bind(normalQueue()).to(normalExchange()).with("death");
    }
}

生产者

/**
 * demo10 死信队列
 */
@GetMapping("/demo10")
public String demo10(String message) {
    //设置消息1秒过期
    MessageProperties messageProperties = new MessageProperties();
    messageProperties.setExpiration("1000");
    //发送消息
    rabbitTemplate.convertAndSend("NormalExchange", "death",
            new Message(message.getBytes(), messageProperties));
    log.info("死信队列发送消息成功:{}", message);
    return "发送成功";
}

消费者

@Slf4j
@Component
public class Demo10Consumer {

    @RabbitListener(queues = "deathQueue")
    public void deathQueue(Message message) throws Exception {
        log.info("死信队列消费者收到消息:{}", message.getBody());
    }
}

延迟队列

创建队列、交换机、绑定信息

@Configuration
public class Demo11QueueConfig {

    /**
     * 创建一个延迟交换机
     */
    @Bean
    public CustomExchange delayExchange() {
        Map<String, Object> args = new HashMap<>();
        args.put("x-delayed-type", "direct");
        // 属性参数 交换机名称 交换机类型 是否持久化 是否自动删除 配置参数
        return new CustomExchange("delay_exchange", "x-delayed-message", false, false, args);
    }

    /**
     * 延时队列
     */
    @Bean
    public Queue delayQueue() {
        // 属性参数 队列名称 是否持久化
        return new Queue("delay_queue", false);
    }

    /**
     * 给延时队列绑定交换机
     */
    @Bean
    public Binding cfgDelayBinding() {
        return BindingBuilder.bind(delayQueue()).to(delayExchange()).with("delay_key").noargs();
    }
}

生产者

/**
 * demo11 延迟队列
 */
@GetMapping("/demo11")
public String demo11(Integer s, String message) {
    //设置消息1秒过期
    MessageProperties messageProperties = new MessageProperties();
    // 配置消息的过期时间
    messageProperties.setDelay(s * 1000);
    //发送消息
    rabbitTemplate.convertAndSend("delay_exchange", "delay_key",
            new Message(message.getBytes(), messageProperties));
    log.info("延迟队列发送消息成功:{}", message);
    return "发送成功";
}

消费者

@Slf4j
@Component
public class Demo11Consumer {

    @RabbitListener(queues = "delay_queue")
    public void deathQueue(Message message) throws Exception {
        log.info("延迟队列消费者收到消息:{}", message.getBody());
    }
}
  • 8
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值