【问题标题】:in Spring amqp how to encapsulate RabbitListener to a high level在 Spring amqp 中如何将 RabbitListener 封装到高级
【发布时间】:2018-07-02 01:36:11
【问题描述】:

我在我的项目中使用spring amqp,我使用实现ChannelAwareMessageListener进行重发和处理异常,让兔子监听器更稳定:

   public abstract class AbstractMessageListener implements ChannelAwareMessageListener {


    @Autowired
    private Jackson2JsonMessageConverter messageConverter;

    @Autowired
    private RedisTemplate<String, Object> redisTemplate;

    /** where comsumer really do biz */
    public abstract void receiveMessage(Message message, MessageConverter messageConverter);

    @Override
    public void onMessage(Message message, Channel channel) throws Exception {
        MessageProperties messageProperties = message.getMessageProperties();
        Long deliveryTag = messageProperties.getDeliveryTag();
        Long consumerCount = redisTemplate.opsForHash().increment(MQConstants.MQ_CONSUMER_RETRY_COUNT_KEY,
                messageProperties.getMessageId(), 1);
        try {
            receiveMessage(message, messageConverter);
            channel.basicAck(deliveryTag, false);             
            redisTemplate.opsForHash().delete(MQConstants.MQ_CONSUMER_RETRY_COUNT_KEY,
                    messageProperties.getMessageId());
        } catch (Exception e) {

            if (consumerCount >= MQConstants.MAX_CONSUMER_COUNT) {               
                channel.basicReject(deliveryTag, false);
            } else {               
                Thread.sleep((long) (Math.pow(MQConstants.BASE_NUM, consumerCount)*1000));
                channel.basicNack(deliveryTag, false, true);
            }
        }
    }

然后我们可以像这样扩展我们的 AbstractMessageListener 来接收:

public class BizMessageListener extends AbstractMessageListener  {

    Logger logger = LoggerFactory.getLogger(getClass());

    @Override
    public void receiveMessage(Message message, MessageConverter messageConverter) {
        //do our own biz
    }
}

但是有一天我老板说这种方式太入侵了你必须使用注解,所以我找到了这样的东西:Spring RabbitMQ - using manual channel acknowledgement on a service with @RabbitListener configuration

我可以在哪里使用注释

@RabbitListener(queues = "so38728668")
        public void receive(String payload, Channel channel, @Header(AmqpHeaders.DELIVERY_TAG) long tag)
                throws IOException {

但是我怎样才能将@RabbitListener 封装到一个高层次,以在我的第一个代码示例中结合我自己的重新发送消息代码,例如有一个注释作为RabbitResenderListener

 @RabbitResenderListener(queues = "so38728668")
            public void receive(Message msg)
                    throws IOException {
 // just do biz 
}

这个注解赋予方法重新发送消息和错误处理能力,使该方法只做商业。谢谢

【问题讨论】:

    标签: rabbitmq spring-cloud spring-amqp spring-rabbit


    【解决方案1】:

    不确定您对我们的期望,但在我看来,注释不适用于扩展和提取抽象,就像我们可以对类做的那样。

    无论如何我可以分享一些你可以尝试的想法。

    有一个方法级别的@RabbitHandler注解。因此,您可以用它标记超类中的方法并执行所有基础架构逻辑。目标实现应在类上使用特定的@RabbitListener 进行标记,以带来所需的queues 配置。 @RabbitHandler 方法会调用继承者的多态方法。

    听起来合理吗?

    【讨论】:

    • 是的,我想做的是,我不想创建一个超类,因为如果我创建一个超类,我们将编写的任何监听器都必须扩展这个超类,因为它被称为侵入性的。我想做的是写一个类扩展一些amqp源代码,并在这个类中编写我的基础架构逻辑。那么使用@RabbitListener 的类只能做业务逻辑,这意味着非侵入性。
    • 很高兴看到一些 PoC,但无论如何@RabbitListener 已经是 AMQP 源,它与方法契约非常相关,并且非常接近监听器容器。您可能需要查看 Spring Integration 以了解服务之间的下一级抽象:projects.spring.io/spring-integration
    • 嗨,我在 amqp 源代码中找到了类 MessagingMessageListenerAdapter.java,我想也许我可以重写 onMessage() 方法并添加我自己的基础架构逻辑。这是否有效?以及如何做到这一点,spring 可以通过扩展 MessagingMessageListenerAdapter 来识别我的新类吗?还是有其他方法可以重叠 amqp 的源代码?谢谢
    • 不,你不能那样做。这是非常具体的代码,并与整个注释处理相关联。不过,您可以考虑实现一些 AOP Advice,它们可以应用于选定的业务服务,并且可以调用适当的基础架构逻辑。 @RabbitListener 具有 containerFactory() 选项,其中 AbstractRabbitListenerContainerFactory 可以与 adviceChain 一起提供。
    猜你喜欢
    • 2017-08-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多