Spring Data Reactive Mongo中Class类型转换器配置问题
解决Spring Boot WebFlux + Reactive Mongo中
Class<?>类型字段的持久化问题 看起来你遇到的核心问题是Mongo默认不支持Class<?>类型的序列化/反序列化,而你之前的自定义转换器没有限定适用场景,导致全局触发转换,干扰了其他String类型字段的正常处理。下面是一套经过验证的解决方案:
问题根源分析
- 你最初只定义了
StringToClassConverter(用于读取Mongo数据转成Class),但缺少反向的ClassToStringConverter(用于写入时把Class转成String)。 - 没有给转换器标注
@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
相关产品推荐
相关产品推荐

