为什么在spring-amqp

时间:2017-01-05 09:13:11

标签: spring-boot spring-amqp

使用AsyncRabbitTemplate.sendAndReceive()或AsyncRabbitTemplate.convertSendAndReceive()方法处理回复消息时,由于回复消息是与调用方法异步返回的,我们可以使用消息监听器来回复队列来接收和处理回复消息,为什么是spring -amqp框架导入AsyncRabbitTemplate和RabbiteMessageFuture来处理回复消息?对于消息监听器,我们可以控制相关的消费者线程, 但是对于RabbitMessageFuture,后台线程无法管理。

-------------------于2017/01/06添加--------------------- -------

  

这只是你的选择。

     

回复可以以不同的顺序返回发送。

     

使用异步模板,框架负责关联   对于您,回复将在将来由发送返回   方法

     

当你使用自己的听众时,你将不得不照顾   相关自己。

谢谢。我知道这种差异。但仍然存在问题。如果我使用消息监听器,我可以手动确认回复消息(如果我的消息监听器 实现ChannelAwareMessageListener接口,我可以获取通道实例)。但是当我使用asyncRabbitTemplate时,我可以手动回复回复消息吗?看来sendAndReceive方法会自动回复回复消息。

  

我不明白你的意思;因为你可以注入监听器   容器进入模板,无论哪种方式都有相同的“控制”。

这似乎意味着存在一些问题。

我创建了一个rabbitTemplate实例和简单的消息监听器容器。但是,当我使用它们来构造asyncRabbitTemplate实例时,如下代码:

@Bean(name="rabbitTemplate")
public RabbitTemplate getRabbitTemplate()
{
        RabbitTemplate rabbitTemplate = new RabbitTemplate(getConnectionFactory());
        rabbitTemplate.setUseTemporaryReplyQueues(false);        
        rabbitTemplate.setReplyAddress("replyQueue");
        rabbitTemplate.setReceiveTimeout(60000);
        rabbitTemplate.setReplyTimeout(60000);
        return rabbitTemplate;
}

@Bean(name="asyncRabbitTemplate")
public AsyncRabbitTemplate getAsyncRabbitTemplate()
{
  AsyncRabbitTemplate asyncRabbitTemplate =
    new AsyncRabbitTemplate(getRabbitTemplate(), createReplyListenerContainer());
  asyncRabbitTemplate.setAutoStartup(true);
  asyncRabbitTemplate.setReceiveTimeout(60000);
  return asyncRabbitTemplate;
}

@Bean(name="replyMessageListenerContainer")
public SimpleMessageListenerContainer createReplyListenerContainer() {
        SimpleMessageListenerContainer listenerContainer = new SimpleMessageListenerContainer();
        listenerContainer.setConnectionFactory(getConnectionFactory());
        listenerContainer.setQueueNames("replyQueue");      
        listenerContainer.setMessageListener(getRabbitTemplate());
        listenerContainer.setRabbitAdmin(getRabbitAdmin());
        listenerContainer.setAcknowledgeMode(AcknowledgeMode.AUTO);
        return listenerContainer;
}

我发现我无法成功发送消息。消费者服务器无法接收消息。

但是当我使用以下代码创建asyncRabbitTemplate实例时,我发现可以成功发送和接收消息。

@Bean(name="asyncRabbitTemplate")
public AsyncRabbitTemplate getAsyncRabbitTemplate()
{
   AsyncRabbitTemplate asyncRabbitTemplate =
            new AsyncRabbitTemplate(getConnectionFactory(),
                        "sendMessageExchange",
                        "sendMessageKey",
                        "replyQueue");
  asyncRabbitTemplate.setReceiveTimeout(60000);
  asyncRabbitTemplate.setAutoStartup(true);
  return asyncRabbitTemplate;
}

如果我的源代码有问题?

我使用了spring-boot-ampq 1.4.3.RELEASE。

1 个答案:

答案 0 :(得分:0)

这只是你的选择。

回复可以以不同的顺序返回发送。

使用异步模板,框架会为您处理相关性 - 回复将在将来由send方法返回。

当您使用自己的听众时,您必须自己处理相关性。

  

对于消息侦听器,我们可以控制相关的使用者线程,但是对于RabbitMessageFuture,后台线程无法管理。

我不明白你的意思;既然您可以将侦听器容器注入模板,那么无论如何都可以使用相同的“控件”。

修改

@SpringBootApplication
public class So41481046Application {

    public static void main(String[] args) throws Exception {
        ConfigurableApplicationContext context = SpringApplication.run(So41481046Application.class, args);
        AsyncRabbitTemplate asyncTemplate = context.getBean(AsyncRabbitTemplate.class);
        RabbitConverterFuture<String> future = asyncTemplate.convertSendAndReceive("foo");
        try {
            String out = future.get(10, TimeUnit.SECONDS);
            System.out.println(out);
        }
        finally {
            context.close();
        }
        System.exit(0);
    }

    @Bean
    public AsyncRabbitTemplate asyncTemplate(RabbitTemplate rabbitTemplate, ConnectionFactory connectionFactory) {
        rabbitTemplate.setRoutingKey(queue().getName());
        rabbitTemplate.setReplyAddress(replyQueue().getName());
        return new AsyncRabbitTemplate(rabbitTemplate, replyContainer(connectionFactory));
    }

    @Bean
    public Queue queue() {
        return new AnonymousQueue();
    }

    @Bean
    public Queue replyQueue() {
        return new AnonymousQueue();
    }

    @Bean
    public SimpleMessageListenerContainer replyContainer(ConnectionFactory connectionFactory) {
        SimpleMessageListenerContainer container = new SimpleMessageListenerContainer(connectionFactory);
        container.setQueueNames(replyQueue().getName());
        return container;
    }

    @Bean
    public SimpleMessageListenerContainer remoteContainer(ConnectionFactory connectionFactory) {
        SimpleMessageListenerContainer container = new SimpleMessageListenerContainer(connectionFactory);
        container.setQueueNames(queue().getName());
        container.setMessageListener(new MessageListenerAdapter(new Object() {

            @SuppressWarnings("unused")
            public String handleMessage(String in) {
                return in.toUpperCase();
            }

        }));
        return container;
    }

}