定义多个目标类型为Optional的Spring Converter遇到问题
这个问题我之前也碰到过,根源在于Spring 1.5.x版本的Converter注册机制对泛型类型的处理限制:当你实现Converter<String, Optional<SomeType>>和Converter<String, Optional<OtherType>>时,Spring会忽略泛型参数,把它们都识别为Converter<String, Optional>类型,导致后注册的Converter覆盖掉前面的,最终只有一个生效。
下面给你两种可行的解决方案,优先推荐第一种:
方案一:利用Spring自带的OptionalConverterFactory(推荐)
Spring Boot默认已经内置了OptionalConverterFactory,它会自动适配普通类型的Converter来处理Optional转换。你完全不需要自己写针对Optional的Converter,只需要实现具体类型的Converter即可:
@Component public class StringToSomeTypeConverter implements Converter<String, SomeType> { @Override public SomeType convert(String source) { // 这里编写你的转换逻辑,返回SomeType实例 // 如果返回null,Spring会自动包装为Optional.empty() return ...; } } @Component public class StringToOtherTypeConverter implements Converter<String, OtherType> { @Override public OtherType convert(String source) { // 同理实现OtherType的转换逻辑 return ...; } }
这样当Spring需要转换到Optional<SomeType>时,会自动找到StringToSomeTypeConverter,把转换结果包装成Optional;转换Optional<OtherType>时则会调用对应的转换器,完美解决冲突问题。
方案二:使用GenericConverter精确匹配泛型类型
如果因为某些特殊需求必须自己实现Optional的Converter,可以使用GenericConverter,它支持基于泛型参数的精确类型匹配:
import org.springframework.core.convert.converter.GenericConverter; import org.springframework.core.convert.TypeDescriptor; import java.util.Collections; import java.util.Set; @Component public class StringToOptionalSomeTypeConverter implements GenericConverter { @Override public Set<ConvertiblePair> getConvertibleTypes() { // 声明支持String到Optional的转换 return Collections.singleton(new ConvertiblePair(String.class, Optional.class)); } @Override public Object convert(Object source, TypeDescriptor sourceType, TypeDescriptor targetType) { // 检查目标类型的泛型参数是否为SomeType if (targetType.getElementTypeDescriptor().getType().equals(SomeType.class)) { String str = (String) source; // 执行SomeType的转换逻辑 SomeType result = ...; return Optional.ofNullable(result); } // 不是当前Converter处理的类型,返回null交给其他Converter处理 return null; } }
用同样的方式实现StringToOptionalOtherTypeConverter,在convert方法中判断泛型参数是否为OtherType即可。这样Spring会根据目标类型的泛型参数选择对应的Converter,不会再出现覆盖问题。
内容的提问来源于stack exchange,提问作者fap

