从原理层面掌握@InitBinder的使用【享学Spring MVC】(下)

简介: 从原理层面掌握@InitBinder的使用【享学Spring MVC】(下)

@InitBinder的value属性的作用


获取你可能还不知道,它还有个value属性呢,并且还是数组


public @interface InitBinder {
  // 用于限定次注解标注的方法作用于哪个模型key上
  String[] value() default {};
}


说人话:若指定了value值,那么只有方法参数名(或者模型名)匹配上了此注解方法才会执行(若不指定,都执行)。


@Controller
@RequestMapping
public class HelloController {
    @InitBinder({"param", "user"})
    public void initBinder(WebDataBinder binder, HttpServletRequest request) {
        System.out.println("当前key:" + binder.getObjectName());
    }
    @ResponseBody
    @GetMapping("/test/initbinder")
    public String testInitBinder(String param, String date,
                                 @ModelAttribute("user") User user, @ModelAttribute("person") Person person) {
        return param + ":" + date;
    }
}


请求:/test/initbinder?param=fsx&date=2019&user.name=demoUser,控制台打印:

当前key:param
当前key:user


从打印结果中很清楚的看出了value属性的作用~


需要说明一点:虽然此处有key是user.name,但是User对象可是不会封装到此值的(因为request.getParameter('user')没这个key嘛~)。如何解决???需要绑定前缀,原理可参考这里


其它应用场景


上面例举的场景是此注解最为常用的场景,大家务必掌握。它还有一些奇淫技巧的使用,心有余力的小伙伴不妨也可以消化消化:


若你一次提交需要提交两个"模型"数据,并且它们有重名的属性。形如下面例子:

@Controller
@RequestMapping
public class HelloController {
    @Getter
    @Setter
    @ToString
    public static class User {
        private String id;
        private String name;
    }
    @Getter
    @Setter
    @ToString
    public static class Addr {
        private String id;
        private String name;
    }
    @InitBinder("user")
    public void initBinderUser(WebDataBinder binder) {
        binder.setFieldDefaultPrefix("user.");
    }
    @InitBinder("addr")
    public void initBinderAddr(WebDataBinder binder) {
        binder.setFieldDefaultPrefix("addr.");
    }
    @ResponseBody
    @GetMapping("/test/initbinder")
    public String testInitBinder(@ModelAttribute("user") User user, @ModelAttribute("addr") Addr addr) {
        return user + ":" + addr;
    }
}


请求:/test/initbinder?user.id=1&user.name=demoUser&addr.id=10&addr.name=北京市海淀区,结果为:HelloController.User(id=1, name=demoUser):HelloController.Addr(id=10, name=北京市海淀区)


至于加了前缀为何能绑定上,这里简要说说:

1、ModelAttributeMethodProcessor#resolveArgument里依赖attribute = createAttribute(name, parameter, binderFactory, webRequest)方法完成数据的封装、转换

2、createAttribute先request.getParameter(attributeName)看请求域里是否有值(此处为null),若木有就反射创建一个空实例,回到resolveArgument方法。

3、继续利用WebDataBinder来完成对这个空对象的数据值绑定,这个时候这些FieldDefaultPrefix就起作用了。执行方法是:bindRequestParameters(binder, webRequest),实际上是((WebRequestDataBinder) binder).bind(request);。对于bind方法的原理,就不陌生了~

4、完成Model数据的封装后,再进行@Valid校验…


参考解析类:ModelAttributeMethodProcessor对参数部分的处理


总结


本文花大篇幅从原理层面总结了@InitBinder这个注解的使用,虽然此注解在当下的环境中出镜率并不是太高,但我还是期望小伙伴能理解它,特别是我本文举例说明的例子的场景一定能做到运用自如。

