SpringBoot2.X整合RabbitMQ

SpringBoot2.X–RabbitMQ实战

maven导入mq包:

		
			org.springframework.boot
			spring-boot-starter-amqp
		

mq配置:

spring.rabbitmq.addresses=127.0.0.1:5672
spring.rabbitmq.username=guest
spring.rabbitmq.password=guest
spring.rabbitmq.virtual-host=/
spring.rabbitmq.connection-timeout=15000

spring.rabbitmq.publisher-confirms=true
spring.rabbitmq.publisher-returns=true
# return 的时候代表消息不可达,设置 broker 不自动删除该消息,
# 而是返回到生产端,让我们进行一些后续的处理
spring.rabbitmq.template.mandatory=true

MQ配置类:

@Configuration
public class RabbitMQConfig {

    public static final String QUEUE_SMS = "queue_inform_sms"; //短信队列名
    public static final String QUEUE_EMAIL = "queue_inform_email"; //邮件队列名
    public static final String ROUTINGKEY_SMS = "routingkey.#.sms.#"; //统配符匹配 短信队列key
    public static final String ROUTINGKEY_EMAIL = "routingkey.#.email.#"; //统配符匹配 邮件队列key
    public static final String EXCHANGE_ROUTING_INFORM = "exchange_topic_inform"; //交换机


    /**
     * 加载交换机组件
     * @return
     */
    @Bean(EXCHANGE_ROUTING_INFORM)
    public Exchange getExchange() {
        //创建交换机并设置模式
        ExchangeBuilder exchangeBuilder = ExchangeBuilder.topicExchange(EXCHANGE_ROUTING_INFORM);
        exchangeBuilder.durable(true); //是否持久化  默认为true
        Exchange exchange = exchangeBuilder.build();
        return exchange;
    }

    /**
     * 加载队列组件
     * @return
     */
    @Bean(QUEUE_SMS)
    public Queue getQueueSMS() {
        return new Queue(QUEUE_SMS,true);
    }

    /**
     * 加载队列组件
     * @return
     */
    @Bean(QUEUE_EMAIL)
    public Queue getQueueEMAIL() {
        return new Queue(QUEUE_EMAIL,true);
    }


    /**
     * 队列绑定交换机指定routingkey
     */
    @Bean
    public Binding bindingSMS(@Qualifier(QUEUE_SMS)Queue queue,
                                   @Qualifier(EXCHANGE_ROUTING_INFORM)Exchange exchange) {
        return BindingBuilder.bind(queue).to(exchange).with(ROUTINGKEY_SMS).noargs();
    }


    /**
     * 队列绑定交换机指定routingkey
     */
    @Bean
    public Binding bindingEMAIL(@Qualifier(QUEUE_EMAIL)Queue queue,
                              @Qualifier(EXCHANGE_ROUTING_INFORM)Exchange exchange) {
        return BindingBuilder.bind(queue).to(exchange).with(ROUTINGKEY_EMAIL).noargs();
    }

}

MQ生产者:

@Component
public class RabbitSender {

    @Autowired
    private RabbitTemplate rabbitTemplate;

    /**
     * 监听MQ服务返回的确认请求,消息到达exchange,ack 就返回true
     * CorrelationData 获取生产者发送的消息
     * ack 判断消息是否到达MQ服务
     */
    final RabbitTemplate.ConfirmCallback confirmCallback = new RabbitTemplate.ConfirmCallback() {
        @Override
        public void confirm(CorrelationData correlationData, boolean ack, String cause) {
            if(!ack){ //判断消息是否发送成功
                String id = correlationData.getId(); //消息ID
                Message message = correlationData.getReturnedMessage(); //消息体
//                byte[] body = message.getBody(); //消息
                System.err.println("消息ID: " + id + " 发送至MQ服务失败...." + message);
            }
        }
    };
    /* 简化版
     private final RabbitTemplate.ConfirmCallback  confirmCallback = (correlationData, ack, cause) -> {
        System.out.println("correlationData:" + correlationData);
        System.out.println("ack:" + ack);
        if (!ack){
            System.out.println("补偿处理...");
        }
    };*/


