spring-amqp具有不同routingKey的多个队列

时间:2015-03-18 22:28:07

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

我最近开始学习Spring和spring-amqp所以这个问题可能看起来很基本所以请原谅我。

我有多个队列,它们位于不同的主机上,并具有不同的QueueName,RoutingKey,vhost,user,password。我正在为这些队列编写发布逻辑,但无法确定每个队列是否应该有一个配置类,还是可以用XML完成。

创建类以获取有关队列的所有信息(主机,vhost,用户名等)的方法正常工作,如this example中所述。 我创建了一个@Configuration类,并为该Queue定义了所有bean。但后来我需要做

ApplicationContext context = new AnnotationConfigApplicationContext(MyQueueConfiguration.class);
AmqpTemplate amqpTemplate  = context.getBean(AmqpTemplate.class);
amqpTemplate.convertAndSend("Hello World!!");

所以我的要求是:

  1. 由于我有许多队列需要在应用程序启动时进行实例化,所以一旦tomcat启动,就应该建立到队列/兔群集的连接/通道。
  2. 然后,只要有来自我的应用程序的POST请求,我就需要根据POST参数将消息发布到其中一个队列。
  3. 因此,对于每个队列,我总是需要这样做:

    ApplicationContext context = new AnnotationConfigApplicationContext(HelloWorldConfiguration.class);
    

    或者有没有办法让Spring加载我的所有Queue配置类,只需使用像:

    这样的对象
        // calling code when I get a POST request
    MyQueueConfigurationClass.publishMessage(payload, queueName);
    
    // The implementation code
    public boolean publishMessage(String payload, String queueName){
    
        // Get Bean for the **queueName** somehow
        AmqpTemplate amqpTemplate = context.getBean(AmqpTemplate.class);
        // Use the bean to send the message
        amqpTemplate.convertAndSend(payload);
    
    }
    
    1. 那么如何在没有new AnnotationConfigApplicationContext()的情况下每次都获取确切队列的amqpTemplate?
    2. 每次请求到我的服务时,新的AnnotationConfigApplicationContext有什么危害? [我猜测为每个请求创建一个新对象不是一个好主意]

1 个答案:

答案 0 :(得分:3)

每次都不应该创建新的上下文;这非常浪费。

您可以将多个连接工厂(每个兔主机一个)添加到根(或Web)上下文,然后使用Routing Connection FactorysendConnectionFactorySelectorExpression来选择适当的主机基于你发送的消息。

或者,您可以为每个服务器简单地连接不同的RabbitTemplate

修改

要使用SimpleRoutingConnectionFactory,请执行类似......

的操作
try {
    SimpleResourceHolder.bind(routingCF, keyForThisMessage);
    rabbitTemplate.convertAndSend(message);
}
finally {
    SimpleResourceHolder.unbind(routingCF);
}

(这适用于未经修改的RabbitTemplate)或......

<rabbit:template id="routingTemplate"
    connection-factory="rcf"
    send-connection-factory-selector-expression="messageProperties.headers['cfKey']" />

<bean id="rcf" class="org.springframework.amqp.rabbit.connection.SimpleRoutingConnectionFactory">
    <property name="targetConnectionFactories">
        <map>
            <entry key="foo" value-ref="cf1"/>
            <entry key="bar" value-ref="cf2"/>
        </map>
    </property>
    <property name="defaultTargetConnectionFactory" ref="defaultCF"/>
</bean>

......然后......

this.routingTemplate.convertAndSend("exchange", "routingKey", "xyz", new MessagePostProcessor() {

    @Override
    public Message postProcessMessage(Message message) throws AmqpException {
        message.getMessageProperties().setHeader("cfKey", "foo");
        return message;
    }

});

有一个完整的测试用例here