rabbitMQ的进阶使用

整合rabbitMQ

首先整合rabbitMQ 需要的初步参考
初步使用rabbitMQ

实现服务端的消息抵达通知

我们现在对配置文件进行修改

  # RabbitMQ配置
  rabbitmq:
    host: 123.57.234.28
    port: 5672
    # 虚拟主机配置
    virtual-host: /
    publisher-returns: true
    ## 只要消息抵达Queue,就会异步发送优先回调returnfirm
    template:
      mandatory: true
    # 手动ack消息,不使用默认的消费端确认
    listener:
      direct:
        acknowledge-mode: manual
    #spring.rabbitmq.publisher-confirm-type新版发布确认属性有三种确认类型
    #NONE值是禁用发布确认模式,是默认值
    #CORRELATED值是发布消息成功到交换器后会触发回调方法
    #simple 的用法  除了包含CORRELATED
   # 开启发送端消息抵达Queue确认
    publisher-confirm-type: correlated

需要去设置回调方法
配置RabbitTemplate的回调

@Configuration
public class MyRabbitConfig {

    private RabbitTemplate rabbitTemplate;

    @Primary
    @Bean
    public RabbitTemplate rabbitTemplate(ConnectionFactory connectionFactory) {
        RabbitTemplate rabbitTemplate = new RabbitTemplate(connectionFactory);
        this.rabbitTemplate = rabbitTemplate;
        rabbitTemplate.setMessageConverter(messageConverter());
        initRabbitTemplate();
        return rabbitTemplate;
    }

    @Bean
    public MessageConverter messageConverter() {
        return new Jackson2JsonMessageConverter();
    }

    /**
     * 定制RabbitTemplate
     * 1、服务收到消息就会回调
     * 1、spring.rabbitmq.publisher-confirms: true
     * 2、设置确认回调
     * 2、消息正确抵达队列就会进行回调
     * 1、spring.rabbitmq.publisher-returns: true
     * spring.rabbitmq.template.mandatory: true
     * 2、设置确认回调ReturnCallback
     * <p>
     * 3、消费端确认(保证每个消息都被正确消费,此时才可以broker删除这个消息)
     */
    // @PostConstruct  //MyRabbitConfig对象创建完成以后,执行这个方法
    public void initRabbitTemplate() {

        /**
         * 1、只要消息抵达Broker就ack=true
         * correlationData:当前消息的唯一关联数据(这个是消息的唯一id)
         * ack:消息是否成功收到
         * cause:失败的原因
         */
        //设置确认回调
        rabbitTemplate.setConfirmCallback((correlationData, ack, cause) -> {
            System.out.println("confirm...correlationData[" + correlationData + "]==>ack:[" + ack + "]==>cause:[" + cause + "]");
        });


        /**
         * 只要消息没有投递给指定的队列,就触发这个失败回调
         * message:投递失败的消息详细信息
         * replyCode:回复的状态码
         * replyText:回复的文本内容
         * exchange:当时这个消息发给哪个交换机
         * routingKey:当时这个消息用哪个路邮键
         */
        rabbitTemplate.setReturnCallback((message,replyCode,replyText,exchange,routingKey) -> {
            System.out.println("Fail Message["+message+"]==>replyCode["+replyCode+"]" +
                    "==>replyText["+replyText+"]==>exchange["+exchange+"]==>routingKey["+routingKey+"]");
        });
    }

}

测试接受消息

服务器端消息发送

首先在配置文件中加入要发送的exchange 和queue 以及绑定的路由

myRabbitmq:
  exchange: hello-java-exchange
  queue: hello-java-queue
  routeKey: hello.java

编写发送测试类,这里用接口调用形式发送

@RestController
@Api(tags= "rabbit发送")
public class RabbitController {
    @Autowired
    private RabbitTemplate rabbitTemplate;

    @Value("${myRabbitmq.exchange}")
    private String exchange;

    @Value("${myRabbitmq.routeKey}")
    private String routeKey;

