10、实体类(POJO)参数的赋值(form表单)原理

10.1、原理解析

  1. 测试用例

    • 准备好两个实体类
    public class Person {
    private String name;
    private Integer age;
    private Pet pet;
    } public class Pet {
    private String name;
    private Integer age;
    }
    • html的form表单

      注意这个 宠物Pet对象的name不能乱写 必须要和 person中定义的名称一样 才可以

    <form action="/person" method="post">
    <input type="text" name="name" value="水三丫">
    <input type="text" name="age" value="18">
    <input type="text" name="pet.name" value="阿猫">
    <input type="text" name="pet.age" value="10">
    <input type="submit" value="Person">
    </form>
    • Controller请求代码
    @PostMapping("/person")
    public Map person(Person person){
    Map<String, Person> map = new HashMap<>();
    map.put("person",person);
    return map;
    }
  2. 源码Debug

    • 从DispatchServlet 的 doDispatch方法开始

      DispatchServlet类中的
      doDispatch方法
      //RequestMappingHandlerAdapter这个处理器
      HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());
    • 获取请求参数的处理器

      HandlerMethodArgumentResolverComposite类中的
      getArgumentResolver方法
      //总共27个处理器
      ServletModelAttributeMethodProcessor这个处理Pojo实体类的参数
    • 创建实体类构造器和赋值

      • 创造构造器
      ModelAttributeMethodProcessor类中的
      resolveArgument方法
      // Create attribute instance
      try {
      attribute = createAttribute(name, parameter,
      binderFactory, webRequest);
      }
      createAttribute方法 //反射获取空参构造器
      Constructor<?> ctor = BeanUtils.getResolvableConstructor(clazz);
      Constructor<?> ctor = BeanUtils.getResolvableConstructor(clazz);
      Object attribute = constructAttribute(ctor, attributeName, parameter,
      binderFactory, webRequest);

      • 属性绑定和验证
      ModelAttributeMethodProcessor类中的
      resolveArgument方法
      // Bean property binding and validation;
      // skipped in case of binding failure on construction.
      WebDataBinder binder = binderFactory.createBinder(webRequest, attribute,
      name);

      • 获取请求的参数
      ServletModelAttributeMethodProcessor类中订单
      bindRequestParameters方法
      servletBinder.bind(servletRequest);
      ServletRequestDataBinder类中的
      bind方法
      MutablePropertyValues mpvs = new
      ServletRequestParameterPropertyValues(request);
      WebUtils方法类中
      getParametersStartingWith方法
      Enumeration<String> paramNames = request.getParameterNames();
      Map<String, Object> params = new TreeMap<>();

      • 准备开始数据绑定

        ServletRequestDataBinder类中的
        bind方法
        doBind(mpvs);
        WebDataBinder类中的
        doBind方法
        super.doBind(mpvs);
        DataBinder类中的
        doBind方法
        applyPropertyValues(mpvs);
        AbstractPropertyAccessor类中的
        setPropertyValues方法
        try {
        setPropertyValue(pv);
        }

        第一步获取数据的绑定格式转换的处理器(因为浏览器以JSOn穿过了的都是字符串)需要格式转换

        TypeConverterDelegate类中的
        convertIfNecessary方法
        try {
        //传入的是请求的参数值 参数类型 需要转换的类型
        return (T) conversionService.convert(newValue, sourceTypeDesc,
        typeDescriptor);
        }
        GenericConversionService类中的
        convert方法
        GenericConverter converter = getConverter(sourceType, targetType);
        getConverter方法
        ConverterCacheKey key = new ConverterCacheKey(sourceType, targetType);
        GenericConverter converter = this.converterCache.get(key);

        需要124个类型转换中寻找这次需要的

        需要的是:

        获取的转换器

        第二步转换数据

        GenericConversionService类中的
        convert方法
        Object result = ConversionUtils.invokeConverter(converter, source,
        sourceType,targetType);

        第三步开始赋值

        AbstractNestablePropertyAccessor类中的
        processLocalProperty方法
        ph.setValue(valueToApply);

        获取set方法

        BeanWrapperImpl类中的
        setValue方法
        Method writeMethod = (this.pd instanceof
        GenericTypeAwarePropertyDescriptor ?
        ((GenericTypeAwarePropertyDescriptor)
        this.pd).getWriteMethodForActualAccess() :
        this.pd.getWriteMethod());

        开始反射赋值

        BeanWrapperImpl类中的
        setValue方法
        writeMethod.invoke(getWrappedInstance(), value);

        赋值完成

10.2、定制化属性转换器

  1. 编写自定义配置转换规则

    @Bean
    public WebMvcConfigurer webMvcConfigurer(){
    return new WebMvcConfigurer() {
    @Override
    public void addFormatters(FormatterRegistry registry) {
    registry.addConverter(new Converter<String, Pet>() {//增加一个转换器
    @Override
    public Pet convert(String source) {//实现这个接口的方法
    if(!StringUtils.isEmpty(source)){
    Pet pet = new Pet();
    String[] split = source.split(",");//以逗号为分隔符
    pet.setName(split[0]);
    pet.setAge(Integer.parseInt(split[1]));
    return pet;
    }
    return null;
    }
    });
    }
    };
    }

    lambda表达式写法

    @Bean
    public WebMvcConfigurer webMvcConfigurer(){
    @Override
    public void addFormatters(FormatterRegistry registry) {
    registry.addConverter(String.class,Pet.class, source -> { if(!StringUtils.isEmpty(source)){
    Pet pet = new Pet();
    String[] split = source.split(",");
    pet.setName(split[0]);
    pet.setAge(Integer.parseInt(split[1]));
    return pet;
    }
    return null;
    });
    }
    };
    }
  2. 测试用例

    html页面form表单代码

    <form action="/person1" method="post">
    <input type="text" name="name" value="水三丫">
    <input type="text" name="age" value="18">
    <input type="text" name="pet" value="阿猫,10">
    <input type="submit" value="Person1">
    </form>
  3. Debug测试

    测试的时候就会在全部转换器中找到我们定制的哪一个

