Spring Boot整合RabbitMQ

1 创建工程

创建生产者工程 springboot-rabbitmq-producer

2 添加依赖

修改pom.xml文件内容为如下:

  <dependencies>
        <!--2. rabbitmq-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-amqp</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
        </dependency>
    </dependencies>

3. 启动类

@SpringBootApplication
public class ProducerApplication {


    public static void main(String[] args) {
        SpringApplication.run(ProducerApplication.class);
    }
}

4. 配置RabbitMQ

spring:
  rabbitmq:
    username: lhj
    password: 123
    host: 192.168.226.66
    virtual-host: lhj
    port: 5672
    publisher-returns: true #开启回退模式
#    publisher-confirm-type: correlated #开启确认模式
mq:
  exchange:
    name: test_exchange_topic
  queue:
    name1: test_topic_exchange_queue_1
    name2: test_topic_exchange_queue_2

5.手动授权配置文件

spring:
  rabbitmq:
    username: lhj
    password: 123
    host: 192.168.226.66
    virtual-host: lhj
    port: 5672
    listener:
      simple:
        acknowledge-mode: manual #开启手动授权
#mq:
#  exchange:
#    name: test_exchange_topic
#  queue:
#    name1: test_topic_exchange_queue_1
server:
  port: 8085
#    name2: test_topic_exchange_queue_2

6.绑定交换机和队列

创建RabbitMQ队列与交换机绑定的配置类com.yyl.rabbitmq.config.RabbitMQConfig

 

    //设置交换机的名字  和 队列的名字
    public static  final String EXCHANGE_NAME="exchange_topic_name";
    public static  final String QUEUE_NAME="queue_topic_name1";
    public static  final String QUEUE_NAME_2="queue_topic_name2";
    //将交换机这只成为一个bean注入到Springboot里面
    @Bean("topicExchange")
    public Exchange topicExchange(){
        //可以持久化的一个交换机
        return ExchangeBuilder.topicExchange(EXCHANGE_NAME).durable(true).build();
    }
    /**
     * 队列
     */
    @Bean("topicQueue")
    public Queue topicQueue(){
        return QueueBuilder.durable(QUEUE_NAME).build();
    }
    @Bean("topicQueue2")
    public Queue topicQueue2(){
        return QueueBuilder.durable(QUEUE_NAME_2).build();
    }
    /**
     * 将队列和交换机绑定到一起
     */
    @Bean
    public Binding exchangeWithQueue(@Qualifier("topicExchange") Exchange exchage, @Qualifier("topicQueue") Queue queue){
        //保存到数据库中
        //将交换机和队列绑定在一起
        return BindingBuilder.bind(queue).to(exchage).with("*.error").noargs();
    }
    @Bean
    public Binding exchangeWithQueue2(@Qualifier("topicExchange") Exchange exchage, @Qualifier("topicQueue2") Queue queue){
        //输出到控制台中
        //将交换机和队列绑定在一起
        return BindingBuilder.bind(queue).to(exchage).with("*.*").noargs();
    }

7.消费者代码

    @Resource
    private RabbitTemplate rabbitTemplate;


    @Test
    public void  testSendMesssage(){
        //将消息发送到队列里面
        rabbitTemplate.convertAndSend(RabbitMqConfig.EXCHANGE_NAME,"test.error","我是test模块中,日志级别为error的信息");
    }

8. 消息的可靠投递

在使用 RabbitMQ 的时候,作为消息发送方希望杜绝任何消息丢失或者投递失败场景。RabbitMQ 为我们提供了两种方式用来控制消息的投递可靠性模式。

  • confirm 确认模式

📌

确认队列中的消息是否被消费者消费

  • return 退回模式

💡

交换机中的消息是否到达队列里面

8.1.确认模式

    @Resource
    private RabbitTemplate rabbitTemplate;


    //确认模式的测试
    //1.开启确认模式 开启publisher-confirms="true"
    //2. 定义回调  在rabbitTemplate中设置信息的确认
    @Test
    public void testConfirm(){


           /**
            * @param correlationData 相关配置信息
            * @param ack   exchange交换机 是否成功收到了消息。true 成功,false代表失败
            * @param cause 失败原因
            */


        //匿名的内部类
        rabbitTemplate.setConfirmCallback(new RabbitTemplate.ConfirmCallback() {
            @Override
            public void confirm(CorrelationData correlationData, boolean ack, String s) {
                System.out.println("confirm方法执行了。。。。。。");
                if(ack){
                    System.out.println("接收成功");
                }else{
                    System.out.println("接收失败,失败的原因是:"+s);
                }
            }
        });
        //发送消息
        rabbitTemplate.convertAndSend(ConfirmConfig.EXCHAGE_CONFIRM_NAME,"confirm","confirm message");
    }

设置publisher-confirms="true" 开启 确认模式。

使用rabbitTemplate.setConfirmCallback设置回调函数。当消息发送到exchange后回调confirm方法。在方法中判断ack,如果为true,则发送成功,如果为false,则发送失败,需要处理。

8.2回退模式

 //设置交换机处理失败消息的模式
        rabbitTemplate.setMandatory(true);
        //匿名的内部类
        rabbitTemplate.setReturnCallback(new RabbitTemplate.ReturnCallback() {
            @Override
            public void returnedMessage(Message message, int replyCode, String replyText, String exchange, String routingKey) {
                System.out.println("return 执行了....");


//                System.out.println(message);
//                System.out.println(replyCode);
//                System.out.println(replyText);
//                System.out.println(exchange);
//                System.out.println(routingKey);
            }
        });
        //发送消息
        rabbitTemplate.convertAndSend(ConfirmConfig.EXCHAGE_CONFIRM_NAME,"confirm","confirm message");

设置publisher-returns="true"开启 退回模式。

使用rabbitTemplate.setReturnCallback设置退回函数,当消息从exchange路由到queue失败后,如果设置了rabbitTemplate.setMandatory(true)参数,则会将消息退回给producer。并执行回调函数returnedMessage。

8.3手动确认

acknowledge="manual" 。可以解决业务异常的情况

(收到消息之后不会立马确认收到消息,当业务处理没有问题的时候手动的调用代码的方 式来进行处理,如果业务失败了,就可以进行额外的操作)

    @Override
    @RabbitListener(queues = "test_confirm_queue")
    public void onMessage(Message message, Channel channel) throws Exception {
        Thread.sleep(2000);
        //1.接收消息
        System.out.println(new String(message.getBody()));
        long deliveryTag = message.getMessageProperties().getDeliveryTag();
        try {
            //2.处理业务luoji
            System.out.println("开始处理业务逻辑");
            int i=3/0;
            //3.成功就直接签收
            /**
             *  basicAck(long deliveryTag, boolean multiple)
             *  参数1 当前收到的消息的tag标签的内容
             *  参数2 是否允许多条消息被同时签收
             */
            //得到第一个参数
            channel.basicAck(deliveryTag, true);
        }catch(Exception e){
            //发生异常的时候就拒接签收
            /**
             * basicNack(long deliveryTag, boolean multiple, boolean requeue)
             * 参数3 是否重回队列  如果设置为true,则消息重新回到queue,broker会重新发送该消息给消费端
             */
            channel.basicNack(deliveryTag,true,true);
        }
    }

设置手动模式需要在配置文件里面添加 acknowlwdge-mode:manual

如果消费端没有异常就会走basicAck的方法,确认签收消息,如果有异常就会调用basicNack的方法拒接签收消息,让MQ重新发送消息

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值