• SpringBoot - @InitBinder注解详解


    写在前面

    @InitBinder注解可以作用在被@Controller注解的类的方法上,表示为当前控制器注册一个属性编辑器,用于对WebDataBinder进行初始化,且只对当前的Controller有效。@InitBinder标注的方法会被多次执行的,也就是说来一次请求就会执行一次@InitBinder注解方法的内容。
    A. @InitBinder注解是在其所标注的方法执行之前被解析和执行;
    B. @InitBinder的value属性,控制的是模型Model里的KEY,而不是方法名;
    C. @InitBinder标注的方法也不能有返回值;
    D. @InitBinder对@RequestBody这种基于消息转换器的请求参数是失效的。

    应用场景

    用于将前端传递过来的数据进行类型转换或者叫属性编辑,如:将前端传递过来的字符串格式的日期数据,转化为DATE类型。

    作用范围

    @InitBinder是属于Controller级别的属性编辑器,并非全局级别(针对所有Controller)的属性编辑器,也就是一个@InitBinder只对当前所在的Controller有效,对其他Controller无效的,如果项目中有多个Controller中都要进属性编辑怎么办呢?一般我们将@InitBinder标注的方法定义在基础的控制器上,所有具体的Controller继承这个基础的Controller即可。

    示例代码

    /**
     * WEB层通用数据处理
     * @author ROCKY
     */
    public class BaseController {
    
        /**
         * 将前端传递过来的日期格式的字符串转化为Date类型,否则无法将数据绑定到实体中。
         * 自定义类型转换器有两种方式:A. implements Converter 或者 B. extends PropertyEditorSupport;
         * 在WebDataBinder对象中,可以设置前缀,可以设置允许、禁止的字段、必填字段以及验证器,可以自定义类型转换器。
         */
        @InitBinder
        public void initBinder(WebDataBinder binder) {
            // Date 类型转换
            binder.registerCustomEditor(Date.class, new PropertyEditorSupport() {
                @Override
                public void setAsText(String text) {
                    setValue(DateUtils.parseDate(text));
                }
            });
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22

    常见错误

    如果后端没有将日期格式的字符串转化为DATE类型,则在后端服务接收DATE类型的数据时,报错如下:

    Failed to convert value of type 'java.lang.String' to required type 'java.util.Date'; 
    nested exception is org.springframework.core.convert.ConversionFailedException: 
    Failed to convert from type [java.lang.String] to type [java.util.Date] for value '2022-08-09 11:15:58'; 
    nested exception is java.lang.IllegalArgumentException
    
    • 1
    • 2
    • 3
    • 4

    为什么@InitBinder对@RequestBody的请求参数是失效的?

    因为@InitBinder用于初始化DataBinder的数据绑定、类型转换等场景;
    @RequestBody的数据解析、格式转换是通过消息转换器来完成的,所以即使自定义了属性编辑器,对@RequestBody的参数是不生效的,@RequestBody的数据绑定转换,如果是JSON格式的数据一般都是交给了JACKSON来完成的。这就是为什么在整个项目中既有属性编辑器,也有JACKSON的消息转换器,同时对应的DO对象中关于日期的属性,需要使用@JsonFormat()进行标注,如下:

    /**
     * 程序注解配置
     *
     * @author ROCKY
     */
    @Configuration
    // 表示通过aop框架暴露该代理对象,AopContext能够访问
    @EnableAspectJAutoProxy(exposeProxy = true)
    // 指定要扫描的Mapper类的包的路径
    @MapperScan("cn.hadoopx.**.mapper")
    public class ApplicationConfig {
        // 1. 时区配置
        @Bean
        public Jackson2ObjectMapperBuilderCustomizer jacksonObjectMapperCustomization() {
            return jacksonObjectMapperBuilder -> jacksonObjectMapperBuilder.timeZone(TimeZone.getDefault());
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    public class BaseEntity implements Serializable {
    
        /**
         * 创建者
         */
        private String createBy;
    
        /**
         * 创建时间
         */
        @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
        private Date createTime;
    
        /**
         * 更新者
         */
        private String updateBy;
    
        /**
         * 更新时间
         */
        @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
        private Date updateTime;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
  • 相关阅读:
    【前端】特效开发
    【C++ 面试 - 新特性】每日 3 题(十)
    Pytorch模型训练实用教程学习笔记:二、模型的构建
    c++的string一键介绍
    详解MAC帧、ARP、DNS、ICMP协议
    python带你采集爆火动漫弹幕,并且做词云图可视化分析
    Haskell高阶函数(归并排序mergesort,map,filter)
    Kali Linux渗透测试技术介绍【文末送书】
    PHP即刻送达同城派送小程序系统
    【BOOST C++ 20 设计模式】(1)库Boost.Flyweight
  • 原文地址:https://blog.csdn.net/goodjava2007/article/details/126374723