首页 文章

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

提问于
浏览
1

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

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

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

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

所以我的要求是:

  • 由于我有许多需要在应用程序启动时实例化的队列,所以一旦tomcat启动,就应 Build 到队列/兔群集的连接/通道 .

  • 然后,只要有来自我的应用程序的POST请求,我就需要根据POST参数将消息发布到其中一个队列 .

所以对于每个队列,我总是需要这样做:

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);

}
  • 那么如何在不执行 new AnnotationConfigApplicationContext() 的情况下获取完整队列的amqpTemplate?

  • 每次请求到我的服务时,新的AnnotationConfigApplicationContext有什么危害? [我猜测为每个请求创建一个新对象不是一个好主意]

1 回答

  • 3

    你不应该每次都创建一个新的上下文;这很浪费 .

    您可以将多个连接工厂(每个兔主机一个)添加到根(或Web)上下文,然后使用Routing Connection FactorysendConnectionFactorySelectorExpression 根据您发送的消息选择正确的主机 .

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

    EDIT

    要使用 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 .

相关问题