spring实体类(POJO)参数的赋值(form表单)原理的更多相关文章

  1. js 取值&赋值-form表单

      form表单元素介绍 CreateTime--2016年9月22日10:25:54 Author:Marydon <form> 表单元素. 表单中的元素: <input>表 ...

  2. 1113 form表单与css选择器

    目录 1.form表单 form元素 特点 参数 form元素内的控件 1.input的使用 2.select标签 3.textarea元素 4.autofocus属性 2.CSS 1.基础语法 cs ...

  3. Java如何实现form表单提交的数据自动对应实体类(源码)

    原文出自:https://blog.csdn.net/seesun2012 原生Java+JQuery form表单serializeArray提交自动对应java实体,这是一个实际的例子: html ...

  4. @NamedEntityGraphs --JPA按实体类对象参数中的字段排序问题得解决方法

    JPA按实体类对象参数中的字段排序问题得解决方法@Entity @Table(name="complaints") @NamedEntityGraphs({ @NamedEntit ...

  5. c# 实体类怎么给LIST赋值,table转LIST

    /// <summary> /// 缓存客服集合信息 /// </summary> public class model { /// <summary> /// 客 ...

  6. 实体类相同属性间赋值与如何判断实体类中是否所有的字段都为null

    1,实体类相同属性间赋值 /// <summary> /// 将实体2的值动态赋值给实体1(名称一样的属性进行赋值) /// </summary> /// <param ...

  7. SpringMVC中使用bean来接收form表单提交的参数时的注意点

    这是前辈们对于SpringMVC接收表单数据记录下来的总结经验: SpringMVC接收页面表单参数 springmvc请求参数获取的几种方法 下面是我自己在使用时发现的,前辈们没有记录的细节和注意点 ...

  8. JsonResponse类的使用、form表单上传文件补充、CBV和FBV、HTML的模板语法之传值与过滤器

    昨日内容回顾 Django请求生命周期 # 1.浏览器发起请求 到达Django的socket服务端(web服务网关接口) 01 wsgiref 02 uwsgi + nginx 03 WSGI协议 ...

  9. Form 表单提交参数

    今天因为要额外提交参数数组性的参数给form传到后台而苦恼了半天,结果发现,只需要在form表单对应的字段html空间中定义name = 后台参数名 的属性就ok了. 后台本来是只有模型参数的,但是后 ...

随机推荐

  1. Java线程同步操作

    synchronized 作用于对象实例:对给定对象加锁,进入同步代码前要获得给定对象的锁. 作用于实例方法:相当于对当前实例加锁,进入同步代码前要获得当前实例的锁. 作用于静态方法:相当于对当前类加 ...

  2. Java获取特定区间随机数及产生不重复随机数

    问题 有这样一种需求,在这样一个数组中String[] arr = new String[]{"电商", "互联网", "小程序", &qu ...

  3. 「Java分享客栈」随时用随时翻:微服务链路追踪之zipkin搭建

    前言 微服务治理方案中,链路追踪是必修课,SpringCloud的组件其实使用很简单,生产环境中真正令人头疼的往往是软件维护,接口在微服务间的调用究竟哪个环节出现了问题,哪个环节耗时较长,这都是项目上 ...

  4. Scalable Multi-Party Private Set-Intersection-解读

    本文记录阅读该paper的笔记. 摘要 本文给出两种MPSI协议,采用的是星型拓扑结构,即有一个leader,需要和其他参与者交互.优点是并非所有各方都必须同时在线: (1)能抗半诚实攻击 通信复杂度 ...

  5. Java - ConcurrentHashMap的原理

    Java - ConcurrentHashMap的原理 **这是JDK1.7的实现** ConcurrentHashMap 类中包含两个静态内部类 HashEntry 和 Segment. HashE ...

  6. ElasticSearch6.4.2

    做一个简单的API记录 1.依赖为6.4.2  比较老的版本 2.指定ES集群,可接多个Put(); Setting setting=Setting.builder().put("clust ...

  7. 十二张图:从0开始理解对称/非对称加密、CA认证、以及K8S各组件颁发证书原由

    目录 一.对称加密 二.对称加密-不安全 三.非对称加密 四.非对称加密-不安全 五.对称加密和非对称加密结合 六.对称加密和非对称加密结合-不安全 七.Https的做法-引入CA机构 八.乘胜追击理 ...

  8. 入坑KeePass(四)KeePass通过坚果云WebDav同步方法

    参考博客:什么值得买平台-Keepass+坚果云:多平台密码无缝同步 .1.在坚果云上创建一个同步专用的文件夹(建议勾上"默认不同步到电脑"选项) 创建之后可以把刚才创建的数据库文 ...

  9. ExtJS 布局-Table布局(Table layout)

    更新记录: 2022年6月1日 开始. 2022年6月10日 发布. 1.说明 table布局类似表格,通过指定行列数实现布局. 2.设置布局方法 在父容器中指定 layout: 'table' la ...

  10. 如何提高访问 GitHub 的速度

    更新记录 本文迁移自Panda666原博客,原发布时间:2021年5月11日. 因为一些特殊的原因,国内访问Github的速度确实比较慢.国内访问Github经常会出现连接不上.图片加载不出来.文件无 ...