聊聊Spring中的数据绑定 --- WebDataBinder、ServletRequestDataBinder、WebBindingInitializer...【享学Spring】(下)

简介: 聊聊Spring中的数据绑定 --- WebDataBinder、ServletRequestDataBinder、WebBindingInitializer...【享学Spring】(下)

顾名思义它就是来创造一个WebDataBinder的工厂。

// @since 3.1   注意:WebDataBinder 可是1.2就有了~
public interface WebDataBinderFactory {
  // 此处使用的是Spring自己的NativeWebRequest   后面两个参数就不解释了
  WebDataBinder createBinder(NativeWebRequest webRequest, @Nullable Object target, String objectName) throws Exception;
}


它的继承树如下:


image.png


DefaultDataBinderFactory

public class DefaultDataBinderFactory implements WebDataBinderFactory {
  @Nullable
  private final WebBindingInitializer initializer;
  // 注意:这是唯一构造函数
  public DefaultDataBinderFactory(@Nullable WebBindingInitializer initializer) {
    this.initializer = initializer;
  }
  // 实现接口的方法
  @Override
  @SuppressWarnings("deprecation")
  public final WebDataBinder createBinder(NativeWebRequest webRequest, @Nullable Object target, String objectName) throws Exception {
    WebDataBinder dataBinder = createBinderInstance(target, objectName, webRequest);
    // 可见WebDataBinder 创建好后,此处就会回调(只有一个)
    if (this.initializer != null) {
      this.initializer.initBinder(dataBinder, webRequest);
    }
    // 空方法 子类去实现,比如InitBinderDataBinderFactory实现了词方法
    initBinder(dataBinder, webRequest);
    return dataBinder;
  }
  //  子类可以复写,默认实现是WebRequestDataBinder
  // 比如子类ServletRequestDataBinderFactory就复写了,使用的new ExtendedServletRequestDataBinder(target, objectName)
  protected WebDataBinder createBinderInstance(@Nullable Object target, String objectName, NativeWebRequest webRequest) throws Exception 
    return new WebRequestDataBinder(target, objectName);
  }
}


按照Spring一贯的设计,本方法实现了模板动作,子类只需要复写对应的动作即可达到效果。


InitBinderDataBinderFactory


它继承自DefaultDataBinderFactory,主要用于处理标注有@InitBinder的方法做初始绑定~


// @since 3.1
public class InitBinderDataBinderFactory extends DefaultDataBinderFactory {
  // 需要注意的是:`@InitBinder`可以标注N多个方法~  所以此处是List
  private final List<InvocableHandlerMethod> binderMethods;
  // 此子类的唯一构造函数
  public InitBinderDataBinderFactory(@Nullable List<InvocableHandlerMethod> binderMethods, @Nullable WebBindingInitializer initializer) {
    super(initializer);
    this.binderMethods = (binderMethods != null ? binderMethods : Collections.emptyList());
  }
  // 上面知道此方法的调用方法生initializer.initBinder之后
  // 所以使用注解它生效的时机是在直接实现接口的后面的~
  @Override
  public void initBinder(WebDataBinder dataBinder, NativeWebRequest request) throws Exception {
    for (InvocableHandlerMethod binderMethod : this.binderMethods) {
      // 判断@InitBinder是否对dataBinder持有的target对象生效~~~(根据name来匹配的)
      if (isBinderMethodApplicable(binderMethod, dataBinder)) {
        // 关于目标方法执行这块,可以参考另外一篇@InitBinder的原理说明~
        Object returnValue = binderMethod.invokeForRequest(request, null, dataBinder);
        // 标注@InitBinder的方法不能有返回值
        if (returnValue != null) {
          throw new IllegalStateException("@InitBinder methods must not return a value (should be void): " + binderMethod);
        }
      }
    }
  }
  //@InitBinder有个Value值,它是个数组。它是用来匹配dataBinder.getObjectName()是否匹配的   若匹配上了,现在此注解方法就会生效
  // 若value为空,那就对所有生效~~~
  protected boolean isBinderMethodApplicable(HandlerMethod initBinderMethod, WebDataBinder dataBinder) {
    InitBinder ann = initBinderMethod.getMethodAnnotation(InitBinder.class);
    Assert.state(ann != null, "No InitBinder annotation");
    String[] names = ann.value();
    return (ObjectUtils.isEmpty(names) || ObjectUtils.containsElement(names, dataBinder.getObjectName()));
  }
}


ServletRequestDataBinderFactory


