私はamqpを春にして新しく、異なる動作をする2つの異なるリスナーを作成したいと思います。問題は、コンパイル時にキュー名がわからないため、thisソリューションを使用できないことです。java spring boot amqp異なる動作をする2つのリスナー
私がしたいことは、「サイドチャネル」キューから最初のメッセージを読み込んだり(削除して)、これは{"queues":["queue1","queue2"]}
のようになります。
ここで、最初のメッセージをqueue1とqueue2から読み取ってから削除します。その後、手順1に進み、サイドチャネルの最初のメッセージを読む
以下のコードで見られるように、2つのSimpleMessageListenerContainersを別のリスナーで作成しようとしましたが、思った通りに動作しません。
マイコード:
@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"
とし、今、私は別のものを送信する場合(A秒)メッセージをqueue1に送信すると、th eメッセージに続いてWaiting for queue2 message
と入力します。
サイクルを続けるには2つのメッセージが必要です...私は何が間違っているのか分かりません。
私はあまりにも複雑に見えますが、なぜあなたは構成を使っていませんか?起動時にキュー名を指定します(Exchangeに配置できる場合は、プロパティファイルに配置することもできます)。 –
私は言ったように、私はamqpを芽生えるのが初めてで、それを理解するのがまだ難しいので、非常に複雑かもしれません。しかし、私はコンパイル時にキュー名を知らないので、それらをプロパティファイルに追加することはできませんか、間違っていますか?とにかくゲイリーの答えは、私が問題を解決するのに役立ちました、あなたの返信に感謝:) –
あなたはコンパイル時にそれらを知る必要はありません。私はリファレンスガイドを読むことをお勧めします。あなたは起動時にプロパティを提供することができ、プロパティは後で定義することができ、固定プロパティ名のみが必要です。 –