03_Springboot整合RabbitMQ

一、Springboot整合RabbitMQ

1.1 添加依赖

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

1.2 application.yml

  rabbitmq:
    host: 192.168.31.128
    port: 5672
    username: mqroot
    password: mqroot
    virtual-host: test
    # 消息确认类型 NONE 默认值 禁止发布调用模式 correlated 发布消息成功到交换器后会触发回调方 法
    publisher-confirm-type: correlated
    # 设置允许消息从交换机路由到队列失败时的回调 默认值是false 即不执行回调
    publisher-returns: true
    listener:
      direct:
        # 手动ack 默认值是auto 自动确认 manual 是手动确认
        acknowledge-mode: manual

1.3 rabbitmq配置类

Queue参数信息

  • name: 队列的名称;

  • actualName: 队列的真实名称,默认用name参数,如果name为空,则根据规则生成一个;

  • durable: 是否持久化;

  • exclusive: 是否独享、排外的;

  • autoDelete: 是否自动删除;

  • arguments:队列的其他属性参数,有如下可选项,可参看图2的arguments:

    • x-message-ttl:消息的过期时间,单位:毫秒;

    • x-expires:队列过期时间,队列在多长时间未被访问将被删除,单位:毫秒;

    • x-max-length:队列最大长度,超过该最大值,则将从队列头部开始删除消息;

    • x-max-length-bytes:队列消息内容占用最大空间,受限于内存大小,超过该阈值则从队列头部开始删除消息;

    • x-overflow:设置队列溢出行为。这决定了当达到队列的最大长度时消息会发生什么。有效值是drop-head、reject-publish或reject-publish-dlx。仲裁队列类型仅支持drop-head;

    • x-dead-letter-exchange:死信交换器名称,过期或被删除(因队列长度超长或因空间超出阈值)的消息可指定发送到该交换器中;

    • x-dead-letter-routing-key:死信消息路由键,在消息发送到死信交换器时会使用该路由键,如果不设置,则使用消息的原来的路由键值

    • x-single-active-consumer:表示队列是否是单一活动消费者,true时,注册的消费组内只有一个消费者消费消息,其他被忽略,false时消息循环分发给所有消费者(默认false)

    • x-max-priority:队列要支持的最大优先级数;如果未设置,队列将不支持消息优先级;

    • x-queue-mode(Lazy mode):将队列设置为延迟模式,在磁盘上保留尽可能多的消息,以减少RAM的使用;如果未设置,队列将保留内存缓存以尽可能快地传递消息;

    • x-queue-master-locator:在集群模式下设置镜像队列的主节点信息。

交换机参数信息

类型

  • FanoutExchange :扇形 交换机

  • DirectExchange :直连交换机 routing模式用的交换机

  • TopicExchange :主题模式交换机

参数信息

  • name:交换机名称

  • durable:是否把交换机持久化到磁盘上

  • autoDelete :是否自动删除交换机 用法有点类似上面的队列中的autoDelete 只有所有队列都和交换机接触订阅,说白了就是所有绑定到交换机上的队列不再需要改交换机,他就该死了,有点残酷

  • artuments :额外参数

配置类

@Configuration
public class RabbitMQConfig {
​
    public static final String EX_CHANGE = "ex.direct";
​
    public static final String ORDER_QUEUE = "order.queue";
    public static final String ORDER_QUEUE_KEY = "order";
​
    public static final String DLL_ORDER_QUEUE = "ddl.order.queue";
    public static final String DLL_ORDER_QUEUE_KEY = "ddl.order";
​
    @Bean("exDirect")
    public DirectExchange initExchange() {
        // new FanoutExchange()
        return new DirectExchange(EX_CHANGE, true, false);
    }
​
    @Bean("orderQueue")
    public Queue initOrderQueue() {
        // 设置有效期
        HashMap<String, Object> map = new HashMap<>();
        map.put("x-message-ttl",10000);
        map.put("x-dead-letter-exchange",EX_CHANGE);
        map.put("x-dead-letter-routing-key",DLL_ORDER_QUEUE_KEY);
        map.put("x-overflow","reject-publish");
        return new Queue(ORDER_QUEUE,true);
    }
​
    @Bean("ddlOrderQueue")
    public Queue initDDLOrderQueue() {
        return new Queue(DLL_ORDER_QUEUE,true);
    }
​
    // 绑定
    @Bean("bindingQueue")
    public Binding bindingQueue(@Qualifier("orderQueue") Queue queue,@Qualifier("exDirect") DirectExchange exchange){
        return BindingBuilder.bind(queue).to(exchange).with(ORDER_QUEUE_KEY);
    }
​
    @Bean("bindingDDLQueue")
    public Binding bindingDDLQueue(@Qualifier("ddlOrderQueue") Queue queue,@Qualifier("exDirect") DirectExchange exchange){
        return BindingBuilder.bind(queue).to(exchange).with(DLL_ORDER_QUEUE_KEY);
    }
    