    @ApiOperation(value = "发送")
    @GetMapping("/sendMQ")
    public String sendMQ(@RequestParam(value = "num", required = false, defaultValue = "10") Integer num){

        OrderEntity entity = new OrderEntity();
        entity.setId(1L);
        entity.setCommentTime(new Date());
        entity.setCreateTime(new Date());
        entity.setConfirmStatus(0);
        entity.setAutoConfirmDay(1);
        entity.setGrowth(1);
        entity.setMemberId(12L);

        OrderItemEntity orderEntity = new OrderItemEntity();
        orderEntity.setCategoryId(225L);
        orderEntity.setId(1L);
        orderEntity.setOrderSn("mall");
        orderEntity.setSpuName("华为");
        for (int i = 0; i < num; i++) {
            if(i % 2 == 0){
                entity.setReceiverName("FIRE-" + i);
                rabbitTemplate.convertAndSend(this.exchange, this.routeKey, entity, new CorrelationData(UUID.randomUUID().toString().replace("-","")));
            }else {
                orderEntity.setOrderSn("mall-" + i);
                //rabbitTemplate.convertAndSend(this.exchange, this.routeKey, orderEntity, new CorrelationData(UUID.randomUUID().toString().replace("-","")));
                // 测试消息发送失败
                rabbitTemplate.convertAndSend(this.exchange, this.routeKey + "test", orderEntity);
            }
        }
        return "ok";
    }
}

调用发送接口,设置num数为10
这样有5条会发送失败

接受端消息处理以及通知

我们用consumer接受队列里面的
接受消息需要把接受类放在spring容器内 @Component
@RabbitListener(queues = “${myRabbitmq.queue}”,concurrency=“4”)
实现监听队列消息

用 @RabbitHandler 标注方法真正处理消息

channel.basicAck(deliveryTag, false)告诉mq已接收到消息,不用重新入队了

@Component
@RabbitListener(queues = "${myRabbitmq.queue}",concurrency="4")
public class TestConsumer {

    /**
     * 	1.Message message: 原生消息类型 详细信息
     * 	2.T<发送消息的类型> OrderEntity orderEntity  [Spring自动帮我们转换]
     * 	3.Channel channel: 当前传输数据的通道
     *
     * 	// 同一个消息只能被一个人收到
     *
     *
     * 	@RabbitListener: 只能标注在类、方法上 配合 @RabbitHandler
     * 	@RabbitHandler: 只能标注在方法上	[重载区分不同的消息]
     */
    @RabbitHandler
    public void receiveMessageA(Message message, OrderEntity orderEntity, Channel channel){
        System.out.println("接受到消息: " + message + "\n内容:" + orderEntity);
        try {
            Thread.sleep(200);
        } catch (InterruptedException e) { }
        // 这个是一个数字 通道内自增
        long deliveryTag = message.getMessageProperties().getDeliveryTag();
        try {
            // 只签收当前货物 不批量签收
            channel.basicAck(deliveryTag, false);

            // deliveryTag: 货物的标签  	multiple: 是否批量拒收 requeue: 是否重新入队
//			channel.basicNack(deliveryTag, false,true);
//			批量拒绝
//			channel.basicReject();
        } catch (IOException e) {
            System.out.println("网络中断");
        }
        System.out.println(orderEntity.getReceiverName() + " 消息处理完成");
    }

    @RabbitHandler
    public void receiveMessageB(Message message, OrderItemEntity orderEntity, Channel channel){
        System.out.println("接受到消息: " + message + "\n内容:" + orderEntity);
        try {
            Thread.sleep(2000);
        } catch (InterruptedException e) { }
        long deliveryTag = message.getMessageProperties().getDeliveryTag();
        try {
            channel.basicAck(deliveryTag, false);
        } catch (IOException e) {
            System.out.println("网络中断");
        }
        System.out.println(orderEntity.getOrderSn() + " 消息处理完成");
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值