java spring boot amqp两个具有不同行为的监听器

时间:2016-05-17 12:40:30

标签: spring-boot spring-amqp

我是spring amqp的新手,我想创建两个具有不同行为的不同侦听器。问题是我在编译时不知道队列名称,所以我不能使用this解决方案。

我想做的事情是:阅读(然后删除)来自" sidechannel"的第一条消息。队列,它应该看起来像{"queues":["queue1","queue2"]}

现在从queue1和queue2读取(然后删除)第一条消息。在此之后,转到步骤1,阅读sidechannel的第一条消息

我尝试使用不同的侦听器创建2个SimpleMessageListenerContainer,如下面的代码所示,但它并没有像我想象的那样工作。

我的代码:

@SpringBootApplication
public class Main implements CommandLineRunner {

final static String queueName = "sidechannel";

@Autowired
AnnotationConfigApplicationContext context;

@Autowired
RabbitTemplate rabbitTemplate;

@Bean
Queue queue() {
    return new Queue(queueName, false);
}

@Bean
TopicExchange exchange() {
    return new TopicExchange("spring-boot-exchange");
}

@Bean
Binding binding(Queue queue, TopicExchange exchange) {
    return BindingBuilder.bind(queue).to(exchange).with(queueName);
}

@Bean
public ConnectionFactory rabbitConnectionFactory() {
    CachingConnectionFactory connectionFactory =
            new CachingConnectionFactory("localhost");
    connectionFactory.setUsername("guest");
    connectionFactory.setPassword("guest");
    return connectionFactory;
}

@Bean
public SimpleMessageListenerContainer messageListenerContainer() {
    SimpleMessageListenerContainer container = new SimpleMessageListenerContainer();
    container.setConnectionFactory(rabbitConnectionFactory());
    container.setQueueNames(queueName);
    container.setMessageListener(sidechannelListener());
    return container;
}

@Bean
public SimpleMessageListenerContainer messageListenerContainer2() {
    SimpleMessageListenerContainer container = new SimpleMessageListenerContainer();
    container.setConnectionFactory(rabbitConnectionFactory());
    container.setQueueNames("queue1","queue2");
    container.setMessageListener(queueListener());
    return container;
}



@Bean
public MessageListener sidechannelListener() {
    return message -> {
        String msg = new String(message.getBody());
        System.out.println(msg);
        try {
            Map<String, Object> map = jsonToMap(msg);
            for (String name : (ArrayList<String>) map.get("queues")) {
                System.out.println("Waiting for " + name + " message");
                rabbitTemplate.receive(name);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }

    };
}

@Bean
public MessageListener queueListener() {
    return message -> {
        String msg = new String(message.getBody());
        System.out.println("Received message: ");
        System.out.println(msg);
    };
}


public static void main(String[] args) throws InterruptedException {
    SpringApplication.run(Main.class, args);
}

@Override
public void run(String... args) throws Exception {
    rabbitTemplate.setReceiveTimeout(-1);

    while(true) {
        System.out.println("Waiting for side channel message");
        rabbitTemplate.receive(queueName);
    }
//        context.close();
}
}

首先,由于某种原因,sidechannel队列中的消息在处理后不会被删除。 其次,当我期待这样的输出时:

Waiting for side channel message
{"queues":["queue1","queue2"]}
Waiting for queue1 message
Received message:
"message from queue1"
Waiting for queue2 message
"message from queue2"
Waiting for side channel message

即使我在这些不同的队列上收到消息,也不会发生任何事情(因为rabbitTemplate.setReceiveTimeout(-1);),但不知怎的,它会对我收到的每条消息做出反应......

另外,我不明白的是,如果我首先向sidechannel发送消息,那么对于queue1,它就像:

Waiting for side channel message
{"queues":["queue1","queue2"]}
Waiting for queue1 message
Received message:
"message from queue1"

现在,如果我向queue1发送另一条(第二条)消息,它会打印出消息然后Waiting for queue2 message

因此需要两条消息来继续循环...我不知道我做错了什么。

1 个答案:

答案 0 :(得分:0)

你似乎在混合范式;你有一个由消息驱动的监听器容器,你也在使用轮询(template.receive())。通常,queue1,queue2的容器已经处理了来自这些队列的消息,这个

            System.out.println("Waiting for " + name + " message");
            rabbitTemplate.receive(name);
如果超时&lt;

将永久阻止0;因此原始信息永远不会被确认。