You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spring Data Reactive Mongo中Class类型转换器配置问题

解决Spring Boot WebFlux + Reactive Mongo中Class<?>类型字段的持久化问题

看起来你遇到的核心问题是Mongo默认不支持Class<?>类型的序列化/反序列化,而你之前的自定义转换器没有限定适用场景,导致全局触发转换,干扰了其他String类型字段的正常处理。下面是一套经过验证的解决方案:

问题根源分析

  1. 你最初只定义了StringToClassConverter(用于读取Mongo数据转成Class),但缺少反向的ClassToStringConverter(用于写入时把Class转成String)。
  2. 没有给转换器标注@ReadingConverter和@WritingConverter注解,导致Spring的转换服务把它们当成全局转换器,在处理其他String字段(比如name)时错误触发String转Class的逻辑,引发报错。

正确配置方案

我们可以通过Spring Data Mongo的自定义转换机制来实现,无需自定义Mongo Codec(这种方式更贴合Spring生态,兼容性更好)。

步骤1:修正实体类(可选但建议)

给inputClass字段加上泛型,避免类型警告:

import lombok.Data;
import org.springframework.data.annotation.Id;

@Data
public class ServiceEntity {
    @Id
    private String id;
    private String name;
    private Class<?> inputClass; // 明确泛型类型
}

步骤2:创建双向转换器并标注场景

分别定义读、写转换器,用注解限定它们只在Mongo数据读写时生效:

import org.springframework.core.convert.converter.Converter;
import org.springframework.data.convert.ReadingConverter;
import org.springframework.data.convert.WritingConverter;

// 读取Mongo中的字符串,转成Class<?>
@ReadingConverter
public class StringToClassConverter implements Converter<String, Class<?>> {
    @Override
    public Class<?> convert(String source) {
        try {
            return Class.forName(source);
        } catch (ClassNotFoundException e) {
            throw new IllegalArgumentException("无法将字符串转换为Class: " + source, e);
        }
    }
}

// 将实体中的Class<?>,转成Mongo存储的字符串
@WritingConverter
public class ClassToStringConverter implements Converter<Class<?>, String> {
    @Override
    public String convert(Class<?> source) {
        return source.getName();
    }
}

步骤3:注册自定义转换器到Spring容器

修改你的Mongo配置类,只需要注册MongoCustomConversions Bean即可,无需自定义CodecRegistry:

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.mongodb.core.convert.MongoCustomConversions;

import java.util.Arrays;

@Configuration
public class MongoConfiguration {

    @Bean
    public MongoCustomConversions mongoCustomConversions() {
        return new MongoCustomConversions(Arrays.asList(
                new StringToClassConverter(),
                new ClassToStringConverter()
        ));
    }
}

为什么这样能解决问题?

  • @ReadingConverter和@WritingConverter注解告诉Spring Data Mongo:这些转换器仅用于Mongo与实体之间的类型转换,不会干扰其他全局转换逻辑。
  • 双向转换器覆盖了读写全流程:写入时Class<?>会被序列化为类的全限定名存储到Mongo;读取时Mongo中的字符串会被反序列化为对应的Class<?>对象。
  • 无需自定义Mongo Codec,Spring Data的转换机制会自动处理Reactive场景下的数据流。

注意事项

确保你存储的类全限定名对应的类,在应用运行时能被类加载器找到,否则Class.forName()会抛出ClassNotFoundException。

内容的提问来源于stack exchange,提问作者Bullet-tooth

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.28 09:54:24