第一节:SpringMVC—数据绑定流程分析

一、问题引入

  在做 Restful 案例的时候,我们在控制器方法入参位置写一个 Employee 类型的参数,SpringMVC 就能把表单中各项属性封装到参数中,这是怎么做到的呢?

    //SpringMVC把表单提交的数据都封装到employee 对象中
    @RequestMapping(value = "/emp", method = RequestMethod.POST)
    public String addEmp(Employee employee) {
        System.out.println("employee = " + employee);
        employeeDao.save(employee);
        //重定向到 emps 查询所有,然后在 list.jsp 显示
        return "redirect:/emps";
    }

  SpringMVC 封装自定义类型对象的时候,JavaBean 要和页面提交的数据进行一一绑定,它是如何做到的呢?

  既然要做到前端页面提交的值与 JavaBean 的属性进行绑定:

  (1)页面提交的所有数据都是字符串;

  (2)对于 Integer age,Date birth 这样的属性,需要做一定的转换操作:

employeName=zhangsan&age=18&gender=1
String age = reuqest.getParameter("age");

  

  既然肯定会牵扯到以下操作:

  1、数据类型转换:数据绑定期间的数据类型转换?String->Integer

  2、数据格式化:数据绑定期间的数据格式化问题,比如提交的日期进行转换;

    birth=2021-11-30  ---> Date 2021.11.30  2021/11/30   2021-11-30

  

  3、数据校验:

    我们提交的数据必须是合法的?

    前端校验:JavaScript + 正则表达式

    后端校验:重要的数据也必须进行校验:校验成功:数据合法;校验失败:提示错误;

二、数据绑定流程原理

  ① Spring MVC 主框架将 ServletRequest 对象及目标方法的入参实例传递给 WebDataBinderFactory 实例,以创建 DataBinder 实例对象;

  ② DataBinder 调用装配在 Spring MVC 上下文中的 ConversionService 组件进行数据类型转换、数据格式化工作。将 Servlet 中的请求信息填充到入参对象中;

  ③ 调用 Validator 组件对已经绑定了请求消息的入参对象进行数据合法性校验,并最终生成数据绑定结果 BindingData 对象;

  ④ Spring MVC 抽取 BindingResult 中的入参对象和校验错误对象,将它们赋给处理方法的响应入参;

  Spring MVC 通过反射机制对目标处理方法进行解析,将请求消息绑定到处理方法的入参中。数据绑定的核心部件是 DataBinder,运行机制如下:

   

   源码分析:

核心代码:
ModelAttributeMethodProcessor:
    resolveArgument() 解析参数
    bindRequestParameters(binder, request); 将页面提交的数据封装到 JavaBean 的属性中
------------------------------------------------
    @Override
    public final Object resolveArgument(
            MethodParameter parameter, ModelAndViewContainer mavContainer,
            NativeWebRequest request, WebDataBinderFactory binderFactory)
            throws Exception {

        String name = ModelFactory.getNameForParameter(parameter);
        Object attribute = (mavContainer.containsAttribute(name)) ?
                mavContainer.getModel().get(name) : createAttribute(name, parameter, binderFactory, request);

        WebDataBinder binder = binderFactory.createBinder(request, attribute, name);
        if (binder.getTarget() != null) {
            //将页面提交过来的数据封装到 JavaBean 的属性中
            bindRequestParameters(binder, request);
            validateIfApplicable(binder, parameter);
            if (binder.getBindingResult().hasErrors()) {
                if (isBindExceptionRequired(binder, parameter)) {
                    throw new BindException(binder.getBindingResult());
                }
            }
        }

        // Add resolved attribute and BindingResult at the end of the model

        Map<String, Object> bindingResultModel = binder.getBindingResult().getModel();
        mavContainer.removeAttributes(bindingResultModel);
        mavContainer.addAllAttributes(bindingResultModel);

        return binder.getTarget();
    }

三、通过debug调试流程

  ① 查看数据绑定流程,在Employee类的set方法上设置断点调试

 

     

   WedDataBinder

 

  ② Spring MVC 上下文中内建了很多转换器,可完成大多数 Java 类型的转换工作。

conversionService.converters=

