記錄:spring(springmvc) Editor Converter使用區別
使用spring 載入配置項、springmvc 請求入參過程中,String 轉需要的類,就是通過內建的Editor Converter完成。
Editor和Converter都可以完成StringToXXX的轉換,但效果又不同。
比如:StringToCollection,Editor轉換後的結果比Converter差。因此使用場景需要注意,否則會花時間除錯。
總結:
1. springmvc 引數的轉換,正常情況全部使用Converter完成。自定義情況,如Date轉換,則交給CustomEditor完成。
2. springmvc json引數(@RequestBody),不涉及Editor和Converter,轉換交給Jackson 或者FastJson完成,如Date轉換,具體看json庫的預設規則。
3. spring 容器載入,如@Value 配置轉換,則交給Editor轉換。
Insight:
優先順序convert邏輯:
1. findCustomEditor
2. getConversionService
org.springframework.format.support.DefaultFormattingConversionService
(來自於mvc啟動 org.springframework.format.support.FormattingConversionServiceFactoryBean)
(! 初始化的時候載入諸多Converter DefaultConversionService.addDefaultConverters(this);)
3. findDefaultEditor
4. 餘下的都是渣渣,1-3都可以搞定org.springframework.web.servlet.DispatcherServlet#doDispatch
org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter#handle
org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter#handleInternal
org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter#invokeHandleMethod
構造org.springframework.web.servlet.mvc.method.annotation.ServletRequestDataBinderFactory
org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod#invokeAndHandle
org.springframework.web.method.support.InvocableHandlerMethod#getMethodArgumentValues
處理Date org.springframework.web.method.annotation.AbstractNamedValueMethodArgumentResolver
org.springframework.web.method.annotation.AbstractNamedValueMethodArgumentResolver#resolveArgument
建立binder org.springframework.web.servlet.mvc.method.annotation.ExtendedServletRequestDataBinder
org.springframework.beans.TypeConverterDelegate#convertIfNecessary
findEditor or Converter
org.springframework.core.convert.ConversionService#convert
諸多Converter開始工作,return result;
內建的Editor和Converter:
/**
* Actually register the default editors for this registry instance.
*/
private void createDefaultEditors() {
this.defaultEditors = new HashMap, PropertyEditor>(64);
// Simple editors, without parameterization capabilities.
// The JDK does not contain a default editor for any of these target types.
this.defaultEditors.put(Charset.class, new CharsetEditor());
this.defaultEditors.put(Class.class, new ClassEditor());
this.defaultEditors.put(Class[].class, new ClassArrayEditor());
this.defaultEditors.put(Currency.class, new CurrencyEditor());
this.defaultEditors.put(File.class, new FileEditor());
this.defaultEditors.put(InputStream.class, new InputStreamEditor());
this.defaultEditors.put(InputSource.class, new InputSourceEditor());
this.defaultEditors.put(Locale.class, new LocaleEditor());
this.defaultEditors.put(Pattern.class, new PatternEditor());
this.defaultEditors.put(Properties.class, new PropertiesEditor());
this.defaultEditors.put(Resource[].class, new ResourceArrayPropertyEditor());
this.defaultEditors.put(TimeZone.class, new TimeZoneEditor());
this.defaultEditors.put(URI.class, new URIEditor());
this.defaultEditors.put(URL.class, new URLEditor());
this.defaultEditors.put(UUID.class, new UUIDEditor());
// Default instances of collection editors.
// Can be overridden by registering custom instances of those as custom editors.
this.defaultEditors.put(Collection.class, new CustomCollectionEditor(Collection.class));
this.defaultEditors.put(Set.class, new CustomCollectionEditor(Set.class));
this.defaultEditors.put(SortedSet.class, new CustomCollectionEditor(SortedSet.class));
this.defaultEditors.put(List.class, new CustomCollectionEditor(List.class));
this.defaultEditors.put(SortedMap.class, new CustomMapEditor(SortedMap.class));
// Default editors for primitive arrays.
this.defaultEditors.put(byte[].class, new ByteArrayPropertyEditor());
this.defaultEditors.put(char[].class, new CharArrayPropertyEditor());
// The JDK does not contain a default editor for char!
this.defaultEditors.put(char.class, new CharacterEditor(false));
this.defaultEditors.put(Character.class, new CharacterEditor(true));
// Spring's CustomBooleanEditor accepts more flag values than the JDK's default editor.
this.defaultEditors.put(boolean.class, new CustomBooleanEditor(false));
this.defaultEditors.put(Boolean.class, new CustomBooleanEditor(true));
// The JDK does not contain default editors for number wrapper types!
// Override JDK primitive number editors with our own CustomNumberEditor.
this.defaultEditors.put(byte.class, new CustomNumberEditor(Byte.class, false));
this.defaultEditors.put(Byte.class, new CustomNumberEditor(Byte.class, true));
this.defaultEditors.put(short.class, new CustomNumberEditor(Short.class, false));
this.defaultEditors.put(Short.class, new CustomNumberEditor(Short.class, true));
this.defaultEditors.put(int.class, new CustomNumberEditor(Integer.class, false));
this.defaultEditors.put(Integer.class, new CustomNumberEditor(Integer.class, true));
this.defaultEditors.put(long.class, new CustomNumberEditor(Long.class, false));
this.defaultEditors.put(Long.class, new CustomNumberEditor(Long.class, true));
this.defaultEditors.put(float.class, new CustomNumberEditor(Float.class, false));
this.defaultEditors.put(Float.class, new CustomNumberEditor(Float.class, true));
this.defaultEditors.put(double.class, new CustomNumberEditor(Double.class, false));
this.defaultEditors.put(Double.class, new CustomNumberEditor(Double.class, true));
this.defaultEditors.put(BigDecimal.class, new CustomNumberEditor(BigDecimal.class, true));
this.defaultEditors.put(BigInteger.class, new CustomNumberEditor(BigInteger.class, true));
// Only register config value editors if explicitly requested.
if (this.configValueEditorsActive) {
StringArrayPropertyEditor sae = new StringArrayPropertyEditor();
this.defaultEditors.put(String[].class, sae);
this.defaultEditors.put(short[].class, sae);
this.defaultEditors.put(int[].class, sae);
this.defaultEditors.put(long[].class, sae);
}
}
// 能想到的型別轉換都包括了,完美!
// 1.標準型別Converter
converterRegistry.addConverter(new StringToBooleanConverter());
converterRegistry.addConverter(Boolean.class, String.class, new ObjectToStringConverter());
converterRegistry.addConverterFactory(new StringToNumberConverterFactory());
converterRegistry.addConverter(Number.class, String.class, new ObjectToStringConverter());
converterRegistry.addConverterFactory(new NumberToNumberConverterFactory());
converterRegistry.addConverter(new StringToCharacterConverter());
converterRegistry.addConverter(Character.class, String.class, new ObjectToStringConverter());
converterRegistry.addConverter(new NumberToCharacterConverter());
converterRegistry.addConverterFactory(new CharacterToNumberFactory());
converterRegistry.addConverterFactory(new StringToEnumConverterFactory());
converterRegistry.addConverter(Enum.class, String.class, new EnumToStringConverter(conversionService));
converterRegistry.addConverter(new StringToLocaleConverter());
converterRegistry.addConverter(Locale.class, String.class, new ObjectToStringConverter());
converterRegistry.addConverter(new PropertiesToStringConverter());
converterRegistry.addConverter(new StringToPropertiesConverter());
converterRegistry.addConverter(new StringToUUIDConverter());
converterRegistry.addConverter(UUID.class, String.class, new ObjectToStringConverter());
// 2.集合類轉換Converter,內部實現迭代處理
converterRegistry.addConverter(new ArrayToCollectionConverter(conversionService));
converterRegistry.addConverter(new CollectionToArrayConverter(conversionService));
converterRegistry.addConverter(new ArrayToArrayConverter(conversionService));
converterRegistry.addConverter(new CollectionToCollectionConverter(conversionService));
converterRegistry.addConverter(new MapToMapConverter(conversionService));
converterRegistry.addConverter(new ArrayToStringConverter(conversionService));
converterRegistry.addConverter(new StringToArrayConverter(conversionService));
converterRegistry.addConverter(new ArrayToObjectConverter(conversionService));
converterRegistry.addConverter(new ObjectToArrayConverter(conversionService));
converterRegistry.addConverter(new CollectionToStringConverter(conversionService));
converterRegistry.addConverter(new StringToCollectionConverter(conversionService));
converterRegistry.addConverter(new CollectionToObjectConverter(conversionService));
converterRegistry.addConverter(new ObjectToCollectionConverter(conversionService));
// 3.回撥型別處理Converter
converterRegistry.addConverter(new ObjectToObjectConverter());
converterRegistry.addConverter(new IdToEntityConverter(conversionService));
converterRegistry.addConverter(new FallbackObjectToStringConverter());
相關文章
- spring和springmvc的區別SpringMVC
- Spring型別轉換(Converter)Spring型別
- spring、springmvc、springboot、springcloud 之間的聯絡和區別SpringMVCSpring BootGCCloud
- ssm springmvc springboot區別SSMSpringMVCSpring Boot
- SpringMVC錯誤記錄SpringMVC
- 有關Editor的記錄(一)
- springboot和springmvc的區別Spring BootSpringMVC
- springmvc和springboot的區別SpringMVCSpring Boot
- 簡述Spring容器與SpringMVC的容器的聯絡與區別SpringMVC
- spring 記錄Spring
- Spring記錄Spring
- SpringMVC框架和Servlet開發有啥子區別(SpringMVC優勢)SpringMVC框架Servlet
- Spring Boot 記錄Spring Boot
- spring_error——記錄使用spring時的一些errorSpringError
- 學習記錄Spring Boot 記錄配置細節Spring Boot
- spring beanFactory與ApplicationContext區別SpringBeanAPPContext
- spring-boot-route(十七)使用aop記錄操作日誌Springboot
- Spring學習記錄1Spring
- Spring MVC和Spring Boot的區別 - hackernoonMVCSpring Boot
- Spring框架和Spring boot有啥區別?框架Spring Boot
- ssm專案的搭建:使用到框架 spring springmvc mybatisSSM框架SpringMVCMyBatis
- SpringMVC(3)-request域和session域的作用和區別SpringMVCSession
- SSM整合(Spring、SpringMVC、Mybatis)SSMSpringMVCMyBatis
- SSM——Spring整合SpringMVC,MyBatisSSMSpringMVCMyBatis
- SSM(SpringMVC + Spring + Mybatis)整合SSMSpringMVCMyBatis
- 使用Spring JDBC新增記錄如何返回自增主鍵值SpringJDBC
- 在Spring Boot中使用CommonsRequestLoggingFilter記錄傳入的請求Spring BootFilter
- 【Spring Boot 使用記錄】kafka自動配置和自定義配置Spring BootKafka
- spring-boot記錄sql探索SpringbootSQL
- Spring Cloud Eureka 學習記錄SpringCloud
- Spring相關問題記錄Spring
- Spring學習筆記目錄Spring筆記
- SpringMVC筆記SpringMVC筆記
- 區塊鏈記錄_1區塊鏈
- spring boot與spring mvc的區別是什麼?Spring BootMVC
- 搭建 Spring+SpringMVC+MyBatis 框架SpringMVCMyBatis框架
- Spring+SpringMVC+MyBatis框架整合SpringMVCMyBatis框架
- Spring+SpringMVC+MyBatis的整合SpringMVCMyBatis
- MyBatis(九) 整合Spring、整合SpringMVCMyBatisSpringMVC