以下是详细聊聊RabbitMQ竟无法反序列化List问题的完整攻略,包含两个示例说明。
问题描述
在使用RabbitMQ时,有时会遇到无法反序列化List的问题。具体来说,当您尝试从RabbitMQ队列中读取包含List的消息时,您可能会遇到以下异常:
com.rabbitmq.client.ShutdownSignalException: channel error; protocol method: #method<channel.close>(reply-code=406, reply-text=PRECONDITION_FAILED - inequivalent arg 'durable' for queue 'my_queue' in vhost '/': received 'false' but current is 'true', class-id=50, method-id=10)
这是因为RabbitMQ无法正确地反序列化List,导致消息无法正确地读取。
解决方案
为了解决这个问题,您可以使用以下两种方法:
方法1:将List转换为JSON字符串
在发送消息之前,将List转换为JSON字符串。这样,您可以将JSON字符串发送到RabbitMQ队列中,然后在接收消息时将其转换回List。以下是一个简单的示例:
// 发送消息
List<String> list = Arrays.asList("Hello", "World");
String json = new Gson().toJson(list);
rabbitTemplate.convertAndSend("my_exchange", "my_routing_key", json);
// 接收消息
String json = (String) rabbitTemplate.receiveAndConvert("my_queue");
List<String> list = new Gson().fromJson(json, new TypeToken<List<String>>(){}.getType());
方法2:使用自定义序列化器
您可以使用自定义序列化器来解决这个问题。以下是一个简单的示例:
public class ListSerializer implements Serializer<List<?>> {
private final Gson gson = new Gson();
@Override
public byte[] serialize(List<?> list) throws SerializationException {
String json = gson.toJson(list);
return json.getBytes();
}
@Override
public List<?> deserialize(byte[] bytes) throws SerializationException {
String json = new String(bytes);
return gson.fromJson(json, new TypeToken<List<?>>(){}.getType());
}
}
然后,在您的Java代码中,您需要使用自定义序列化器。以下是一个简单的示例:
@Configuration
public class RabbitMQConfig {
@Bean
public Queue myQueue() {
return new Queue("my_queue", true);
}
@Bean
public DirectExchange myExchange() {
return new DirectExchange("my_exchange");
}
@Bean
public Binding myBinding() {
return BindingBuilder.bind(myQueue()).to(myExchange()).with("my_routing_key");
}
@Bean
public MessageConverter messageConverter() {
return new SimpleMessageConverter() {
@Override
protected Object convertPayload(Message message) throws IOException {
if (message.getMessageProperties().getContentType().equals("application/json")) {
return new Gson().fromJson(new String(message.getBody()), new TypeToken<List<?>>(){}.getType());
}
return super.convertPayload(message);
}
};
}
@Bean
public RabbitTemplate rabbitTemplate(ConnectionFactory connectionFactory, MessageConverter messageConverter) {
RabbitTemplate rabbitTemplate = new RabbitTemplate(connectionFactory);
rabbitTemplate.setMessageConverter(messageConverter);
return rabbitTemplate;
}
@Bean
public SimpleRabbitListenerContainerFactory rabbitListenerContainerFactory(ConnectionFactory connectionFactory, MessageConverter messageConverter) {
SimpleRabbitListenerContainerFactory factory = new SimpleRabbitListenerContainerFactory();
factory.setConnectionFactory(connectionFactory);
factory.setMessageConverter(messageConverter);
return factory;
}
}
然后,在您的Java代码中,您需要使用自定义序列化器。以下是一个简单的示例:
@Autowired
private RabbitTemplate rabbitTemplate;
public void sendMessage(List<String> list) {
rabbitTemplate.convertAndSend("my_exchange", "my_routing_key", list, message -> {
message.getMessageProperties().setContentType("application/json");
return message;
});
}
@RabbitListener(queues = "my_queue")
public void receiveMessage(List<String> list) {
System.out.println("Received message: " + list);
}
总结
无法反序列化List是RabbitMQ中的一个常见问题。为了解决这个问题,您可以使用两种方法:将List转换为JSON字符串或使用自定义序列化器。无论您选择哪种方法,都需要确保您的代码能够正确地读取和写入List。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:详细聊聊RabbitMQ竟无法反序列化List问题 - Python技术站