栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

springboot整合rabbitMQ及手动ack确认

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

springboot整合rabbitMQ及手动ack确认

springboot版2.2.2


    4.0.0

    com.ex
    tmap2
    1.0-SNAPSHOT

    
        org.springframework.boot
        spring-boot-starter-parent
        2.2.2.RELEASE
         
    

    
        org.springframework.boot
        spring-boot-starter-web
    






    
        org.springframework.boot
        spring-boot-starter-amqp
    
    
        org.projectlombok
        lombok
    
    
        org.springframework.boot
        spring-boot-starter-test
        test
    



application.yml
 
spring:
  rabbitmq:
    host: localhost
    port: 5672
    username: admin
    password: 123456
    virtual-host: /ems
    template:
      retry: #重试,消息发送失败会重试
        enabled: true # 开启重试
        initial-interval: 10000ms  #第一次十秒重试
        max-interval: 80000ms  #最后一次是八秒重试
        multiplier: 2  #重试翻倍率
    publisher-confirms: true #发送者开启 confirm 确认机制
    publisher-returns: true  # 发送者开启 return 确认机制



RabbitCallbackConfig.java
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.connection.ConnectionFactory;
import org.springframework.amqp.rabbit.connection.CorrelationData;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Slf4j
@Configuration
public class RabbitCallbackConfig implements RabbitTemplate.ConfirmCallback, RabbitTemplate.ReturnCallback {
    @Bean
    RabbitTemplate rabbitTemplate(ConnectionFactory connectionFactory) {
        RabbitTemplate rabbitTemplate = new RabbitTemplate(connectionFactory);
        rabbitTemplate.setMandatory(true);
        rabbitTemplate.setConfirmCallback(this);
        rabbitTemplate.setReturnCallback(this);
        return rabbitTemplate;
    }

    // 下边这样写也可以
    // @Autowired
    // private RabbitTemplate rabbitTemplate;
    // @PostConstruct
    // public void init() {
    //     rabbitTemplate.setMandatory(true);
    //     rabbitTemplate.setReturnCallback(this);
    //     rabbitTemplate.setConfirmCallback(this);
    // }

    @Override
    public void confirm(CorrelationData correlationData, boolean ack, String cause) {
        if (!ack) {
            log.error("confirm==>发送到broker.exchange失败rn" +
                            "correlationData={}rn" + "ack={}rn" + "cause={}",
                    correlationData, ack, cause);
        } else {
            log.info("confirm==>发送到broker.exchange成功rn" +
                            "correlationData={}rn" + "ack={}rn" + "cause={}",
                    correlationData, ack, cause);
        }
    }

    @Override
    public void returnedMessage(Message message, int replyCode, String replyText,
                                String exchange, String routingKey) {
        log.info("returnedMessage==> rn" + "message={}rn" + "replyCode={}rn" +
                        "replyText={}rn" + "exchange={}rn" + "routingKey={}",
                message, replyCode, replyText, exchange, routingKey);
    }
}
WorkCustomer.java
import com.rabbitmq.client.Channel;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.rabbit.annotation.Exchange;
import org.springframework.amqp.rabbit.annotation.Queue;
import org.springframework.amqp.rabbit.annotation.QueueBinding;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.amqp.support.AmqpHeaders;
import org.springframework.messaging.handler.annotation.Header;
import org.springframework.stereotype.Component;

import java.io.IOException;
@Slf4j
@Component
public class WorkCustomer {


    @RabbitListener(queuesToDeclare = @Queue(value = "hello",declare = "true"),ackMode ="MANUAL" )
    @SneakyThrows
    public void receive12(String message, Channel channel,@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag){
        try {
            log.info("message: {}",message);
            // 处理实际业务
            // 制造异常
//             int wrongNumber = 1/0;
            // 无异常,确认消息消费成功
            channel.basicAck(deliveryTag, true);
        }catch (IOException | ArithmeticException exception) {
            log.error("处理消息发生异常", exception);
            // 有异常,将消息返回给Queue里,第三个参数requeue可以直接看出来,是否返回到Queue中
            channel.basicNack(deliveryTag, true, true);
        }

    }


    //-----------------工作模式---------------------------------------
    // 生产端没有指定交换机只有routingKey和Object。
    //消费方产生work队列,放在默认的交换机(AMQP default)上。
    //而默认的交换机有一个特点,只要你的routerKey的名字与这个
    //交换机的队列有相同的名字,他就会自动路由上。
    //生产端routingKey 叫work ,消费端生产work队列。
    //他们就路由上了
    @RabbitListener(queuesToDeclare = @Queue("work"))
    public void receive1(String message){
        System.out.println("work message1 = " + message);
    }


    @RabbitListener(queuesToDeclare = @Queue("work"))
    public void receive2(String message){
        System.out.println("work message2 = " + message);
    }