result = {LinkedHashMap@5127}  size = 97
{GenericConverter$ConvertiblePair@5227} "java.lang.Number -> java.lang.Number" -> {GenericConversionService$ConvertersForPair@5228} "java.lang.Number -> java.lang.Number : org.springframework.core.convert.support.NumberToNumberConverterFactory@68161576"
{GenericConverter$ConvertiblePair@5229} "java.lang.String -> java.lang.Number" -> {GenericConversionService$ConvertersForPair@5230} "java.lang.String -> java.lang.Number : org.springframework.core.convert.support.StringToNumberConverterFactory@2d148610"
{GenericConverter$ConvertiblePair@5231} "java.lang.Number -> java.lang.String" -> {GenericConversionService$ConvertersForPair@5232} "java.lang.Number -> java.lang.String : org.springframework.core.convert.support.ObjectToStringConverter@3c1bc3fa"
{GenericConverter$ConvertiblePair@5233} "java.lang.String -> java.lang.Character" -> {GenericConversionService$ConvertersForPair@5234} "java.lang.String -> java.lang.Character : org.springframework.core.convert.support.StringToCharacterConverter@1cf34886"
{GenericConverter$ConvertiblePair@5235} "java.lang.Character -> java.lang.String" -> {GenericConversionService$ConvertersForPair@5236} "java.lang.Character -> java.lang.String : org.springframework.core.convert.support.ObjectToStringConverter@441653cb"
{GenericConverter$ConvertiblePair@5237} "java.lang.Number -> java.lang.Character" -> {GenericConversionService$ConvertersForPair@5238} "java.lang.Number -> java.lang.Character : org.springframework.core.convert.support.NumberToCharacterConverter@4d3b795f"
{GenericConverter$ConvertiblePair@5239} "java.lang.Character -> java.lang.Number" -> {GenericConversionService$ConvertersForPair@5240} "java.lang.Character -> java.lang.Number : org.springframework.core.convert.support.CharacterToNumberFactory@2f5d6711"
{GenericConverter$ConvertiblePair@5241} "java.lang.String -> java.lang.Boolean" -> {GenericConversionService$ConvertersForPair@5242} "java.lang.String -> java.lang.Boolean : org.springframework.core.convert.support.StringToBooleanConverter@296cad04"
{GenericConverter$ConvertiblePair@5243} "java.lang.Boolean -> java.lang.String" -> {GenericConversionService$ConvertersForPair@5244} "java.lang.Boolean -> java.lang.String : org.springframework.core.convert.support.ObjectToStringConverter@5f123be9"
{GenericConverter$ConvertiblePair@5245} "java.lang.String -> java.lang.Enum" -> {GenericConversionService$ConvertersForPair@5246} "java.lang.String -> java.lang.Enum : org.springframework.core.convert.support.StringToEnumConverterFactory@497540d5"
{GenericConverter$ConvertiblePair@5247} "java.lang.Enum -> java.lang.String" -> {GenericConversionService$ConvertersForPair@5248} "java.lang.Enum -> java.lang.String : org.springframework.core.convert.support.EnumToStringConverter@dd4d305"
{GenericConverter$ConvertiblePair@5249} "java.lang.String -> java.util.Locale" -> {GenericConversionService$ConvertersForPair@5250} "java.lang.String -> java.util.Locale : org.springframework.core.convert.support.StringToLocaleConverter@411c5b36"
{GenericConverter$ConvertiblePair@5251} "java.util.Locale -> java.lang.String" -> {GenericConversionService$ConvertersForPair@5252} "java.util.Locale -> java.lang.String : org.springframework.core.convert.support.ObjectToStringConverter@f1ffd8f"
{GenericConverter$ConvertiblePair@5253} "java.lang.String -> java.util.Properties" -> {GenericConversionService$ConvertersForPair@5254} "java.lang.String -> java.util.Properties : org.springframework.core.convert.support.StringToPropertiesConverter@6c0f6751"
{GenericConverter$ConvertiblePair@5255} "java.util.Properties -> java.lang.String" -> {GenericConversionService$ConvertersForPair@5256} "java.util.Properties -> java.lang.String : org.springframework.core.convert.support.PropertiesToStringConverter@47e8dd2e"
{GenericConverter$ConvertiblePair@5257} "java.lang.String -> java.util.UUID" -> {GenericConversionService$ConvertersForPair@5258} "java.lang.String -> java.util.UUID : org.springframework.core.convert.support.StringToUUIDConverter@640eeb0e"
{GenericConverter$ConvertiblePair@5259} "java.util.UUID -> java.lang.String" -> {GenericConversionService$ConvertersForPair@5260} "java.util.UUID -> java.lang.String : org.springframework.core.convert.support.ObjectToStringConverter@140d8185"
{GenericConverter$ConvertiblePair@5261} "[Ljava.lang.Object; -> java.util.Collection" -> {GenericConversionService$ConvertersForPair@5262} "org.springframework.core.convert.support.ArrayToCollectionConverter@32f59ba"
{GenericConverter$ConvertiblePair@5263} "java.util.Collection -> [Ljava.lang.Object;" -> {GenericConversionService$ConvertersForPair@5264} "org.springframework.core.convert.support.CollectionToArrayConverter@2aff55c"
{GenericConverter$ConvertiblePair@5265} "[Ljava.lang.Object; -> [Ljava.lang.Object;" -> {GenericConversionService$ConvertersForPair@5266} "org.springframework.core.convert.support.ArrayToArrayConverter@116a289c"
{GenericConverter$ConvertiblePair@5267} "java.util.Collection -> java.util.Collection" -> {GenericConversionService$ConvertersForPair@5268} "org.springframework.core.convert.support.CollectionToCollectionConverter@6913829d"
{GenericConverter$ConvertiblePair@5269} "java.util.Map -> java.util.Map" -> {GenericConversionService$ConvertersForPair@5270} "org.springframework.core.convert.support.MapToMapConverter@1088e48c"
{GenericConverter$ConvertiblePair@5271} "[Ljava.lang.Object; -> java.lang.String" -> {GenericConversionService$ConvertersForPair@5272} "org.springframework.core.convert.support.ArrayToStringConverter@6d70f6d4"
{GenericConverter$ConvertiblePair@5273} "java.lang.String -> [Ljava.lang.Object;" -> {GenericConversionService$ConvertersForPair@5274} "org.springframework.core.convert.support.StringToArrayConverter@2d1e0d2e"
{GenericConverter$ConvertiblePair@5275} "[Ljava.lang.Object; -> java.lang.Object" -> {GenericConversionService$ConvertersForPair@5276} "org.springframework.core.convert.support.ArrayToObjectConverter@58ec757a"
{GenericConverter$ConvertiblePair@5277} "java.lang.Object -> [Ljava.lang.Object;" -> {GenericConversionService$ConvertersForPair@5278} "org.springframework.core.convert.support.ObjectToArrayConverter@f17566f"
{GenericConverter$ConvertiblePair@5279} "java.util.Collection -> java.lang.String" -> {GenericConversionService$ConvertersForPair@5280} "org.springframework.core.convert.support.CollectionToStringConverter@65bbc70f"
{GenericConverter$ConvertiblePair@5281} "java.lang.String -> java.util.Collection" -> {GenericConversionService$ConvertersForPair@5282} "org.springframework.core.convert.support.StringToCollectionConverter@3891c1eb"
{GenericConverter$ConvertiblePair@5283} "java.util.Collection -> java.lang.Object" -> {GenericConversionService$ConvertersForPair@5284} "org.springframework.core.convert.support.CollectionToObjectConverter@3ed2426"
{GenericConverter$ConvertiblePair@5285} "java.lang.Object -> java.util.Collection" -> {GenericConversionService$ConvertersForPair@5286} "org.springframework.core.convert.support.ObjectToCollectionConverter@36fcae1a"
{GenericConverter$ConvertiblePair@5287} "java.nio.ByteBuffer -> java.lang.Object" -> {GenericConversionService$ConvertersForPair@5288} "org.springframework.core.convert.support.ByteBufferConverter@dc48475"
{GenericConverter$ConvertiblePair@5289} "java.lang.Object -> java.nio.ByteBuffer" -> {GenericConversionService$ConvertersForPair@5290} "org.springframework.core.convert.support.ByteBufferConverter@dc48475"
{GenericConverter$ConvertiblePair@5291} "java.time.ZoneId -> java.util.TimeZone" -> {GenericConversionService$ConvertersForPair@5292} "java.time.ZoneId -> java.util.TimeZone : org.springframework.core.convert.support.ZoneIdToTimeZoneConverter@3bec82bf"
{GenericConverter$ConvertiblePair@5293} "java.time.ZonedDateTime -> java.util.Calendar" -> {GenericConversionService$ConvertersForPair@5294} "java.time.ZonedDateTime -> java.util.Calendar : org.springframework.core.convert.support.ZonedDateTimeToCalendarConverter@514a4df0"
{GenericConverter$ConvertiblePair@5295} "java.lang.Object -> java.lang.Object" -> {GenericConversionService$ConvertersForPair@5296} "org.springframework.core.convert.support.IdToEntityConverter@295a5bd,org.springframework.core.convert.support.ObjectToObjectConverter@2b5b7eb6"
{GenericConverter$ConvertiblePair@5297} "java.lang.Object -> java.lang.String" -> {GenericConversionService$ConvertersForPair@5298} "org.springframework.core.convert.support.FallbackObjectToStringConverter@747de818"
{GenericConverter$ConvertiblePair@5299} "java.lang.Object -> java.util.Optional" -> {GenericConversionService$ConvertersForPair@5300} "org.springframework.core.convert.support.ObjectToOptionalConverter@77db0eaa"
{GenericConverter$ConvertiblePair@5301} "java.lang.Long -> java.lang.String" -> {GenericConversionService$ConvertersForPair@5302} "@org.springframework.format.annotation.DateTimeFormat java.lang.Long -> java.lang.String: org.springframework.format.datetime.DateTimeFormatAnnotationFormatterFactory@584ce5a1,@org.springframework.format.annotation.NumberFormat java.lang.Long -> java.lang.String: org.springframework.format.number.NumberFormatAnnotationFormatterFactory@28929ed0"
{GenericConverter$ConvertiblePair@5303} "java.lang.String -> java.lang.Long" -> {GenericConversionService$ConvertersForPair@5304} "java.lang.String -> @org.springframework.format.annotation.DateTimeFormat java.lang.Long: org.springframework.format.datetime.DateTimeFormatAnnotationFormatterFactory@584ce5a1,java.lang.String -> @org.springframework.format.annotation.NumberFormat java.lang.Long: org.springframework.format.number.NumberFormatAnnotationFormatterFactory@28929ed0"
{GenericConverter$ConvertiblePair@5305} "java.math.BigInteger -> java.lang.String" -> {GenericConversionService$ConvertersForPair@5306} "@org.springframework.format.annotation.NumberFormat java.math.BigInteger -> java.lang.String: org.springframework.format.number.NumberFormatAnnotationFormatterFactory@28929ed0"
{GenericConverter$ConvertiblePair@5307} "java.lang.String -> java.math.BigInteger" -> {GenericConversionService$ConvertersForPair@5308} "java.lang.String -> @org.springframework.format.annotation.NumberFormat java.math.BigInteger: org.springframework.format.number.NumberFormatAnnotationFormatterFactory@28929ed0"
{GenericConverter$ConvertiblePair@5309} "java.lang.Float -> java.lang.String" -> {GenericConversionService$ConvertersForPair@5310} "@org.springframework.format.annotation.NumberFormat java.lang.Float -> java.lang.String: org.springframework.format.number.NumberFormatAnnotationFormatterFactory@28929ed0"
{GenericConverter$ConvertiblePair@5311} "java.lang.String -> java.lang.Float" -> {GenericConversionService$ConvertersForPair@5312} "java.lang.String -> @org.springframework.format.annotation.NumberFormat java.lang.Float: org.springframework.format.number.NumberFormatAnnotationFormatterFactory@28929ed0"
{GenericConverter$ConvertiblePair@5313} "java.lang.Double -> java.lang.String" -> {GenericConversionService$ConvertersForPair@5314} "@org.springframework.format.annotation.NumberFormat java.lang.Double -> java.lang.String: org.springframework.format.number.NumberFormatAnnotationFormatterFactory@28929ed0"
{GenericConverter$ConvertiblePair@5315} "java.lang.String -> java.lang.Double" -> {GenericConversionService$ConvertersForPair@5316} "java.lang.String -> @org.springframework.format.annotation.NumberFormat java.lang.Double: org.springframework.format.number.NumberFormatAnnotationFormatterFactory@28929ed0"
{GenericConverter$ConvertiblePair@5317} "java.lang.Short -> java.lang.String" -> {GenericConversionService$ConvertersForPair@5318} "@org.springframework.format.annotation.NumberFormat java.lang.Short -> java.lang.String: org.springframework.format.number.NumberFormatAnnotationFormatterFactory@28929ed0"
{GenericConverter$ConvertiblePair@5319} "java.lang.String -> java.lang.Short" -> {GenericConversionService$ConvertersForPair@5320} "java.lang.String -> @org.springframework.format.annotation.NumberFormat java.lang.Short: org.springframework.format.number.NumberFormatAnnotationFormatterFactory@28929ed0"
{GenericConverter$ConvertiblePair@5321} "java.lang.Integer -> java.lang.String" -> {GenericConversionService$ConvertersForPair@5322} "@org.springframework.format.annotation.NumberFormat java.lang.Integer -> java.lang.String: org.springframework.format.number.NumberFormatAnnotationFormatterFactory@28929ed0"
{GenericConverter$ConvertiblePair@5323} "java.lang.String -> java.lang.Integer" -> {GenericConversionService$ConvertersForPair@5324} "java.lang.String -> @org.springframework.format.annotation.NumberFormat java.lang.Integer: org.springframework.format.number.NumberFormatAnnotationFormatterFactory@28929ed0"
{GenericConverter$ConvertiblePair@5325} "java.lang.Byte -> java.lang.String" -> {GenericConversionService$ConvertersForPair@5326} "@org.springframework.format.annotation.NumberFormat java.lang.Byte -> java.lang.String: org.springframework.format.number.NumberFormatAnnotationFormatterFactory@28929ed0"
{GenericConverter$ConvertiblePair@5327} "java.lang.String -> java.lang.Byte" -> {GenericConversionService$ConvertersForPair@5328} "java.lang.String -> @org.springframework.format.annotation.NumberFormat java.lang.Byte: org.springframework.format.number.NumberFormatAnnotationFormatterFactory@28929ed0"
{GenericConverter$ConvertiblePair@5329} "java.math.BigDecimal -> java.lang.String" -> {GenericConversionService$ConvertersForPair@5330} "@org.springframework.format.annotation.NumberFormat java.math.BigDecimal -> java.lang.String: org.springframework.format.number.NumberFormatAnnotationFormatterFactory@28929ed0"
{GenericConverter$ConvertiblePair@5331} "java.lang.String -> java.math.BigDecimal" -> {GenericConversionService$ConvertersForPair@5332} "java.lang.String -> @org.springframework.format.annotation.NumberFormat java.math.BigDecimal: org.springframework.format.number.NumberFormatAnnotationFormatterFactory@28929ed0"
{GenericConverter$ConvertiblePair@5333} "java.util.Date -> java.lang.Long" -> {GenericConversionService$ConvertersForPair@5334} "java.util.Date -> java.lang.Long : org.springframework.format.datetime.DateFormatterRegistrar$DateToLongConverter@33349ef2,java.util.Date -> java.lang.Long : org.springframework.format.datetime.DateFormatterRegistrar$DateToLongConverter@1cb56860"
{GenericConverter$ConvertiblePair@5335} "java.util.Date -> java.util.Calendar" -> {GenericConversionService$ConvertersForPair@5336} "java.util.Date -> java.util.Calendar : org.springframework.format.datetime.DateFormatterRegistrar$DateToCalendarConverter@236be7ba,java.util.Date -> java.util.Calendar : org.springframework.format.datetime.DateFormatterRegistrar$DateToCalendarConverter@1f338919"
{GenericConverter$ConvertiblePair@5337} "java.util.Calendar -> java.util.Date" -> {GenericConversionService$ConvertersForPair@5338} "java.util.Calendar -> java.util.Date : org.springframework.format.datetime.DateFormatterRegistrar$CalendarToDateConverter@8675703,java.util.Calendar -> java.util.Date : org.springframework.format.datetime.DateFormatterRegistrar$CalendarToDateConverter@3f26c807"
{GenericConverter$ConvertiblePair@5339} "java.util.Calendar -> java.lang.Long" -> {GenericConversionService$ConvertersForPair@5340} "java.util.Calendar -> java.lang.Long : org.springframework.format.datetime.DateFormatterRegistrar$CalendarToLongConverter@438cbe6e,java.util.Calendar -> java.lang.Long : org.springframework.format.datetime.DateFormatterRegistrar$CalendarToLongConverter@40f48c47"
{GenericConverter$ConvertiblePair@5341} "java.lang.Long -> java.util.Date" -> {GenericConversionService$ConvertersForPair@5342} "java.lang.Long -> java.util.Date : org.springframework.format.datetime.DateFormatterRegistrar$LongToDateConverter@72191415,java.lang.Long -> java.util.Date : org.springframework.format.datetime.DateFormatterRegistrar$LongToDateConverter@7bf68ca1"
{GenericConverter$ConvertiblePair@5343} "java.lang.Long -> java.util.Calendar" -> {GenericConversionService$ConvertersForPair@5344} "java.lang.Long -> java.util.Calendar : org.springframework.format.datetime.DateFormatterRegistrar$LongToCalendarConverter@5daf227f,java.lang.Long -> java.util.Calendar : org.springframework.format.datetime.DateFormatterRegistrar$LongToCalendarConverter@39dd1b39"
{GenericConverter$ConvertiblePair@5345} "java.time.LocalDateTime -> java.time.LocalDate" -> {GenericConversionService$ConvertersForPair@5346} "java.time.LocalDateTime -> java.time.LocalDate : org.springframework.format.datetime.standard.DateTimeConverters$LocalDateTimeToLocalDateConverter@3de19ab"
{GenericConverter$ConvertiblePair@5347} "java.time.LocalDateTime -> java.time.LocalTime" -> {GenericConversionService$ConvertersForPair@5348} "java.time.LocalDateTime -> java.time.LocalTime : org.springframework.format.datetime.standard.DateTimeConverters$LocalDateTimeToLocalTimeConverter@4c021ef5"
{GenericConverter$ConvertiblePair@5349} "java.time.ZonedDateTime -> java.time.LocalDate" -> {GenericConversionService$ConvertersForPair@5350} "java.time.ZonedDateTime -> java.time.LocalDate : org.springframework.format.datetime.standard.DateTimeConverters$ZonedDateTimeToLocalDateConverter@681a61d0"
{GenericConverter$ConvertiblePair@5351} "java.time.ZonedDateTime -> java.time.LocalTime" -> {GenericConversionService$ConvertersForPair@5352} "java.time.ZonedDateTime -> java.time.LocalTime : org.springframework.format.datetime.standard.DateTimeConverters$ZonedDateTimeToLocalTimeConverter@39cfbb39"
{GenericConverter$ConvertiblePair@5353} "java.time.ZonedDateTime -> java.time.LocalDateTime" -> {GenericConversionService$ConvertersForPair@5354} "java.time.ZonedDateTime -> java.time.LocalDateTime : org.springframework.format.datetime.standard.DateTimeConverters$ZonedDateTimeToLocalDateTimeConverter@4aaffeea"
{GenericConverter$ConvertiblePair@5355} "java.time.ZonedDateTime -> java.time.OffsetDateTime" -> {GenericConversionService$ConvertersForPair@5356} "java.time.ZonedDateTime -> java.time.OffsetDateTime : org.springframework.format.datetime.standard.DateTimeConverters$ZonedDateTimeToOffsetDateTimeConverter@1686a4fc"
{GenericConverter$ConvertiblePair@5357} "java.time.ZonedDateTime -> java.time.Instant" -> {GenericConversionService$ConvertersForPair@5358} "java.time.ZonedDateTime -> java.time.Instant : org.springframework.format.datetime.standard.DateTimeConverters$ZonedDateTimeToInstantConverter@2d29531d"
{GenericConverter$ConvertiblePair@5359} "java.time.OffsetDateTime -> java.time.LocalDate" -> {GenericConversionService$ConvertersForPair@5360} "java.time.OffsetDateTime -> java.time.LocalDate : org.springframework.format.datetime.standard.DateTimeConverters$OffsetDateTimeToLocalDateConverter@69fb23f2"
{GenericConverter$ConvertiblePair@5361} "java.time.OffsetDateTime -> java.time.LocalTime" -> {GenericConversionService$ConvertersForPair@5362} "java.time.OffsetDateTime -> java.time.LocalTime : org.springframework.format.datetime.standard.DateTimeConverters$OffsetDateTimeToLocalTimeConverter@5c16d889"
{GenericConverter$ConvertiblePair@5363} "java.time.OffsetDateTime -> java.time.LocalDateTime" -> {GenericConversionService$ConvertersForPair@5364} "java.time.OffsetDateTime -> java.time.LocalDateTime : org.springframework.format.datetime.standard.DateTimeConverters$OffsetDateTimeToLocalDateTimeConverter@7f9426b3"
{GenericConverter$ConvertiblePair@5365} "java.time.OffsetDateTime -> java.time.ZonedDateTime" -> {GenericConversionService$ConvertersForPair@5366} "java.time.OffsetDateTime -> java.time.ZonedDateTime : org.springframework.format.datetime.standard.DateTimeConverters$OffsetDateTimeToZonedDateTimeConverter@18c233e7"
{GenericConverter$ConvertiblePair@5367} "java.time.OffsetDateTime -> java.time.Instant" -> {GenericConversionService$ConvertersForPair@5368} "java.time.OffsetDateTime -> java.time.Instant : org.springframework.format.datetime.standard.DateTimeConverters$OffsetDateTimeToInstantConverter@289667be"
{GenericConverter$ConvertiblePair@5369} "java.util.Calendar -> java.time.ZonedDateTime" -> {GenericConversionService$ConvertersForPair@5370} "java.util.Calendar -> java.time.ZonedDateTime : org.springframework.format.datetime.standard.DateTimeConverters$CalendarToZonedDateTimeConverter@422e30b5"
{GenericConverter$ConvertiblePair@5371} "java.util.Calendar -> java.time.OffsetDateTime" -> {GenericConversionService$ConvertersForPair@5372} "java.util.Calendar -> java.time.OffsetDateTime : org.springframework.format.datetime.standard.DateTimeConverters$CalendarToOffsetDateTimeConverter@1cd137fd"
{GenericConverter$ConvertiblePair@5373} "java.util.Calendar -> java.time.LocalDate" -> {GenericConversionService$ConvertersForPair@5374} "java.util.Calendar -> java.time.LocalDate : org.springframework.format.datetime.standard.DateTimeConverters$CalendarToLocalDateConverter@1585728b"
{GenericConverter$ConvertiblePair@5375} "java.util.Calendar -> java.time.LocalTime" -> {GenericConversionService$ConvertersForPair@5376} "java.util.Calendar -> java.time.LocalTime : org.springframework.format.datetime.standard.DateTimeConverters$CalendarToLocalTimeConverter@e355c12"
{GenericConverter$ConvertiblePair@5377} "java.util.Calendar -> java.time.LocalDateTime" -> {GenericConversionService$ConvertersForPair@5378} "java.util.Calendar -> java.time.LocalDateTime : org.springframework.format.datetime.standard.DateTimeConverters$CalendarToLocalDateTimeConverter@3d2d7ef9"
{GenericConverter$ConvertiblePair@5379} "java.util.Calendar -> java.time.Instant" -> {GenericConversionService$ConvertersForPair@5380} "java.util.Calendar -> java.time.Instant : org.springframework.format.datetime.standard.DateTimeConverters$CalendarToInstantConverter@2856c87e"
{GenericConverter$ConvertiblePair@5381} "java.lang.Long -> java.time.Instant" -> {GenericConversionService$ConvertersForPair@5382} "java.lang.Long -> java.time.Instant : org.springframework.format.datetime.standard.DateTimeConverters$LongToInstantConverter@16f9f6d5"
{GenericConverter$ConvertiblePair@5383} "java.time.Instant -> java.lang.Long" -> {GenericConversionService$ConvertersForPair@5384} "java.time.Instant -> java.lang.Long : org.springframework.format.datetime.standard.DateTimeConverters$InstantToLongConverter@3208fdd4"
{GenericConverter$ConvertiblePair@5385} "java.time.LocalDate -> java.lang.String" -> {GenericConversionService$ConvertersForPair@5386} "@org.springframework.format.annotation.DateTimeFormat java.time.LocalDate -> java.lang.String: org.springframework.format.datetime.standard.Jsr310DateTimeFormatAnnotationFormatterFactory@648487da,java.time.LocalDate -> java.lang.String : org.springframework.format.datetime.standard.TemporalAccessorPrinter@7a0fb60c"
{GenericConverter$ConvertiblePair@5387} "java.lang.String -> java.time.LocalDate" -> {GenericConversionService$ConvertersForPair@5388} "java.lang.String -> @org.springframework.format.annotation.DateTimeFormat java.time.LocalDate: org.springframework.format.datetime.standard.Jsr310DateTimeFormatAnnotationFormatterFactory@648487da,java.lang.String -> java.time.LocalDate: org.springframework.format.datetime.standard.TemporalAccessorParser@2319a8c6"
{GenericConverter$ConvertiblePair@5389} "java.time.LocalTime -> java.lang.String" -> {GenericConversionService$ConvertersForPair@5390} "@org.springframework.format.annotation.DateTimeFormat java.time.LocalTime -> java.lang.String: org.springframework.format.datetime.standard.Jsr310DateTimeFormatAnnotationFormatterFactory@648487da,java.time.LocalTime -> java.lang.String : org.springframework.format.datetime.standard.TemporalAccessorPrinter@560a172c"
{GenericConverter$ConvertiblePair@5391} "java.lang.String -> java.time.LocalTime" -> {GenericConversionService$ConvertersForPair@5392} "java.lang.String -> @org.springframework.format.annotation.DateTimeFormat java.time.LocalTime: org.springframework.format.datetime.standard.Jsr310DateTimeFormatAnnotationFormatterFactory@648487da,java.lang.String -> java.time.LocalTime: org.springframework.format.datetime.standard.TemporalAccessorParser@1670e060"
{GenericConverter$ConvertiblePair@5393} "java.time.LocalDateTime -> java.lang.String" -> {GenericConversionService$ConvertersForPair@5394} "@org.springframework.format.annotation.DateTimeFormat java.time.LocalDateTime -> java.lang.String: org.springframework.format.datetime.standard.Jsr310DateTimeFormatAnnotationFormatterFactory@648487da,java.time.LocalDateTime -> java.lang.String : org.springframework.format.datetime.standard.TemporalAccessorPrinter@11c88b74"
{GenericConverter$ConvertiblePair@5395} "java.lang.String -> java.time.LocalDateTime" -> {GenericConversionService$ConvertersForPair@5396} "java.lang.String -> @org.springframework.format.annotation.DateTimeFormat java.time.LocalDateTime: org.springframework.format.datetime.standard.Jsr310DateTimeFormatAnnotationFormatterFactory@648487da,java.lang.String -> java.time.LocalDateTime: org.springframework.format.datetime.standard.TemporalAccessorParser@7f794e13"
{GenericConverter$ConvertiblePair@5397} "java.time.ZonedDateTime -> java.lang.String" -> {GenericConversionService$ConvertersForPair@5398} "@org.springframework.format.annotation.DateTimeFormat java.time.ZonedDateTime -> java.lang.String: org.springframework.format.datetime.standard.Jsr310DateTimeFormatAnnotationFormatterFactory@648487da,java.time.ZonedDateTime -> java.lang.String : org.springframework.format.datetime.standard.TemporalAccessorPrinter@794c95a7"
{GenericConverter$ConvertiblePair@5399} "java.lang.String -> java.time.ZonedDateTime" -> {GenericConversionService$ConvertersForPair@5400} "java.lang.String -> @org.springframework.format.annotation.DateTimeFormat java.time.ZonedDateTime: org.springframework.format.datetime.standard.Jsr310DateTimeFormatAnnotationFormatterFactory@648487da,java.lang.String -> java.time.ZonedDateTime: org.springframework.format.datetime.standard.TemporalAccessorParser@68ae090e"
{GenericConverter$ConvertiblePair@5401} "java.time.OffsetDateTime -> java.lang.String" -> {GenericConversionService$ConvertersForPair@5402} "@org.springframework.format.annotation.DateTimeFormat java.time.OffsetDateTime -> java.lang.String: org.springframework.format.datetime.standard.Jsr310DateTimeFormatAnnotationFormatterFactory@648487da,java.time.OffsetDateTime -> java.lang.String : org.springframework.format.datetime.standard.TemporalAccessorPrinter@3d68ac44"
{GenericConverter$ConvertiblePair@5403} "java.lang.String -> java.time.OffsetDateTime" -> {GenericConversionService$ConvertersForPair@5404} "java.lang.String -> @org.springframework.format.annotation.DateTimeFormat java.time.OffsetDateTime: org.springframework.format.datetime.standard.Jsr310DateTimeFormatAnnotationFormatterFactory@648487da,java.lang.String -> java.time.OffsetDateTime: org.springframework.format.datetime.standard.TemporalAccessorParser@854642c"
{GenericConverter$ConvertiblePair@5405} "java.time.OffsetTime -> java.lang.String" -> {GenericConversionService$ConvertersForPair@5406} "@org.springframework.format.annotation.DateTimeFormat java.time.OffsetTime -> java.lang.String: org.springframework.format.datetime.standard.Jsr310DateTimeFormatAnnotationFormatterFactory@648487da,java.time.OffsetTime -> java.lang.String : org.springframework.format.datetime.standard.TemporalAccessorPrinter@15a8392c"
{GenericConverter$ConvertiblePair@5407} "java.lang.String -> java.time.OffsetTime" -> {GenericConversionService$ConvertersForPair@5408} "java.lang.String -> @org.springframework.format.annotation.DateTimeFormat java.time.OffsetTime: org.springframework.format.datetime.standard.Jsr310DateTimeFormatAnnotationFormatterFactory@648487da,java.lang.String -> java.time.OffsetTime: org.springframework.format.datetime.standard.TemporalAccessorParser@dd6b4ee"
{GenericConverter$ConvertiblePair@5409} "java.time.Instant -> java.lang.String" -> {GenericConversionService$ConvertersForPair@5410} "java.time.Instant -> java.lang.String : org.springframework.format.datetime.standard.InstantFormatter@7524339c"
{GenericConverter$ConvertiblePair@5411} "java.lang.String -> java.time.Instant" -> {GenericConversionService$ConvertersForPair@5412} "java.lang.String -> java.time.Instant: org.springframework.format.datetime.standard.InstantFormatter@7524339c"
{GenericConverter$ConvertiblePair@5413} "java.util.Calendar -> java.lang.String" -> {GenericConversionService$ConvertersForPair@5414} "@org.springframework.format.annotation.DateTimeFormat java.util.Calendar -> java.lang.String: org.springframework.format.datetime.DateTimeFormatAnnotationFormatterFactory@584ce5a1"
{GenericConverter$ConvertiblePair@5415} "java.lang.String -> java.util.Calendar" -> {GenericConversionService$ConvertersForPair@5416} "java.lang.String -> @org.springframework.format.annotation.DateTimeFormat java.util.Calendar: org.springframework.format.datetime.DateTimeFormatAnnotationFormatterFactory@584ce5a1"
{GenericConverter$ConvertiblePair@5417} "java.util.Date -> java.lang.String" -> {GenericConversionService$ConvertersForPair@5418} "@org.springframework.format.annotation.DateTimeFormat java.util.Date -> java.lang.String: org.springframework.format.datetime.DateTimeFormatAnnotationFormatterFactory@584ce5a1"
{GenericConverter$ConvertiblePair@5419} "java.lang.String -> java.util.Date" -> {GenericConversionService$ConvertersForPair@5420} "java.lang.String -> @org.springframework.format.annotation.DateTimeFormat java.util.Date: org.springframework.format.datetime.DateTimeFormatAnnotationFormatterFactory@584ce5a1"

  ③ WebDataBinder 核心类

  WebDataBinder:数据绑定器负责数据绑定工作,负责数据绑定期间产生的类型转换、格式化、数据校验等问题
    (1)ConversionService 组件进行数据类型转换、数据格式化工作;
    (2)Validator 组件对已经绑定了请求消息的入参对象进行数据合法性校验,并最终生成数据绑定结果 BindingData 对象;
    (3)BindingResult 负责保存以及解析数据绑定期间数据校验产生的错误;
       Spring MVC 抽取 BindingResult 中的入参对象和校验错误对象,将它们赋给处理方法的响应入参;

  