    /**
     * 监听exchange 是否将消息转发至对应的队列中(routingKey可能找不到对应的queue)
     */
    final RabbitTemplate.ReturnCallback returnCallback = new RabbitTemplate.ReturnCallback() {
        @Override
        public void returnedMessage(Message message, int replyCode, String replyText,
                                    String exchange, String routingKey) {
            if("NO_ROUTE".equals(replyText)) { //replyCode: 312, replyText: NO_ROUTE
                System.err.println("交换机转发消息至队列异常:{ Exchange" + exchange + ", RoutingKey: " + routingKey + " }");
            }
        }
    };
    /* 简化版
    private final RabbitTemplate.ReturnCallback returnCallback = (message, replyCode, replyText,
                                                                  exchange, routingKey) -> System.out.println("return exchange:" + exchange + ", routingKey:" + routingKey +
            ", replyText:" + replyText);*/



    /**
     * Rabbitmq 发送消息
     * @param obj 参数
     */
    public void sendOrder(Object obj) {
        //监听MQ服务回调
        rabbitTemplate.setConfirmCallback(confirmCallback);
        //监听Exchange回调
        rabbitTemplate.setReturnCallback(returnCallback);
        //发布者的基类
        CorrelationData cd = new CorrelationData();
        // 消息唯一标识
        String id = UUID.randomUUID().toString();
        cd.setId(id);
        /**
         * String exchange,  交换机
           String routingKey, 路由key
           Object object, 消息
           CorrelationData correlationData
           关联发布者的基类确认已发送的消息。使用org.springframework.amqp.rabbit.core。包含其中一个作为参数的RabbitTemplate方法;当收到发布者confirm时,将使用ack/nack返回CorrelationData。
         */
        rabbitTemplate.convertAndSend(RabbitMQConfig.EXCHANGE_ROUTING_INFORM, "routingkey.sms", obj, cd);
    }

}

MQ消费者:

@Component
public class RabbitConsumer {
    /**
     * @RabbitListener注解指定目标方法来作为消费消息的方法,通过注解参数指定所监听的队列或者Binding
     * @QueueBinding 定义队列并绑定交换机
     * @Queue 队列
     * @Exchange 交换机
     */
    @RabbitListener(bindings =
       @QueueBinding(value =@Queue(value = RabbitMQConfig.QUEUE_SMS, durable = "true"),
                    exchange = @Exchange(value = RabbitMQConfig.EXCHANGE_ROUTING_INFORM,
                                    durable = "true",
                                    type = "topic",
                                    ignoreDeclarationExceptions = "true"),
            key = RabbitMQConfig.ROUTINGKEY_SMS)
    )
    @RabbitHandler
    public void onOrderMessage(@Payload Object obj, @Headers Map properties, Channel channel) throws Exception {
        System.out.println("消费端 order:" + obj);
        // deliveryTag: 确认消息的条数,一般为1
        Long deliveryTag = (Long) properties.get(AmqpHeaders.DELIVERY_TAG);
        System.out.println("deliveryTag:" + deliveryTag);
        // 限流处理:消息体大小不限制,每次限制消费一条,只作用于该Consumer层,不作用于Channel
        channel.basicQos(0, 1, false);
        // 手工ACK,不批量ack
        channel.basicAck(deliveryTag, false);
    }
}

测试类:

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

    @Autowired
    public RabbitTemplate rabbitTemplate;

    @Autowired
    public RabbitSender sender;

    @Test
    public void sendMsg() {
//        String msg = "send msg...";
//        rabbitTemplate.convertAndSend(RabbitMQConfig.EXCHANGE_ROUTING_INFORM,"routingkey.sms",msg);
        HashMap params = new HashMap<>();
        params.put("title","测试");
        params.put("body","哈哈哈。。。");
        sender.sendOrder(params);
    }
}

SpringBoot2.X整合RabbitMQ_第1张图片

你可能感兴趣的:(MQ中间件)