SpringMVC type conversion and data binding [with source code analysis]

Source: Internet
Author: User

Directory

  • Preface
  • Attribute Editor Introduction
  • Important interfaces and Classes
  • Partial classification and interface Testing
  • Source code analysis
  • Compile a custom property Editor
  • Summary
  • References
Preface

SpringMVC is one of the mainstream Web MVC frameworks.

If you are not familiar with it, please refer to its entry blog: http://www.cnblogs.com/fangjian0423/p/springMVC-introduction.html

public String method(Integer num, Date birth) {  ...}

The data transmitted in the Http request is of the String type. The method above is defined in the Controller. If the address corresponding to the method receives the browser request, if the request contains the num and birth parameters, the num is automatically converted to an Integer object, and the birth is automatically converted to a Date object (Date conversion requires configuring the Attribute Editor ).

This article will analyze this principle and explain how SpringMVC converts data types.

Attribute Editor Introduction

Before explaining the core content, let's take a look at the Attribute Editor defined in Java.

Sun's property editor is designed to serve IDE, allowing IDE to visually set attributes of JavaBean.

PropertyEditor is an interface of the property editor.

We use the Attribute Editor to convert String objects to the java objects we need.

It is very important to have a method setAsText. For example, if the String object "1" needs to be converted to an Integer object by using the property Editor, The Integer object is obtained through Integer. parseInt (text) in setAsText, and then the Integer object is saved to the property.

Its basic implementation class is PropertyEditorSupport. Generally, you only need to inherit this class to compile a custom property editor.

Spring has many custom attribute editors in the org. springframework. beans. propertyeditors package of spring-beans jar.

CustomBooleanEditor inherits PropertyEditorSupport and overrides the setAsText method.

Important interfaces and Classes

Just analyzed the property editor designed by sun. Let's take a look at Spring's design in this regard.

1. PropertyEditorRegistry Interface

Encapsulation Method to register the corresponding Attribute Editor for the JavaBean.

2.PropertyEditorRegistrySupport:Basic implementation class of PropertyEditorRegistry Interface

  

The PropertyEditorRegistrySupport class has a createDefaultEditors method, which creates a default Attribute Editor.

  

  

3. TypeConverter Interface

Type conversion interface. This interface can be used to convert values to requiredType objects.

  

4. TypeConverterSupport: basic implementation class of TypeConverter, and inherits PropertyEditorRegistrySupport

The typeConverterDelegate attribute has the type TypeConverterDelegate. TypeConverterSupport delegates the type conversion to the typeConverterDelegate operation.

5. TypeConverterDelegate

Type conversion delegate class. The specific type conversion operation is completed by this class.

