Spring Boot中如何通过JMS消息转换器实现Java对象与JSON互转
1. 消息体Java对象的注解要求
如果POJO严格符合JavaBean规范(提供public无参构造方法、所有需要序列化的字段提供对应public getter/setter方法),不需要强制添加任何注解即可完成基础JSON双向转换。生产环境推荐添加1个实用注解避免异常:
@JsonIgnoreProperties(ignoreUnknown = true):加在类上,反序列化时自动忽略JSON中存在但Java类未定义的字段,避免因消息携带冗余字段抛出反序列化错误- (可选)
@JsonProperty("自定义字段名"):加在字段上,仅当JSON字段名和Java字段名不一致时做映射,无自定义映射需求可不加
如果使用Lombok简化代码,可按需添加@Data、@NoArgsConstructor、@AllArgsConstructor自动生成getter/setter、构造方法,这类注解属于代码简化工具注解,不属于JMS/Jackson的强制要求。
2. 消息转换器选型
直接选用Spring官方提供的MappingJackson2MessageConverter即可。该转换器基于Jackson JSON库实现,自动完成Java对象到JSON格式TextMessage的序列化、以及JSON TextMessage到Java对象的反序列化,和JmsTemplate、@JmsListener适配度最高,无额外兼容问题。
注意:不要使用已废弃的
MappingJacksonMessageConverter,该实现是为Jackson 1.x版本设计的旧组件,早已停止维护。
本方案使用嵌入式内存ActiveMQ作为消息中间件,无需额外部署外部MQ,启动即可直接运行。
第一步:引入Maven依赖
<dependencies> <!-- Spring JMS + 嵌入式ActiveMQ starter --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-activemq</artifactId> </dependency> <!-- Jackson JSON序列化依赖,引入spring-boot-starter-web可自动引入,无web依赖则手动添加 --> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-databind</artifactId> </dependency> <!-- Lombok可选,不想用可以手动写getter/setter、构造方法 --> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <optional>true</optional> </dependency> </dependencies>
第二步:添加应用配置
在application.yml中添加如下配置:
spring: activemq: broker-url: vm://embedded?broker.persistent=false # 启用嵌入式内存MQ,不持久化消息 packages: trust-all: true # 开发环境可开启全类信任,生产环境请替换为trusted配置指定具体包路径 jms: template: default-destination: test-json-queue # 默认发送队列名 listener: acknowledge-mode: auto
生产环境建议关闭
trust-all配置,通过spring.activemq.packages.trusted指定具体信任的实体类包路径,避免反序列化安全风险。
第三步:配置JMS消息转换器
编写JMS配置类,注册JSON转换器并绑定到JMS组件:
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.jms.annotation.EnableJms; import org.springframework.jms.core.JmsTemplate; import org.springframework.jms.support.converter.MappingJackson2MessageConverter; import org.springframework.jms.support.converter.MessageConverter; import org.springframework.jms.support.converter.MessageType; import jakarta.jms.ConnectionFactory; @Configuration @EnableJms // 开启JMS注解监听支持 public class JmsConfig { @Bean public MessageConverter jacksonJmsMessageConverter() { MappingJackson2MessageConverter converter = new MappingJackson2MessageConverter(); // 转换后的消息存为文本类型,JSON内容写入TextMessage converter.setTargetType(MessageType.TEXT); // 存储Java类型标识的消息属性名,反序列化时自动识别对应实体类型 converter.setTypeIdPropertyName("_type"); return converter; } @Bean public JmsTemplate jmsTemplate(ConnectionFactory connectionFactory, MessageConverter messageConverter) { JmsTemplate jmsTemplate = new JmsTemplate(connectionFactory); jmsTemplate.setMessageConverter(messageConverter); return jmsTemplate; } }
如果使用Spring Boot 2.x版本,将上述代码中
jakarta.jms.ConnectionFactory替换为javax.jms.ConnectionFactory即可,其余代码无差异。
第四步:定义消息实体类
import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; import java.io.Serializable; import java.time.LocalDateTime; @Data @NoArgsConstructor @AllArgsConstructor @JsonIgnoreProperties(ignoreUnknown = true) public class UserMessage implements Serializable { private Long userId; private String content; private LocalDateTime sendTime; }
不使用Lombok的话,手动生成无参构造、全参构造、所有字段的getter/setter、toString方法即可,功能完全一致。
第五步:实现消息生产者
直接通过JmsTemplate发送Java对象,转换器会自动完成对象转JSON的逻辑:
import org.springframework.jms.core.JmsTemplate; import org.springframework.stereotype.Component; @Component public class MessageProducer { private final JmsTemplate jmsTemplate; public MessageProducer(JmsTemplate jmsTemplate) { this.jmsTemplate = jmsTemplate; } public void sendUserMessage(UserMessage message) { jmsTemplate.convertAndSend(message); System.out.printf("发送消息成功:%s%n", message); } }
第六步:实现消息消费者
通过@JmsListener监听队列,方法参数直接用实体类接收,转换器会自动完成JSON转对象的逻辑:
import org.springframework.jms.annotation.JmsListener; import org.springframework.stereotype.Component; @Component public class MessageConsumer { @JmsListener(destination = "test-json-queue") public void receiveUserMessage(UserMessage message) { System.out.printf("收到消息,自动转换为UserMessage对象:%s%n", message); System.out.printf("字段读取结果:userId=%d,内容=%s,发送时间=%s%n", message.getUserId(), message.getContent(), message.getSendTime()); } }
第七步:编写启动类测试
import org.springframework.boot.CommandLineRunner; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import java.time.LocalDateTime; @SpringBootApplication public class JmsJsonDemoApplication implements CommandLineRunner { private final MessageProducer messageProducer; public JmsJsonDemoApplication(MessageProducer messageProducer) { this.messageProducer = messageProducer; } public static void main(String[] args) { SpringApplication.run(JmsJsonDemoApplication.class, args); } @Override public void run(String... args) { // 应用启动后构造测试对象发送 UserMessage testMsg = new UserMessage( 1001L, "JMS JSON双向转换测试消息", LocalDateTime.now() ); messageProducer.sendUserMessage(testMsg); } }
运行验证
直接启动应用,控制台会输出如下日志,说明双向转换流程正常:
发送消息成功:UserMessage(userId=1001, content=JMS JSON双向转换测试消息, sendTime=2024-05-20T16:20:33.125) 收到消息,自动转换为UserMessage对象:UserMessage(userId=1001, content=JMS JSON双向转换测试消息, sendTime=2024-05-20T16:20:33.125) 字段读取结果:userId=1001,内容=JMS JSON双向转换测试消息,发送时间=2024-05-20T16:20:33.125
全程无需手动编写JSON序列化/反序列化逻辑,转换器会自动完成Java对象和JSON的双向映射。
内容的提问来源于stack exchange,提问作者Edie Reynolds

