JSON 序列化
JSON是RabbitMQ消息体的常用格式,需在发送前序列化对象、接收后反序列化还原。
定义
JSON序列化将Java对象转换为JSON字节数组作为消息体,接收方将字节数组还原为Java对象。相比原生Java序列化,JSON具备跨语言兼容与可读性强的优势。
Maven 依赖
XML
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.15.2</version>
</dependency>
序列化与反序列化工具类
Java
import com.fasterxml.jackson.databind.ObjectMapper;
public class JsonSerializer {
private static final ObjectMapper MAPPER = new ObjectMapper();
// 对象转JSON字节数组
public static byte[] serialize(Object obj) throws Exception {
return MAPPER.writeValueAsBytes(obj);
}
// JSON字节数组转对象
public static <T> T deserialize(byte[] data, Class<T> clazz) throws Exception {
return MAPPER.readValue(data, clazz);
}
}
发送端示例
Java
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;
public class JsonProducer {
private static final String QUEUE_NAME = "json_queue";
public static void main(String[] args) throws Exception {
ConnectionFactory factory = new ConnectionFactory();
factory.setHost("localhost");
try (Connection connection = factory.newConnection();
Channel channel = connection.createChannel()) {
channel.queueDeclare(QUEUE_NAME, false, false, false, null);
// 构建消息对象
OrderMessage order = new OrderMessage("ORD-001", "iPhone 15", 1, 7999.0);
// 序列化为JSON字节数组
byte[] body = JsonSerializer.serialize(order);
// 设置content_type标识
channel.basicPublish("", QUEUE_NAME,
createJsonProperties(), body);
System.out.println("已发送订单消息: " + order);
}
}
private static com.rabbitmq.client.AMQP.BasicProperties createJsonProperties() {
return new com.rabbitmq.client.AMQP.BasicProperties.Builder()
.contentType("application/json")
.contentEncoding("UTF-8")
.build();
}
}
// 消息实体类
class OrderMessage {
private String orderId;
private String productName;
private int quantity;
private double price;
public OrderMessage() {}
public OrderMessage(String orderId, String productName, int quantity, double price) {
this.orderId = orderId;
this.productName = productName;
this.quantity = quantity;
this.price = price;
}
// getter/setter省略
public String getOrderId() { return orderId; }
public void setOrderId(String orderId) { this.orderId = orderId; }
public String getProductName() { return productName; }
public void setProductName(String productName) { this.productName = productName; }
public int getQuantity() { return quantity; }
public void setQuantity(int quantity) { this.quantity = quantity; }
public double getPrice() { return price; }
public void setPrice(double price) { this.price = price; }
@Override
public String toString() {
return "OrderMessage{" + "orderId='" + orderId + "', productName='" + productName + "'}";
}
}
接收端示例
Java
import com.rabbitmq.client.*;
import java.io.IOException;
public class JsonConsumer {
private static final String QUEUE_NAME = "json_queue";
public static void main(String[] args) throws Exception {
ConnectionFactory factory = new ConnectionFactory();
factory.setHost("localhost");
try (Connection connection = factory.newConnection();
Channel channel = connection.createChannel()) {
channel.queueDeclare(QUEUE_NAME, false, false, false, null);
DeliverCallback deliverCallback = (consumerTag, delivery) -> {
byte[] body = delivery.getBody();
try {
// 反序列化为订单对象
OrderMessage order = JsonSerializer.deserialize(body, OrderMessage.class);
System.out.println("收到订单消息: " + order);
// 验证content_type
String contentType = delivery.getProperties().getContentType();
if (!"application/json".equals(contentType)) {
System.err.println("警告: 消息类型不匹配, 期望 application/json, 实际: " + contentType);
}
channel.basicAck(delivery.getEnvelope().getDeliveryTag(), false);
} catch (Exception e) {
System.err.println("JSON反序列化失败: " + e.getMessage());
channel.basicNack(delivery.getEnvelope().getDeliveryTag(), false, false);
}
};
channel.basicConsume(QUEUE_NAME, false, deliverCallback, consumerTag -> {});
}
}
}
注意事项
必须在消息属性中设置
contentType = "application/json",以便消费者识别消息格式并做相应处理。
Jackson默认要求实体类有无参构造函数,否则需配置Creator或使用@JsonCreator注解。
JSON序列化不包含类型信息,反序列化时需明确指定目标类型,或使用
@JsonTypeInfo注解保留类型。
对于包含敏感信息的字段,使用
@JsonIgnore或@JsonProperty(access = Access.WRITE_ONLY)避免序列化。
Jackson 高级配置
Java
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
public class AdvancedJsonSerializer {
private static final ObjectMapper MAPPER;
static {
MAPPER = new ObjectMapper();
// 忽略未知字段
MAPPER.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
// 格式化日期
MAPPER.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);
// 支持Java 8时间
MAPPER.registerModule(new JavaTimeModule());
}
public static byte[] serialize(Object obj) throws Exception {
return MAPPER.writeValueAsBytes(obj);
}
public static <T> T deserialize(byte[] data, Class<T> clazz) throws Exception {
return MAPPER.readValue(data, clazz);
}
}
要点总结
- JSON序列化将对象转换为字节数组,作为RabbitMQ消息体传输
- 发送端序列化,接收端反序列化,需保持序列化配置一致
- 必须设置
contentType = "application/json"标识消息格式 - Jackson是主流选择,需配置无参构造函数或Creator
- 反序列化时验证contentType可避免格式不匹配错误
- 高级场景需配置日期格式、Java 8时间支持、忽略未知字段等
📝 发现内容有误?点击此处直接编辑