springmvc自定义类型转换器,springmvc类型转换
目录
类型转换服务实现转换器接口实现转换器工厂接口实现通用转换器接口环境:春天5.3.12。发布.
春天3引入了一个core.onvert包,提供一个通用类型转换系统。系统定义了一个串行外设接口(串行外设接口的缩写)来实现类型转换逻辑,以及一个应用程序界面来在运行时执行类型转换。在弹簧容器中,可以使用这个系统作为使用实现的替代,将外部化的豆属性值字符串转换为所需的属性类型。还可以在应用程序中需要类型转换的任何地方使用公共API。
类型转换服务
转换服务类型转换服务的接口。
公共接口转换服务{ //判断是否能进行转换布尔型canConvert(类?sourceType,Class?目标类型);boolean可以转换(类型描述符源类型,类型描述符目标类型);//进行类型转换T T convert(对象源,ClassT目标类型);对象转换(对象源,类型描述符源类型,类型描述符目标类型);}在大多数情况下我们应该实现。
可配置转换服务可配置的类型转换服务接口。该接口整合转换服务的所有操作和ConverterRegistry接口的相关操作,可对具体的转换进行增删。在应用程序上下文引导代码中处理可配置环境实例时,后者特别有用。
可配置转换服务接口。
公共接口可配置转换服务扩展了ConversionService,ConverterRegistry {}Spring提供了GenericConversionService实现类;该类适合在大多数环境中使用的基本转换服务实现。通过
可配置转换服务接口间接实现ConverterRegistry作为注册API。该类没有提供默认的类型转换功能,需要我们自己添加转换接口。
示例:
GenericConversionService GCS=new GenericConversionService();Long result=gcs.convert(10 ,Long)。类);System.out.println(结果);以上代码运行将报错:
线程“主要”组织。spring框架。核心。转换。converternotfoundexception :未找到能够从类型[java.lang.String]转换为类型[java.lang.Long]的转换器
没有转换接口发现错误。
FormattingConversionService类是GenericConversionService子类对象,主要作用就是增加了格式化功能(还
是类型转换的一种表现),该类提供了Printer和Parser的支持,可对对象进行打印展示及将源数据解析成目标对象,示例:
FormattingConversionService fcs = new FormattingConversionService() ;fcs.addParser(new Parser<Teacher>() { @Override public Teacher parse(String text, Locale locale) throws ParseException { String[] t = text.split("\") ; return new Teacher(t[0], Integer.valueOf(t[1])) ; }});System.out.println(fcs.convert("张晶晶26", Teacher.class)) ;
这里的addParser方法最后还是将Parser转换为GenericConverter。
将对象转换为可读的信息,示例:
FormattingConversionService fcs = new FormattingConversionService() ;fcs.addPrinter(new Printer<Teacher>() { @Override public String print(Teacher object, Locale locale) { return "【 name = " + object.getName() + ", age = " + object.getAge() + "】" ; }});System.out.println(fcs.convert(new Teacher("张晶晶", 26), String.class)) ;
以上介绍的类型转换服务默认没有任何的类型转换能力,都需要我们自定义添加,在Spring中还提供了DefaultConversionService和WebConversionService。
通过名称知道WebConversionService针对Web项目,但是你也是可以在非Web项目中使用。这里我就介绍DefaultConversionService。先看示例:
DefaultConversionService dcs = new DefaultConversionService() ;Long result = dcs.convert("10", Long.class) ;Date date = dcs.convert("2022-07-01", Date.class) ;System.out.println(result) ;System.out.println(date) ;
上面两个类型的转换都能成功,为什么呢?因为DefaultConversionService内部已经帮我们注册了很多的类型转换,源码:
public class DefaultConversionService extends GenericConversionService { public DefaultConversionService() { addDefaultConverters(this); } public static void addDefaultConverters(ConverterRegistry converterRegistry) { addScalarConverters(converterRegistry); // 该方法中还注册了很多集合,流数据类型的转换功能,详细查看源码 addCollectionConverters(converterRegistry); converterRegistry.addConverter(new ByteBufferConverter((ConversionService) converterRegistry)); converterRegistry.addConverter(new StringToTimeZoneConverter()); converterRegistry.addConverter(new ZoneIdToTimeZoneConverter()); converterRegistry.addConverter(new ZonedDateTimeToCalendarConverter()); converterRegistry.addConverter(new ObjectToObjectConverter()); converterRegistry.addConverter(new IdToEntityConverter((ConversionService) converterRegistry)); converterRegistry.addConverter(new FallbackObjectToStringConverter()); converterRegistry.addConverter(new ObjectToOptionalConverter((ConversionService) converterRegistry)); }}
通常我们一般都是使用DefaultConversionService。
在Web环境下默认使用的WebConversionService,这里以SpringBoot为例,源码如下:
public class WebMvcAutoConfiguration { public static class EnableWebMvcConfiguration extends DelegatingWebMvcConfiguration implements ResourceLoaderAware { @Bean @Override public FormattingConversionService mvcConversionService() { Format format = this.mvcProperties.getFormat(); WebConversionService conversionService = new WebConversionService(new DateTimeFormatters().dateFormat(format.getDate()).timeFormat(format.getTime()).dateTimeFormat(format.getDateTime())); addFormatters(conversionService); return conversionService; } }}
WebConversionService的继承关系
public class WebConversionService extends DefaultFormattingConversionService {}public class DefaultFormattingConversionService extends FormattingConversionService {}public class FormattingConversionService extends GenericConversionService implements FormatterRegistry, EmbeddedValueResolverAware {}
Spring还提供了一个ConversionServiceFactoryBean来注册我们自定义的类型转换。
public class ConversionServiceFactoryBean implements FactoryBean<ConversionService>, InitializingBean { private Set<?> converters; private GenericConversionService conversionService; public void setConverters(Set<?> converters) { this.converters = converters; } @Override public void afterPropertiesSet() { this.conversionService = createConversionService(); ConversionServiceFactory.registerConverters(this.converters, this.conversionService); } protected GenericConversionService createConversionService() { return new DefaultConversionService(); } @Override public ConversionService getObject() { return this.conversionService; } @Override public Class<? extends ConversionService> getObjectType() { return GenericConversionService.class; } @Override public boolean isSingleton() { return true; }}
我们可以定个该Bean,然后注入converters属性值。
@Beanpublic ConversionServiceFactoryBean conversionService() { ConversionServiceFactoryBean factory = new ConversionServiceFactoryBean() ; // 自定义的类型转换 factory.setConverters(...) ; return factory ;}
Spring的类型转换服务是不是挺简单?接下来介绍Spring提供的各种自定义类型转换方式。
接下来我们都是以示例为主。
实现Converter接口
Converter接口。
@FunctionalInterfacepublic interface Converter<S, T> { T convert(S source);}
自定义Converter接口,我们使用匿名内部类实现。
DefaultConversionService cs = new DefaultConversionService();// 自定义类型转换器,当有了ConversionService完全可以替代PropertyEditorcs.addConverter(new Converter<String, Users>() { public Users convert(String source) { String[] temp = source.split("\") ; return new Users(temp[0], Integer.parseInt(temp[1])) ; }}) ;Users users = cs.convert("张三100", Users.class) ;System.out.println(users) ;
实现ConverterFactory接口
当你需要集中整个类层次结构的转换逻辑时(例如,当从String转换到Enum对象时),你可以实现ConverterFactory。也就是有继承关系的类型转换。
ConverterFactory接口。
public interface ConverterFactory<S, R> { <T extends R> Converter<S, T> getConverter(Class<T> targetType);}
自定义工厂类。
public class EnvObjectConvert implements ConverterFactory<String, EnvObject> { @Override public <T extends EnvObject> Converter<String, T> getConverter(Class<T> targetType) { return new EnvConvert<T>(); } private class EnvConvert<T extends EnvObject> implements Converter<String, T> { @Override public T convert(String source) { String[] temp = source.split("\") ; return (T) new EnvObject(temp[0], Integer.valueOf(temp[1])) ; } }}
实现GenericConverter接口
当你需要复杂的Converter实现时,请考虑使用GenericConverter接口。与Converter相比,GenericConverter具有更灵活但强类型较少的签名,因此它支持在多个源类型和目标类型之间进行转换。此外,GenericConverter提供了可用的源和目标字段上下文,你可以在实现转换逻辑时使用它们。这样的上下文允许通过字段注释或在字段签名上声明的泛型信息驱动类型转换。下面的清单显示了GenericConverter的接口定义:
GenericConverter接口。
public interface GenericConverter { Set<ConvertiblePair> getConvertibleTypes(); Object convert(@Nullable Object source, TypeDescriptor sourceType, TypeDescriptor targetType);}
自定义GenericConverter。
public class CustomGenericConverter implements GenericConverter { @Override public Set<ConvertiblePair> getConvertibleTypes() { // 这里我们可以定义多组的类型转换关系 ConvertiblePair teacherPair = new ConvertiblePair(String.class, Teacher.class) ; ConvertiblePair studentPair = new ConvertiblePair(String.class, Student.class) ; Set<ConvertiblePair> pairs = new HashSet<>() ; pairs.add(teacherPair) ; pairs.add(studentPair) ; return pairs ; } @Override public Object convert(Object source, TypeDescriptor sourceType, TypeDescriptor targetType) { // 下面分别看到不同的类型做不同的处理 String str = null ; if (sourceType.getObjectType() == String.class) { str = (String) source ; } if (targetType.getObjectType() == Teacher.class) { String[] t = str.split("\") ; return new Teacher(t[0], Integer.valueOf(t[1])) ; } if (targetType.getObjectType() == Student.class) { String[] t = str.split("\") ; return new Student(t[0], t[1]) ; } return null ; }}
以上就是Spring中自定义数据类型转换的方法详解的详细内容,更多关于Spring数据类型转换的资料请关注盛行IT其它相关文章!
郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。