SpringMVC type converter, property editor

For the MVC framework, parameter binding has always been considered a very magical and convenient thing. In the process of parameter binding, the property editor and type converter are used.

Parameter binding process

Parameter binding: Convert the data in the request into an object of a specified type and give it to the method that processes the request

editor converter

  • The request enters the DisptacherServlet to unload the data in the request
  • DisptacherServlet sends data in request to Controller
  • Get the parameter type that the Controller needs to receive, and send the parameter type and request data to the DataBinder
  • DataBinder sends the parameter type and request data to TypeConverter, which is assembled into a bean by TypeConverter
  • TypeConverter looks up the registered PropertyEditor in the PropertyEditorRegistry based on the member type in the bean
  • PropertyEditor sets data to members in bean
  • TypeConverter returns assembled bean to DataBinder
  • The DataBinder hands the wired bean to the method that handles the request

In the process of parameter binding, TypeConverter and PropertyEditor are the core processes of converting data into objects (non-serialization) TypeConverter is responsible for converting data into a bean PropertyEditor is responsible for converting data into a member field

property editor

PropertiesEditor is responsible for converting simple objects. Because http requests are in the form of strings, they are generally converted according to String. Springmvc provides many default property editors in the org.springframework.beans.propertyeditors package, such as

WeChat screenshot_20160716120316

  • CustomBooleanEditor.class,String 转换 Boolean
  • CustomCollectionEditor.class,String 转换 Collection
  • CustomDateEditor.class,String 转换 Date
  • CustomMapEditor.class, String conversion Map
  • CustomNumberEditor.class,String 转换  int、floot、double..

All property editors inherit PropertiesEditorSupport, the default property editor, which is automatically loaded by Spring when it starts. In addition, if the property to be assembled does not have a suitable editor, you can also customize the property editor to register a custom editor. After defining the property editor, register it in the CustomEditorConfigurer, and the property editor can be used globally by the application, because the factory of the property editor is in the global scope

PropertiesEditor source code analysis

PropertiesEditor.java

public class PropertiesEditor extends PropertyEditorSupport {
 //Convert String to object of specified type
 @Override
 public void setAsText(String text) throws IllegalArgumentException {
  Properties props = new Properties();//Properties以key-value存值
   if (text != null) {
   try {
   //Convert the key=value or key:value information represented in String into Properties
   //key represents the field name in the bean
   //If you want to convert to Date, the value is Date, and String can be in the form of "date=2012-12-12" (date is the field name)
   props.load(new ByteArrayInputStream(text.getBytes("ISO-8859-1")));
  }
  catch (IOException ex) {
   throw new IllegalArgumentException(
   "Failed to parse [" + text + "] into Properties", ex);
   }
 }
  setValue(props);
 }
 //Convert old object to new object
 @Override
 public void setValue(Object value) {
   if (!(value instanceof Properties) && value instanceof Map) {
   Properties props = new Properties();
   props.putAll((Map<?, ?>) value);
   super.setValue(props);
 }
 else {
   //The parent class PropertyEditorSupport holds the value object, which is the object to be converted
   super.setValue(value);
  }
 }
}

It should be noted that setAsText achieves the effect of attribute editing through a certain format string, "member name=value", or "member name: value", which will set the value to the specified member of the bean in the editor The two most important methods are setAsTest(String) and setValue(value). In these two methods, we complete the transformation from String-object, object-object

CustomDateEditor source code analysis

CustomDateEditor is a default property editor of Spring, which is responsible for converting String into a Date object in a specified format. It also inherits PropertiesEditorSupport and rewrites the setAsTest method.

public class CustomDateEditor extends PropertyEditorSupport {
 //Specified date format, such as "yyyy-MM-dd"
 private final DateFormat dateFormat;
 // Whether to allow the string to be empty
 private final boolean allowEmpty;
 // strict date length
 private final int exactDateLength;

