Skip to content

Ethan,这份笔记将从底层原理到通用代码实现,带你彻底打通 Spring Boot 的“数据流通脉络”。我们将这三者看作一个翻译系统ObjectMapper 是字典,MessageConverter 是翻译官,而 RedisTemplate 是负责记录翻译结果的档案员。


一、 ObjectMapper:全能字典 (The Core Engine)

深入浅出:

ObjectMapper 是 Jackson 库的心脏。它的唯一工作就是:把 Java 对象揉碎成 JSON 字符串(序列化),或者把 JSON 字符串拼回成 Java 对象(反序列化)。

默认情况下,这本“字典”很笨,它不知道怎么处理 Java 8 的 LocalDateTime(于是把它转成数组或时间戳),遇到 Java 对象里没有的字段还会报错。

🛠️ 通用配置代码

java
@Configuration
public class JacksonConfig {
    @Bean
    @Primary // 设置为首选 Bean,方便其他组件自动注入
    public ObjectMapper objectMapper() {
        ObjectMapper om = new ObjectMapper();

        // 1. 核心:日期时间处理模块
        JavaTimeModule javaTimeModule = new JavaTimeModule();
        // 设置序列化格式(Java -> JSON)
        javaTimeModule.addSerializer(LocalDateTime.class, 
                new LocalDateTimeSerializer(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
        // 设置反序列化格式(JSON -> Java)
        javaTimeModule.addDeserializer(LocalDateTime.class, 
                new LocalDateTimeDeserializer(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
        
        // 注册模块到字典中
        om.registerModule(javaTimeModule);

        // 2. 增强通用性与健壮性
        // 【反序列化】时:如果 JSON 里多出了字段,而 Java 类里没有,不要报错(防止接口升级导致旧代码崩溃)
        om.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
        
        // 【序列化】时:如果对象属性全是 null,不要报错(允许空对象的传输)
        om.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);

        // 3. 字段命名策略(可选):比如把 Java 的驼峰命名转为 JSON 的下划线命名
        // om.setPropertyNamingStrategy(PropertyNamingStrategies.SNAKE_CASE);

        return om;
    }
}

二、 HttpMessageConverter:Web 翻译官 (The Messenger)

深入浅出:

当你在 Controller 里写 return shop; 时,Spring MVC 并不知道怎么把这个对象发给浏览器。它会派出一个 消息转换器 (MessageConverter)

这个转换器就像一个快递员,他手里拿着你配置好的 ObjectMapper(字典),把对象翻译成 JSON 字符串,塞进 HTTP 响应体里发出去。

🛠️ 关联配置

Java

@Configuration
public class WebMvcConfig implements WebMvcConfigurer {
    @Autowired
    private ObjectMapper objectMapper;

    /**
     * 扩展消息转换器:确保全项目 Web 接口输出的 JSON 格式高度统一
     */
    @Override
    public void extendMessageConverters(List<HttpMessageConverter<?>> converters) {
        // 创建一个专用的 JSON 转换器,并塞入我们的“自定义字典”
        MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter(objectMapper);
        
        // 关键点:将它放在列表的最前面(索引 0),确保 Spring 优先用它,而不是系统默认的
        converters.add(0, converter);
    }
}

三、 RedisTemplate:仓库管理员 (The Archivist)

深入浅出:

Redis 只能存字节。RedisTemplate 的作用就是决定以什么样的姿势把对象压成字节存进去。

为了通用性,我们必须解决**“类型丢失”**的问题。如果你用普通的序列化,取出来时它可能只是一堆 LinkedHashMap,而不是你原本的 Shop 对象。

🛠️ 通用化 Redis 配置

Java

@Configuration
public class RedisConfig {

    @Bean
    public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory, ObjectMapper objectMapper) {
        RedisTemplate<String, Object> template = new RedisTemplate<>();
        template.setConnectionFactory(factory);

        // 1. 使用通用 JSON 序列化器
        // 重点:使用 GenericJackson2JsonRedisSerializer,它会在 JSON 中存入对象的 @class 类型信息
        // 这样取出来时,Jackson 才知道要把它转回哪个类,实现了真正的“通用”
        GenericJackson2JsonRedisSerializer jsonSerializer = new GenericJackson2JsonRedisSerializer(objectMapper);

        // 2. 配置 Key 和 Value 的序列化规则
        // Key 通常是字符串,使用 StringRedisSerializer
        template.setKeySerializer(RedisSerializer.string());
        template.setHashKeySerializer(RedisSerializer.string());
        
        // Value 使用上面配置好的 JSON 序列化器
        template.setValueSerializer(jsonSerializer);
        template.setHashValueSerializer(jsonSerializer);

        template.afterPropertiesSet();
        return template;
    }
}

🎯 总结:三者的深度绑定关系

组件核心职能为什么配置它?
ObjectMapper核心逻辑层定义“怎么转”。不配它,LocalDateTime 就会乱码。
MessageConverterHTTP 展现层负责“发出去”。不配它,前端拿到的数据格式不符合 UI 要求。
RedisTemplate数据持久层负责“存起来”。不配它,Redis 里的数据是一堆看不懂的乱码。

💡 Ethan,你应该如何查阅和使用这套笔记?

  1. 全局一致性:这三者通过 ObjectMapper 实现联动。你在 JacksonConfig 里改了日期格式,Web 接口和 Redis 缓存会同步改变,这叫“单一事实来源”。
  2. 通用性体现:在 RedisTemplate 中使用 GenericJackson2JsonRedisSerializer 后,你可以存入任何对象(Shop, User, Order),取出来时不需要手动强转,框架会自动根据 JSON 里的 @class 字段帮你转好。
  3. Hutool 的位置:在有了这套自动化配置后,尽量避免在 Redis 操作中手动调用 JSONUtil.toJsonStr()。直接让 RedisTemplate 帮你转,这样才能享受到我们在 JacksonConfig 里配置的各种福利。

这套体系架构是目前主流 Java 互联网项目的标准模版。配置好后,你可以把更多的精力放在业务逻辑(比如你的 RAG 学习助手)上,而不需要每天在日期格式和序列化报错上浪费时间。

在使用这套配置的过程中,关于反序列化时的 NoClassDefFound 或者 @class 注入问题,你还有什么疑虑吗?