6. SimpleTypeConverter

  The default Attribute Editor defined in PropertyEditorRegistrySupport (parent class TypeConverterSupport's parent class PropertyEditorRegistrySupport) is used as a subclass of TypeConverterSupport.

7. PropertyAccessor Interface

The interface for Attribute operations in the class.

8. BeanWrapper Interface

It inherits the configuran core interface of configuran in Spring by using the ConfigurablePropertyAccessor, PropertyEditorRegistry, and TypeConverter interfaces.

9. BeanWrapperImpl class

BeanWrapper interface's default implementation class. TypeConverterSupport is its parent class, which can be converted to a type or set attributes.

10. DataBinder class

Class that implements PropertyEditorRegistry and TypeConverter. Supports data type conversion, parameter verification, and data binding.

The SimpleTypeConverter attribute is used for type conversion.

11. WebDataBinder

A subclass of DataBinder, mainly used to bind data for Web requests.

Partial classification and interface Testing

BeanWrapper supports type conversion and attribute setting. Take the BeanWrapper interface as an example to perform several tests to give readers a clearer understanding of them:

Take the JavaBean TestModel as an example. properties:

  private int age;  private Date birth;  private String name;  private boolean good;  private long times;

Test Method 1:

TestModel tm = new TestModel();BeanWrapper bw = new BeanWrapperImpl(tm);bw.setPropertyValue("good", "on");//bw.setPropertyValue("good", "1");//bw.setPropertyValue("good", "true");//bw.setPropertyValue("good", "yes");System.out.println(tm);

Good is a boolean attribute. When BeanWrapperImpl is used to set the attribute, data type conversion is used internally (provided by TypeConverterSupport of the parent class) to convert the String type to boolean. CustomBooleanEditor converts the String value to on, 1, true and yes are converted to true. This article describes PropertyEditorRegistrySupport, and CustomBooleanEditor is the default Attribute Editor.

Test Method 2:

TestModel tm = new TestModel();BeanWrapperImpl bw = new BeanWrapperImpl(false);bw.setWrappedInstance(tm);bw.setPropertyValue("good", "1");System.out.println(tm);

The default Attribute Editor is not used for type conversion. Obviously, an error is reported in this Code and no proper attribute editing is found. The String type cannot be a value of the boolean type.

Error message:Failed to convert property value of type 'java. lang. string' to required type 'boolean' for property 'good ';

Test method 3:

TestModel tm = new TestModel();BeanWrapper bw = new BeanWrapperImpl(tm);bw.registerCustomEditor(Date.class, new CustomDateEditor(new SimpleDateFormat("yyyy-MM-dd"), true));bw.setPropertyValue("birth", "1990-01-01");System.out.println(tm);

The default Attribute Editor does not have a Date Attribute Editor. We register a CustomDateEditor Attribute Editor provided by Spring, which corresponds to a Date object and is empty. With CustomDateEditor, data is automatically converted to a Date object by type conversion when birth is set.

 

You can test other attributes.

Source code analysis

The Spring version used in this article is 4.0.2.

Before analyzing how RequestParamMethodArgumentResolver processes request parameters, let's briefly review how SpringMVC processes http requests.

HandlerAdapter will instantiate a ServletInvocableHandlerMethod object for each request for processing. Let's just look at the construction process of WebDataBinderFactory.

The WebDataBinderFactory interface is a factory interface for creating WebDataBinder.

Take the following method as an example:

public ModelAndView test(boolean b, ModelAndView view) {  view.setViewName("test/test");  if(b) {      view.addObject("attr", "b is true");  } else {      view.addObject("attr", "b is false");  }  return view;}

In another blog post.

Next we will go to RequestParamMethodArgumentResolver to see how it is handled.

The resolveArgument method of RequestParamMethodArgumentResolver is defined by its parent class AbstractNamedValueMethodArgumentResolver:

ServletRequestDataBinderFactory creates ExtendedServletRequestDataBinder.

ExtendedServletRequestDataBinder is a subclass of DataBinder.

When we introduced important interfaces, we said that when DataBinder is used for type conversion, SimpleTypeConverter is used internally for data conversion.

Let's take a look at the test:

 

CustomBooleanEditor will throw IllegalArgumentException when processing ohmygod. Finally, the http 400 error is intercepted and processed.

PS: in the preceding example, if the boolean type is changed to the Boolean type, if the parameter is not set, B is null. we explain that the Boolean Type parameter is allowed to be null during the default Attribute Editor. If a parameter is not set for the boolean type, the default value is false without throwing an exception. The reason is that handleNullValue in the resolveArgument method processes null values, and spring performs special processing. If the parameter type is boolean, false is used. You can try it.

 

Let's look at an example:

public ModelAndView testObj(Employee e, ModelAndView view) {  view.setViewName("test/test");  view.addObject("attr", e.toString());  return view;}

This method will be processed by the HandlerMethodArgumentResolver of ServletModelAttributeMethodProcessorr.

The resolveArgument method of ServletModelAttributeMethodProcessorr is defined by its parent class ModelAttributeMethodProcessor:

Here, the WebDataBinder method bind will use BeanWrapper to construct the object, and then set the corresponding attributes. BeanWrapper has been introduced in this article.

Compile a custom property Editor

The editor provided by Spring certainly does not meet our daily development functions. Therefore, it is also necessary to develop a custom attribute editor.

Next we will write a custom attribute editor.

public class CustomDeptEditor extends PropertyEditorSupport {    @Override  public void setAsText(String text) throws IllegalArgumentException {     if(text.indexOf(",") > 0) {        Dept dept = new Dept();        String[] arr = text.split(",");        dept.setId(Integer.parseInt(arr[0]));        dept.setName(arr[1]);        setValue(dept);    } else {        throw new IllegalArgumentException("dept param is error");    }  }  }

Spring MVC uses the custom attribute editor in three ways:

1. Add @ InitBinder annotation to the Controller Method

@InitBinderpublic void initBinder(WebDataBinder binder) {   binder.registerCustomEditor(Dept.class, new CustomDeptEditor());  }

2. Implement the WebBindingInitializer Interface

public class MyWebBindingInitializer implements WebBindingInitializer {    @Override  public void initBinder(WebDataBinder binder, WebRequest request) {     binder.registerCustomEditor(Dept.class, new CustomDeptEditor());    }  }

In the previous source code analysis, when HandlerAdapter constructs WebDataBinderFactory, it will pass the attributes of HandlerAdapter webBindingInitializer.

Therefore, when we construct RequestMappingHandlerAdapter in the configuration file, we pass in the webBindingInitializer parameter.

3. @ ControllerAdvice Annotation

@ControllerAdvicepublic class InitBinderControllerAdvice {    @InitBinder  public void initBinder(WebDataBinder binder) {     binder.registerCustomEditor(Dept.class, new CustomDeptEditor());    }  }

When adding ControllerAdvice, do not forget the configuration file component-scan to scan this class.

 

Final result:

Summary

After analyzing the data conversion function of Spring, explaining how this magic conversion function is implemented, I wrote a custom attribute editor.

This section describes important classes and interfaces in Spring type conversion.

SpringMVC is currently being written in three articles: Interceptor, HandlerAdapter, and view. I hope this series of articles will be helpful to readers.

Errors may inevitably occur in the article. I hope readers can point it out.

References

Http://jinnianshilongnian.iteye.com/blog/1866350

Http://jinnianshilongnian.iteye.com/blog/1723270

Http://www.iteye.com/topic/1123628

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.