四、SpringMVC 的类型转换器

  ConversionService 组件:负责数据类型的转换以及格式化功能;
  ConversionService有非常多的 convert,不同类型的转换和格式化用它自己的 converter;

  Spring MVC 上下文中内建了很多转换器,可完成大多数 Java 类型的转换工作。

  以 StringToNumberConverterFactory 为例分析:

{GenericConverter$ConvertiblePair@5229} "java.lang.String -> java.lang.Number" -> {GenericConversionService$ConvertersForPair@5230} "java.lang.String -> java.lang.Number : org.springframework.core.convert.support.StringToNumberConverterFactory@2d148610"

  

  查看:StringToNumberConverterFactory源码,在getConverter()方法中设置断点,在执行set方法(性别字段)前会调用该方法。

final class StringToNumberConverterFactory implements ConverterFactory<String, Number> {

    @Override
    public <T extends Number> Converter<String, T> getConverter(Class<T> targetType) {
        return new StringToNumber<T>(targetType);
    }

    private static final class StringToNumber<T extends Number> implements Converter<String, T> {

        private final Class<T> targetType;

        public StringToNumber(Class<T> targetType) {
            this.targetType = targetType;
        }

        @Override
        public T convert(String source) {
            if (source.length() == 0) {
                return null;
            }
            return NumberUtils.parseNumber(source, this.targetType);
        }
    }

}

五、@InitBinder 注解(了解)

  由 @InitBinder 标识的方法,可以对 WebDataBinder 对象进行初始化。WebDataBinder 是 DataBinder 的子类,用于完成由表单字段到 JavaBean 属性的绑定

  @InitBinder方法不能有返回值,它必须声明为void。

  @InitBinder方法的参数通常是 WebDataBinder。

  

   示例代码:

/**
由 @InitBinder 标识的方法,可以对 WebDataBinder 对象进行初始化。
WebDataBinder 是 DataBinder 的子类,用于完成由表单字段到 JavaBean 属性的绑定
@InitBinder方法不能有返回值,它必须声明为void。
@InitBinder方法的参数通常是 WebDataBinder
 */
@InitBinder
public void initBinder(WebDataBinder dataBinder){
    dataBinder.setDisallowedFields("lastName");
}
原文地址:https://www.cnblogs.com/niujifei/p/15627979.html