背景
在Java项目中,我们使用RabbitMQ发送消息的时候,一般采用RabbitTemplate,比如采用convertAndSend方法发送一个简单的字符串消息,这个时候我们会发现,消费者的MessageId是null,也就是MessageId没有被赋值,这对于我们想做幂等性判断的场景下,无法使用。那原因是什么,如何解决的呢?
首先我们看下convertAndSend方法做了哪些事情
public void convertAndSend(String routingKey, Object object) {
this.convertAndSend(this.exchange, routingKey, object, (CorrelationData)null);
}
public void convertAndSend(String exchange, String routingKey, Object object, @Nullable CorrelationData correlationData) {
this.send(exchange, routingKey, this.convertMessageIfNecessary(object), correlationData);
}
protected Message convertMessageIfNecessary(Object object) {
return object instanceof Message ? (Message)object : this.getRequiredMessageConverter().toMessage(object, new MessageProperties());
}
我们会看到,消息发送,最终要转换为Message对象,也就是调用convertMessageIfNecessary方法,而这个方法需要获取Converter,并且调用toMessage方法转换为Message对象。
private MessageConverter messageConverter = new SimpleMessageConverter();
private MessageConverter getRequiredMessageConverter() throws IllegalStateException {
return this.getMessageConverter();
}
public MessageConverter getMessageConverter() {
return this.messageConverter;
}
我们发现获取的Converter最终是SimpleMessageConverter,而父类是AbstractMessageConverter,具体代码如下:
public abstract class AbstractMessageConverter implements MessageConverter {
private boolean createMessageIds = false;
public void setCreateMessageIds(boolean createMessageIds) {
this.createMessageIds = createMessageIds;
}
public final Message toMessage(Object object, @Nullable MessageProperties messagePropertiesArg, @Nullable Type genericType) throws MessageConversionException {
MessageProperties messageProperties = messagePropertiesArg;
if (messageProperties == null) {
messageProperties = new MessageProperties();
}
Message message = this.createMessage(object, messageProperties, genericType);
messageProperties = message.getMessageProperties();
if (this.createMessageIds && messageProperties.getMessageId() == null) {
messageProperties.setMessageId(UUID.randomUUID().toString());
}
return message;
}
}
我们发现setMessageId有个条件createMessageIds,默认是false,所以只需要解决这个就可以了,比如在获取RabbitTemplate的时候,设置为true
RabbitTemplate rabbitTemplate = new RabbitTemplate();
((AbstractMessageConverter) rabbitTemplate.getMessageConverter()).setCreateMessageIds(true);