2020-09-18

@RabbitListener注解和ChannelAwareMessageListener之间的关系

两者本质上是同级的,比如监听了同一个queue,那么生产者发到这个queue的消息会轮询这两个消费方式。

不同的点是**@RabbitListener注解想实现手动ack必须在配置文件中配置**:

spring:
 rabbitmq:
  listener:
   simple:
    acknowledge-mode: manual

增加配置后才可以在代码中进行手动ack:

@Component
public class DirectListenerOne {

	@RabbitListener(queues = "TestDirectQueue")//监听的队列名称 TestDirectQueue
public void process(Message testMessage, Channel channel, @Headers Map<String, Object> map) {
    System.out.println("One DirectReceiver消费者收到消息  : " + testMessage.toString());
    //RabbitListener与ChannelAwareMessageListener同时basicReject情况测试
    /*try {
        channel.basicReject(testMessage.getMessageProperties().getDeliveryTag(), true);
    } catch (IOException e) {
        e.printStackTrace();
    }*/
}
}

否则会报unknown delivery tag 1的错误,就是因为rabbitmq的默认ack是自动的,如果在代码中手动reject,那么就相当于ack了两次,那么第二次肯定就会找不到delivery。

而ChannelAwareMessageListener一般是配合SimpleMessageListenerContainer一起使用,通过在配置文件中配置实现:

@Configuration
public class MessageListenerConfig {

    @Autowired
    private CachingConnectionFactory connectionFactory;
    @Autowired
    private MyAckListener myAckListener;//消息接收处理类

    @Bean
    public SimpleMessageListenerContainer simpleMessageListenerContainer() {
        SimpleMessageListenerContainer container = new SimpleMessageListenerContainer(connectionFactory);
        container.setConcurrentConsumers(1);
        container.setMaxConcurrentConsumers(1);
        container.setAcknowledgeMode(AcknowledgeMode.MANUAL); // RabbitMQ默认是自动确认,这里改为手动确认消息
        //设置一个队列
        container.setQueueNames("TestDirectQueue");
        //如果同时设置多个如下: 前提是队列都是必须已经创建存在的
        //  container.setQueueNames("TestDirectQueue","TestDirectQueue2","TestDirectQueue3");

        //另一种设置队列的方法,如果使用这种情况,那么要设置多个,就使用addQueues
        //container.setQueues(new Queue("TestDirectQueue",true));
        //container.addQueues(new Queue("TestDirectQueue2",true));
        //container.addQueues(new Queue("TestDirectQueue3",true));
        container.setMessageListener(myAckListener);

        return container;
    }

}

消息确认模式:

  • AcknowledgeMode.NONE:自动确认
  • AcknowledgeMode.AUTO:根据情况确认
  • AcknowledgeMode.MANUAL:手动确认

手动确认

basic.ack用于肯定确认
basic.nack用于否定确认

channel.basicNack(deliveryTag, false, true);

  • 第一个参数依然是当前消息到的数据的唯一id;
  • 第二个参数是指是否针对多条消息;如果是true,也就是说一次性针对当前通道的消息的tagID小于当前这条消息的,都拒绝确认。
  • 第三个参数是指是否重新入列,也就是指不确认的消息是否重新丢回到队列里面去。
basic.reject用于否定确认,但与basic.nack相比有一个限制:一次只能拒绝单条消息

channel.basicReject(deliveryTag, true); 拒绝消费当前消息,如果第二参数传入true,就是将数据重新丢回队列里,那么下次还会消费这消息。设置false,就是告诉服务器,我已经知道这条消息数据了,因为一些原因拒绝它,而且服务器也把这个消息丢掉就行。 下次不想再消费这条消息了。

@RabbitListener 和 @RabbitHandler 搭配使用

@RabbitListener 可以标注在类上面,需配合 @RabbitHandler 注解一起使用
@RabbitListener 标注在类上面表示当有收到消息的时候,就交给 @RabbitHandler 的方法处理,具体使用哪个方法处理,根据 MessageConverter 转换后的参数类型

@Component
@RabbitListener(queues = "consumer_queue")
public class Receiver {

 @RabbitHandler public void processMessage1(String message) { System.out.println(message); }
 @RabbitHandler public void processMessage2(byte[] message) { System.out.println(new String(message)); } }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值