RabbitMQ - Java Spring - 如何初始化多个队列?

时间:2016-06-19 10:04:27

标签: java spring spring-boot rabbitmq

我很难找到Spring方法来初始化一个将传入消息发送到多个队列的交换 - 在我的Spring-boot应用程序上:

我找不到定义秒交换队列绑定的好方法。

我正在使用RabbitTemplate作为制作人客户端。

RabbitMQ 6页面教程对此没有任何帮助,因为:

  1. 来自Consumer on-demand的唯一初始几个临时队列(虽然我需要生产者来执行绑定 - 持久队列)
  2. 这些示例适用于基本的Java用法 - 不使用Spring功能。
  3. 我也没能找到如何通过Spring AMQP页面实现它。

    我到目前为止所做的是尝试将基本的java绑定注入到弹簧的方式 - 但它不起作用....

    @Bean
    public ConnectionFactory connectionFactory() throws IOException {
        CachingConnectionFactory connectionFactory = new CachingConnectionFactory("localhost");
        connectionFactory.setUsername("guest");
        connectionFactory.setPassword("guest");
    
        Connection conn = connectionFactory.createConnection();
        Channel channel = conn.createChannel(false);
    
        channel.exchangeDeclare(SPRING_BOOT_EXCHANGE, "fanout");
        channel.queueBind(queueName, SPRING_BOOT_EXCHANGE, ""); //first bind
        channel.queueBind(queueName2, SPRING_BOOT_EXCHANGE, "");// second bind
    
        return connectionFactory;
    }
    

    任何帮助将不胜感激

    被修改

    认为问题出现的事实是,每次我重新启动服务器时,它都会尝试重新定义交换查询绑定 - 而它们会在代理中持续存在... 我设法通过代理UI控制台手动定义它们 - 因此Producer只知道交换名称,而Consumer只知道它的相关队列。 有没有办法以渐进方式定义这些元素 - 但是这样一来,如果以前的重新启动已经存在,它将不会被重新定义\覆盖?

2 个答案:

答案 0 :(得分:1)

我们使用类似于以下的方法将数据从一个特定的输入通道发送到其他消费者的几个输入队列:

@Bean
public IntegrationFlow integrationFlow(final RabbitTemplate rabbitTemplate, final AmqpHeaderMapper amqpHeaderMapper) {
    IntegrationFlows
        .from("some-input-channel")
        .handle(Amqp.outboundAdapter(rabbitTemplate)
        .headerMapper(headerMapper))
        .get()    
}

@Bean
public AmqpHeaderMapper amqpHeaderMapper() {
    final DefaultAmqpHeaderMapper headerMapper = new DefaultAmqpHeaderMapper();
    headerMapper.setRequestHeaderNames("*");
    return headerMapper;
}

@Bean
public ConnectionFactory rabbitConnectionFactory() {
   return new CachingConnectionFactory();
}

@Bean
public RabbitAdmin rabbitAdmin(final ConnectionFactory rabbitConnectionFactory) {
    final RabbitAdmin rabbitAdmin = new RabbitAdmin(rabbitConnectionFactory);
    rabbitAdmin.afterPropertiesSet();
    return rabbitAdmin;
}

@Bean
public RabbitTemplate rabbitTemplate(final ConnectionFactory rabbitConnectionFactory, final RabbitAdmin rabbitAdmin) {
    final RabbitTemplate rabbitTemplate = new RabbitTemplate();
    rabbitTemplate.setConnectionFactory(connectionFactory);

    final FanoutExchange fanoutExchange = new FanoutExchange(MY_FANOUT.getFanoutName());
    fanoutExchange.setAdminsThatShouldDeclare(rabbitAdmin);
    for (final String queueName : MY_FANOUT.getQueueNames) {
        final Queue queue = new Queue(queueName, true);
        queue.setAdminsThatShouldDeclare(rabbitAdmin);

        final Binding binding = BindingBuilder.bind(queue).to(fanoutExchange);
        binding.setAdminsThatShouldDeclare(rabbitAdmin);
    }
    rabbitTemplate.setExchange(fanoutExchange);    
}

为了完整性,这里是扇出声明的枚举:

public enum MyFanout {
    MY_FANOUT(Lists.newArrayList("queue1", "queue2"), "my-fanout"),

    private final List<String> queueNames;
    private final String fanoutName;

    MyFanout(final List<String> queueNames, final String fanoutName) {
        this.queueNames = requireNonNull(queueNames, "queue must not be null!");
        this.fanoutName = requireNonNull(fanoutName, "exchange must not be null!");
    }

    public List<String> getQueueNames() {
        return this.queueNames;
    }

    public String getFanoutName() {
        return this.fanoutName;
    }
}

希望它有所帮助!

答案 1 :(得分:0)

谢谢! 这就是我一直在寻找的答案。 另外 - 为了完整起见 - 我在Spring Bean中找到了一种“java方式”的方法:

  @Bean
public ConnectionFactory connectionFactory() throws IOException {
    CachingConnectionFactory connectionFactory = new CachingConnectionFactory("localhost");
    connectionFactory.setUsername("guest");
    connectionFactory.setPassword("guest");

    Connection conn = connectionFactory.createConnection();
    Channel channel = conn.createChannel(false);

    // declare exchnage
    AMQP.Exchange.DeclareOk resEx = channel.exchangeDeclare(AmqpTemp.SPRING_BOOT_EXCHANGE_test, ExchangeTypes.FANOUT, true, false, false, null);

    // declares queues
    AMQP.Queue.DeclareOk resQ = channel.queueDeclare(AmqpTemp.Q2, true, false, false, null);
    resQ = channel.queueDeclare(AmqpTemp.Q3, true, false, false, null);

    // declare binding
    AMQP.Queue.BindOk resB = channel.queueBind(AmqpTemp.Q2, AmqpTemp.SPRING_BOOT_EXCHANGE_test, "");
    resB = channel.queueBind(AmqpTemp.Q3, AmqpTemp.SPRING_BOOT_EXCHANGE_test, "");
    // channel.queueBind(queueName2, SPRING_BOOT_EXCHANGE, "");

    return connectionFactory;
}

我之前遇到过的问题是,我在初次使用代码时创建了一些队列 - 当我尝试重用相同的队列名称时,它会导致异常,因为它们最初的定义不同 - 所以 - 吸取的经验教训:从您使用代码“玩”时使用的名称重命名队列。