    /*
    ---------------------------------------
    --------------其他类型交换机配置类似-------
    ---------------------------------------
    */
​
    /**
     * 将队列和交换机绑定, 并设置用于匹配键
     * @return
     */
    @Bean
    public RabbitTemplate createRabbitTemplate(ConnectionFactory connectionFactory) {
        
        /*
        ConfirmCallback是用来得知是否进入到交换机
        ReturnCallback是获取未进入队列的回调信息,如果成功进入队列,不会进入这个回调方法。必须设置rabbitTemplate.setMandatory(true);
        */
        
        RabbitTemplate rabbitTemplate = new RabbitTemplate();
        rabbitTemplate.setConnectionFactory(connectionFactory);
        
        // 消息进入到MQ触发,是否到交换机
        rabbitTemplate.setConfirmCallback(new RabbitTemplate.ConfirmCallback() {
            @Override
            public void confirm(CorrelationData correlationData, boolean ack, String cause) {
                System.out.println("ConfirmCallback:相关数据:" + correlationData);
                System.out.println("ConfirmCallback:确认情况:" + ack);
                System.out.println("ConfirmCallback:原因:" + cause);
            }
        });
​
        
        // 设置开启Mandatory,才能触发回调函数,无论消息推送结果怎么样都强制调用回调函数
        // 为true时,消息通过交换器无法匹配到队列会返回给生产者,并触发MessageReturn,为false时,匹配不到会直接被丢弃
        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("ReturnCallback:消息:" + message);
                System.out.println("ReturnCallback:回应码:" + replyCode);
                System.out.println("ReturnCallback:回应信息:" + replyText);
                System.out.println("ReturnCallback:交换机:" + exchange);
                System.out.println("ReturnCallback:路由键:" + routingKey);
            }
        });
​
        return rabbitTemplate;
    }
​
 }

1.4 生产者

@RestController
public class RabbitMQProductController {
​
​
​
    @Resource
    RabbitTemplate rabbitTemplate;
​
    @PostMapping("send")
    public String send() {
        String messageId = String.valueOf(UUID.randomUUID());
        String messageData = "test message, hello!";
        String createTime = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
        Map<String, Object> map = new HashMap<>();
        map.put("messageId", messageId);
        map.put("messageData", messageData);
        map.put("createTime", createTime);
        //将消息携带绑定键值:TestDirectRouting 发送到交换机TestDirectExchange
        rabbitTemplate.convertAndSend("TestDirectExchange", "TestDirectRouting", map);
        return "ok";
    }
}

1.5 消费者

@RabbitListener添加给类

@Component
@RabbitListener(queues = "TestDirectQueue")//监听的队列名称 TestDirectQueue
public class DirectReceiver {
​
    @RabbitHandler
    public void process(Map testMessage, Message message, Channel channel) throws IOException {
        System.out.println("DirectReceiver消费者收到消息  : " + testMessage.toString());
        System.out.println(message);
        // 手动应答
        channel.basicAck(message.getMessageProperties().getDeliveryTag(),false);
    }
​
}

@RabbitListener添加给方法

/**
 * 消费者:监听队列,从队列中获取消息,并处理消息
 */
@Component
public class DirectListener2 {
    /**
     *
     * @param msg:获取到的消息,类型与发布时的类型一致
     * @param message:消息的详细信息:消息内容body,存储信息(队列,交换机,路由,标识符)
     * @param channel:信道
     */
    @RabbitListener(queues = RabbitMQConfig.DIRECT_EXCHANGE_QUEUE)
    public void handleMyQueue(Map msg, Message message, Channel channel) throws IOException {
        System.out.println("队列my-queue的信息");
        System.out.println(msg.toString());
        System.out.println(message);
        System.out.println(channel);
        // 手动应答
        channel.basicAck(message.getMessageProperties().getDeliveryTag(),true);
    }
​
    @RabbitListener(queues = "aaa")
    public void handleAAA(String msg, Message message, Channel channel) throws IOException {
        System.out.println("队列aaa的信息");
        System.out.println(msg.toString());
        System.out.println(message);
        System.out.println(channel);
        // 手动应答
        channel.basicAck(message.getMessageProperties().getDeliveryTag(),true);
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值