我将RabbitTemplate发送消息与自己生成的CorrelationData一起使用。我已经在cofirmCallBack中收到了correlationId,但是在消费者端却无法收到它。
我用2.0.3.RELEASE和2.1.0.RELEASE测试了这个问题,结果与上面的描述一致。
rabbitmq配置
@Configuration
public class RabbitMQConfig {
@Value("${mq.rabbit.addresses}")
private String addresses;
@Value("${mq.rabbit.username}")
private String username;
@Value("${mq.rabbit.password}")
private String password;
@Value("${mq.rabbit.virtualHost}")
private String virtualHost;
@Value("${mq.rabbit.sessionCacheSize}")
private int sessionCacheSize;
@Bean
public ConnectionFactory connectionFactory() {
CachingConnectionFactory connectionFactory = new CachingConnectionFactory();
connectionFactory.setAddresses(addresses);// addresses list of addresses with form "host[:port],..."
connectionFactory.setVirtualHost(virtualHost);
connectionFactory.setPublisherConfirms(true);
connectionFactory.setPublisherReturns(true);
connectionFactory.setChannelCacheSize(sessionCacheSize);
connectionFactory.setUsername(username);
connectionFactory.setPassword(password);
return connectionFactory;
}
@Bean
@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
public RabbitTemplate rabbitTemplate(MessageConverter messageConverter) {
RabbitTemplate template = new RabbitTemplate(connectionFactory());
template.setMessageConverter(messageConverter);
template.setMandatory(true);
template.setConfirmCallback(new ConfirmCallbackListener());
template.setReturnCallback(new ReturnCallBackListener());
return template;
}
@Bean
public MessageConverter messageConverter(ObjectMapper customMapper) {
return new Jackson2JsonMessageConverter(customMapper);
}
@Bean
public Queue testQueue() {
return new Queue("test-queue", true);
}
@Bean
public TopicExchange defaultExchange() {
return new TopicExchange("test-exchange", true, false);
}
@Bean
public Binding bindingExchangeCommon(Queue testQueue, TopicExchange defaultExchange) {
return BindingBuilder.bind(testQueue).to(defaultExchange).with("test");
}
@Bean
public SimpleMessageListenerContainer testMessageContainer(ConnectionFactory connectionFactory) {
SimpleMessageListenerContainer container = new SimpleMessageListenerContainer(connectionFactory);
container.setQueueNames("test-queue");
container.setExposeListenerChannel(true);
container.setPrefetchCount(250);
container.setMaxConcurrentConsumers(20);
container.setConcurrentConsumers(10);
container.setAcknowledgeMode(AcknowledgeMode.MANUAL);
container.setMessageListener(new TestMessageListener());
return container;
}
}
确认回调
public class ConfirmCallbackListener implements RabbitTemplate.ConfirmCallback {
private Logger logger = LoggerFactory.getLogger(this.getClass());
@Override
public void confirm(CorrelationData correlationData, boolean ack, String cause) {
if(!ack) {
logger.info("send message ack failed: " + cause + " -> ID: " + String.valueOf(correlationData));
}else {
logger.info("send message ack success -> ID: " + String.valueOf(correlationData));
}
}
}
返回回调
public class ReturnCallBackListener implements RabbitTemplate.ReturnCallback{
private Logger logger = LoggerFactory.getLogger(this.getClass());
@Override
public void returnedMessage(Message message, int replyCode, String replyText, String exchange, String routingKey) {
logger.info("send message failed...");
}
}
消息监听器
public class TestMessageListener implements ChannelAwareMessageListener {
private Logger logger = LoggerFactory.getLogger(this.getClass());
@Override
public void onMessage(Message message, Channel channel) throws Exception {
try {
// Here: get CorrelationId is always null
logger.info("handle message: {} -> ID: {}" , new String(message.getBody(), "UTF-8"),
message.getMessageProperties().getCorrelationId());
if(true) {
channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);
logger.info("listener ack message completed");
}else {
channel.basicNack(message.getMessageProperties().getDeliveryTag(), false, true);
}
} catch (Exception e) {
logger.error("handle test message error", e);
channel.basicNack(message.getMessageProperties().getDeliveryTag(), false, false);
}
}
}
发送消息
@RestController
@RequestMapping("/rabbitmq")
public class RabbitmqCtrl {
private AtomicLong atoId = new AtomicLong();
@Resource
private RabbitTemplate rabbitTemplate;
@PostMapping("sendMsg")
public String sendMsg(@RequestBody String content) {
Message message = new Message();
message.setId(String.valueOf(atoId.incrementAndGet()));
message.setContent(content);
rabbitTemplate.convertAndSend("test-exchange", "test", message, new CorrelationData(String.valueOf(atoId.get())));
return "success";
}
}
我尝试将CorrelationDataPostProcessor设置为RabbitTemplate,如下所示:
template.setCorrelationDataPostProcessor(new CorrelationDataPostProcessor() {
@Override
public CorrelationData postProcess(Message message, CorrelationData correlationData) {
if(correlationData != null) {
message.getMessageProperties().setCorrelationId(correlationData.getId());
}
return correlationData;
}
});
通过这种方式,我可以获得CorelationID,但是我认为由于在发送消息时已经设置了ID,所以我不必这样做。还有其他更合理的解释吗?
答案 0 :(得分:1)
<DataTrigger Binding="{Binding ElementName=MyWPFCombo, Path=SelectedValue}" Value="10">
<Setter Property="Text" Value="Select the old items:" />
</DataTrigger>
不会通过网络发送,除非您使用自定义CorrelationData
明确声明,就像您对MessagePostProcessor
所做的那样。
默认实现是这样的:
CorrelationDataPostProcessor
您看到default Message postProcessMessage(Message message, Correlation correlation) {
return postProcessMessage(message);
}
被完全忽略。
因此,要向用户端发送相关信息,我们实际上必须提供自定义correlation
并将其注入MessagePostProcessor
中。