 public CustomDateEditor(DateFormat dateFormat, boolean allowEmpty) {
 //constructor method
 }
 public CustomDateEditor(DateFormat dateFormat, boolean allowEmpty, int exactDateLength) {
 //constructor method
 }
 //String converted to Dtae
 @Override
 public void setAsText(String text) throws IllegalArgumentException {
   //Check if the string is empty
   if (this.allowEmpty && !StringUtils.hasText(text)) {
    setValue(null);
   }
   / / Determine whether the length of the string is equal to exactDateLength
   else if (text != null && this.exactDateLength >= 0 && text.length() != this.exactDateLength) {
     throw new IllegalArgumentException(
     "Could not parse date: it is not exactly" + this.exactDateLength + "characters long");
    }
   else {
   try {
     //Format the text into a Date object
    setValue(this.dateFormat.parse(text));
   }
   catch (ParseException ex) {
     throw new IllegalArgumentException("Could not parse date: " + ex.getMessage(), ex);
   }
   }
   }
 //output String from Date
 @Override
 public String getAsText() {
   Date value = (Date) getValue();
   //return the formatted String
   return (value != null ? this.dateFormat.format(value) : "");
 }
}

As can be seen from the source code of CustomDateEditor, the most important thing is to rewrite the setAsText method, first check that the string format character does not meet the requirements, throw an exception if it does not meet the requirements, and then convert the string into the Date object of the specified DateFormat according to the string

type converter

The property editor just mentioned is used to fill in the properties in the bean. The type converter is responsible for converting data into a bean. Therefore, during the conversion process, the property editor is needed to help fill in the properties, so it should hold a bunch of property editors. (beans have various properties), then holding a PropertyEditorRegistry (a property editor factory) is enough

  • TypeConverter, the interface for type conversion
  • TypeConverterSupport, the implementation of type conversion, holds a TypeConverterDelegate, and the specific conversion work is completed by TypeConverterDelegate
  • TypeConverterDelegate, the delegate class for type conversion, all the work of type conversion is done by him

typeConverter

The only method to be implemented is convertIfNecessary, which converts the source object to the target object

TypeConverterDelegate source code analysis

Because the conversion work is done by TypeConverterDelegate, the source code is too long, just look at the code of that part of the conversion

/*
@Param propertyName the name of the bean
@Param requiredType required type
@Param typeDescriptor type descriptor
*/
public <T> T convertIfNecessary(String propertyName, Object oldValue, Object newValue,Class<T> requiredType, TypeDescriptor typeDescriptor) throws IllegalArgumentException {
 //Get the property editor that can edit requiredType from the registered property editor
 PropertyEditor editor = this.propertyEditorRegistry.findCustomEditor(requiredType, propertyName);
 //...
 //Use the property editor to convert oldValue to requiredType
 convertedValue = doConvertValue(oldValue, convertedValue, requiredType, editor);
 //...
 return convertedValue;
 }
/*
@Param propertyName the name of the bean
@Param requiredType required type
@Param editor property editor
*/
 private Object doConvertValue(Object oldValue, Object newValue, Class<?> requiredType, PropertyEditor editor) {
   Object convertedValue = newValue;
   if (editor != null && !(convertedValue instanceof String)) {
   try {
     //convert data
     editor.setValue(convertedValue);
     // get the converted data
     Object newConvertedValue = editor.getValue();
     if (newConvertedValue != convertedValue) {
    convertedValue = newConvertedValue;
     editor = null;
    }
 }
   catch (Exception ex) {
     if (logger.isDebugEnabled()) {
     logger.debug("PropertyEditor [" + editor.getClass().getName() + "] does not support setValue call", ex);
    }
   }
 }
 Object returnValue = convertedValue;
 //...
 return returnValue;
 }
}

 View the original text: http://zswlib.com/2016/07/16/springmvc%E7%B1%BB%E5%9E%8B%E8%BD%AC%E6%8D%A2%E5%99%A8%E3 %80%81%E5%B1%9E%E6%80%A7%E7%BC%96%E8%BE%91%E5%99%A8/

Guess you like

Origin http://10.200.1.11:23101/article/api/json?id=326915738&siteId=291194637