它继承自InitBinderDataBinderFactory,作用就更明显了。既能够处理@InitBinder,而且它使用的是更为强大的数据绑定器:ExtendedServletRequestDataBinder

// @since 3.1
public class ServletRequestDataBinderFactory extends InitBinderDataBinderFactory {
  public ServletRequestDataBinderFactory(@Nullable List<InvocableHandlerMethod> binderMethods, @Nullable WebBindingInitializer initializer) {
    super(binderMethods, initializer);
  }
  @Override
  protected ServletRequestDataBinder createBinderInstance(
      @Nullable Object target, String objectName, NativeWebRequest request) throws Exception  {
    return new ExtendedServletRequestDataBinder(target, objectName);
  }
}


此工厂是RequestMappingHandlerAdapter这个适配器默认使用的一个数据绑定器工厂,而RequestMappingHandlerAdapter却又是当下使用得最频繁、功能最强大的一个适配器


总结


WebDataBinder在SpringMVC中使用,它不需要我们自己去创建,我们只需要向它注册参数类型对应的属性编辑器PropertyEditor。PropertyEditor可以将字符串转换成其真正的数据类型,它的void setAsText(String text)方法实现数据转换的过程。


好好掌握这部分内容,这在Spring MVC中结合@InitBinder注解一起使用将有非常大的威力,能一定程度上简化你的开发,提高效率

相关文章
|
1月前
|
数据采集 Java 数据安全/隐私保护
Spring Boot 3.3中的优雅实践:全局数据绑定与预处理
【10月更文挑战第22天】 在Spring Boot应用中,`@ControllerAdvice`是一个强大的工具,它允许我们在单个位置处理多个控制器的跨切面关注点,如全局数据绑定和预处理。这种方式可以大大减少重复代码,提高开发效率。本文将探讨如何在Spring Boot 3.3中使用`@ControllerAdvice`来实现全局数据绑定与预处理。
69 2
|
存储 前端开发 Java
Spring MVC 中的数据绑定和验证机制是什么,如何使用
Spring MVC 中的数据绑定和验证机制是什么,如何使用
|
7月前
|
存储 前端开发 Java
Spring Boot中Spring MVC的表单标签库与数据绑定讲解与实战(附源码 超详细必看)
Spring Boot中Spring MVC的表单标签库与数据绑定讲解与实战(附源码 超详细必看)
102 0
|
前端开发 Java 应用服务中间件
Spring MVC-05循序渐进之数据绑定和form标签库(下) 实战从0到1
Spring MVC-05循序渐进之数据绑定和form标签库(下) 实战从0到1
727 0
|
前端开发 Java 数据安全/隐私保护
Spring MVC-05循序渐进之数据绑定和form标签库(上)
Spring MVC-05循序渐进之数据绑定和form标签库(上)
10326 0
|
XML Java API
最新最全面的Spring详解(三)——Resources,验证、数据绑定和类型转换与Spring表达式语言(SpEL)(上)
最新最全面的Spring详解(三)——Resources,验证、数据绑定和类型转换与Spring表达式语言(SpEL)
224 0
最新最全面的Spring详解(三)——Resources,验证、数据绑定和类型转换与Spring表达式语言(SpEL)(上)
|
Java API Spring
Spring官网阅读(十六)Spring中的数据绑定(2)
Spring官网阅读(十六)Spring中的数据绑定(2)
252 0
Spring官网阅读(十六)Spring中的数据绑定(2)
|
XML Java 数据格式
最新最全面的Spring详解(三)——Resources,验证、数据绑定和类型转换与Spring表达式语言(SpEL)(下)
最新最全面的Spring详解(三)——Resources,验证、数据绑定和类型转换与Spring表达式语言(SpEL)(下)
275 0
|
XML 前端开发 Java
最新最全面的Spring详解(三)——Resources,验证、数据绑定和类型转换与Spring表达式语言(SpEL)(中)
最新最全面的Spring详解(三)——Resources,验证、数据绑定和类型转换与Spring表达式语言(SpEL)(中)
224 0
|
XML 存储 Java
聊聊 Spring 核心特性中的数据绑定 (DataBinder)
Spring 的核心特性包括 IOC 容器、事件、资源管理、国际化、校验、数据绑定、类型转换、EL 表达式、AOP。其他特性可以轻易的在网络上找到很多资料,而数据绑定这个特性即便在 Spring 官网描述却也不太多。这是因为数据绑定主要应用于 Spring 内部,对于用户而言直接使用的场景并不多。如果想要深入理解 Spring 内部的运行机制,数据绑定是必须了解的一块内容。
262 0