最后,此注解的使用的注意事项我把它总结如下,供各位使用过程中参考:


  1. @InitBinder标注的方法执行是多次的,一次请求来就执行一次(第一次惩罚)
  2. Controller实例中的所有@InitBinder只对当前所在的Controller有效
  3. @InitBinder的value属性控制的是模型Model里的key,而不是方法名(不写代表对所有的生效)
  4. @InitBinder标注的方法不能有返回值(只能是void或者returnValue=null)
  5. @InitBinder对@RequestBody这种基于消息转换器的请求参数无效
  6. 1. 因为@InitBinder它用于初始化DataBinder数据绑定、类型转换等功能,而@RequestBody它的数据解析、转换时消息转换器来完成的,所以即使你自定义了属性编辑器,对它是不生效的(它的WebDataBinder只用于数据校验,不用于数据绑定和数据转换。它的数据绑定转换若是json,一般都是交给了jackson来完成的)
  7. 只有AbstractNamedValueMethodArgumentResolver才会调用binder.convertIfNecessary进行数据转换,从而属性编辑器才会生效
相关文章
|
7小时前
|
监控 安全 Java
Spring cloud原理详解
Spring cloud原理详解
17 0
|
7小时前
|
设计模式 前端开发 Java
初识Spring MVC
初识Spring MVC
11 0
|
7小时前
|
前端开发 Java 应用服务中间件
Spring MVC框架概述
Spring MVC 是一个基于Java的轻量级Web框架,采用MVC设计模型实现请求驱动的松耦合应用开发。框架包括DispatcherServlet、HandlerMapping、Handler、HandlerAdapter、ViewResolver核心组件。DispatcherServlet协调这些组件处理HTTP请求和响应,Controller处理业务逻辑,Model封装数据,View负责渲染。通过注解@Controller、@RequestMapping等简化开发,支持RESTful请求。Spring MVC具有清晰的角色分配、Spring框架集成、多种视图技术支持以及异常处理等优点。
15 1
|
7小时前
|
监控 前端开发 Java
SpringBoot与SpringMVC有哪些区别?
SpringBoot和SpringMVC是Java开发中常用的两个框架,它们都是由Spring框架所提供的,但在功能和使用方式上有着一些区别。
23 2
|
7小时前
|
Java 开发者 微服务
Spring Cloud原理详解
【5月更文挑战第4天】Spring Cloud是Spring生态系统中的微服务框架,包含配置管理、服务发现、断路器、API网关等工具,简化分布式系统开发。核心组件如Eureka(服务发现)、Config Server(配置中心)、Ribbon(负载均衡)、Hystrix(断路器)、Zuul(API网关)等。本文讨论了Spring Cloud的基本概念、核心组件、常见问题及解决策略,并提供代码示例,帮助开发者更好地理解和实践微服务架构。此外,还涵盖了服务通信方式、安全性、性能优化、自动化部署、服务网格和无服务器架构的融合等话题,揭示了微服务架构的未来趋势。
35 6
|
7小时前
|
负载均衡 Java 开发者
Spring Cloud:一文读懂其原理与架构
Spring Cloud 是一套微服务解决方案,它整合了Netflix公司的多个开源框架,简化了分布式系统开发。Spring Cloud 提供了服务注册与发现、配置中心、消息总线、负载均衡、熔断机制等工具,让开发者可以快速地构建一些常见的微服务架构。
|
7小时前
|
安全 Java API
Spring工厂API与原理
Spring工厂API与原理
35 10
|
7小时前
|
数据采集 前端开发 Java
数据塑造:Spring MVC中@ModelAttribute的高级数据预处理技巧
数据塑造:Spring MVC中@ModelAttribute的高级数据预处理技巧
23 3
|
Java Spring
Spring原理学习系列之五:IOC原理之Bean加载
其实很多同学都想通过阅读框架的源码以汲取框架设计思想以及编程营养,Spring框架其实就是个很好的框架源码学习对象。我们都知道Bean是Spring框架的最小操作单元,Spring框架通过对于Bean的统一管理实现其IOC以及AOP等核心的框架功能,那么Spring框架是如何把Bean加载到环境中来进行管理的呢?本文将围绕这个话题进行详细的阐述,并配合Spring框架的源码解析。
Spring原理学习系列之五:IOC原理之Bean加载
|
7小时前
|
Java 应用服务中间件 Maven
SpringBoot 项目瘦身指南
SpringBoot 项目瘦身指南
56 0