記錄:spring(springmvc) Editor Converter使用區別

炸雞店老闆發表於2017-07-29

使用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());


相關文章