    //-------------------------广播模式--------------------------------------------------
    @RabbitListener(bindings = @QueueBinding(
            value = @Queue, // 创建临时队列
            exchange = @Exchange(name = "logs", type = "fanout")
    ))
    public void fanout1(String message) {
        System.out.println("message1 = " + message);
    }

    @RabbitListener(bindings = @QueueBinding(
            value = @Queue, // 创建临时队列
            exchange = @Exchange(name = "logs", type = "fanout")
    ))
    public void fanout2(String message) {
        System.out.println("message2 = " + message);
    }
//-------------------------路由模式--------------------------------------------------

    @RabbitListener(bindings = {
            @QueueBinding(
                    value = @Queue(value = "infoQue",declare = "true"), // 创建info队列,declare默认队列持久化
                    key = {"info"}, // 路由key
                    exchange = @Exchange(type = "direct", name = "directs")
            )})
    public void receive1221(String message) {
        System.out.println("message1 = " + message);
    }



@RabbitListener(bindings = {
        @QueueBinding(
                value = @Queue(value = "info||error"), // 创建临时队列
                key = {"info", "error"}, // 路由key
                exchange = @Exchange(type = "direct", name = "directs")
        )})
public void receive11(String message) {
    System.out.println("message1 = " + message);
}

    @RabbitListener(bindings = {
            @QueueBinding(
                    value = @Queue,
                    key = {"error"},
                    exchange = @Exchange(type = "direct", name = "directs")
            )})
    public void receive22(String message) {
        System.out.println("message2 = " + message);
    }
//-------------------------Topic 订阅模型(动态路由模型)--------------------------------------------------
@RabbitListener(bindings = {
        @QueueBinding(
                value = @Queue,
                key = {"user.*"},
                exchange = @Exchange(type = "topic",name = "topics")
        )
})
public void receive111(String message){
    System.out.println("message1 = " + message);
}

    @RabbitListener(bindings = {
            @QueueBinding(
                    value = @Queue,
                    key = {"user.#"},
                    exchange = @Exchange(type = "topic",name = "topics")
            )
    })
    public void receive222(String message){
        System.out.println("message2 = " + message);
    }



    
//    @RabbitListener(queues = "${queue.topic.first}", ackMode = "MANUAL")
//    @RabbitHandler
//    @SneakyThrows
//    public void receiveFirstTopicQueueMessage(String firstTopicQueueMessage, Channel channel, @Header(AmqpHeaders.DELIVERY_TAG) long tag) {
//        log.info("This is firstTopicQueue received message: {}", firstTopicQueueMessage);
//        try {
//            // 处理实际业务
//            TimeUnit.SECONDS.sleep(5);
//            // 制造异常
//            // int wrongNumber = 1/0;
//            // 无异常,确认消息消费成功
//            channel.basicAck(tag, true);
//        }catch (IOException | ArithmeticException exception) {
//            log.error("处理消息发生异常", exception);
//            // 有异常,将消息返回给Queue里,第三个参数requeue可以直接看出来,是否返回到Queue中
//            channel.basicNack(tag, true, true);
//        }
//    }

}
TTest.java
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;

@RunWith(SpringRunner.class)
@SpringBootTest
public class TTest {

    @Autowired
    private RabbitTemplate rabbitTemplate;

    //5.2 第一种hello world模型使用
    @Test
    public void test1() {
        rabbitTemplate.convertAndSend("hello", "你好");
        // 生产端没有指定交换机只有routingKey和Object。
        //消费方产生hello队列,放在默认的交换机(AMQP default)上。
        //而默认的交换机有一个特点,只要你的routerKey的名字与这个
        //交换机的队列有相同的名字,他就会自动路由上。
        //生产端routingKey 叫hello ,消费端生产hello队列。
//他们就路由上了
    }

    //5.3 第二种work模型使用
    @Test
    public void test2() {
        for (int i = 0; i < 10; i++) {
            rabbitTemplate.convertAndSend("work", "hello work!");
            // 生产端没有指定交换机只有routingKey和Object。
            //消费方产生work队列,放在默认的交换机(AMQP default)上。
            //而默认的交换机有一个特点,只要你的routerKey的名字与这个
            //交换机的队列有相同的名字,他就会自动路由上。
            //生产端routingKey 叫work ,消费端生产work队列。
            //他们就路由上了
        }
    }
//    5.4 Fanout 广播模型

    @Test
    public void test3() {
        rabbitTemplate.convertAndSend("logs", "", "这是日志广播"); // 参数1为交换机,参数2为路由key,“”表示为任意路由,参数3为消息内容
    }

    //5.5 Route 路由模型
    @Test
    public void contextLoads() {
//        rabbitTemplate.convertAndSend("directs", "error", "error 的日志信息");
        rabbitTemplate.convertAndSend("directs", "info", "info 的日志信息");
    }

    //5.6 Topic 订阅模型(动态路由模型)
    @Test
    public void contextLoads1() {
        rabbitTemplate.convertAndSend("topics", "user.save.findAll", "user.save.findAll 的消息");
    }
}

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/946329.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号