Java注解校验参数及JSR-303,JSR-380区别


前言

最近在写项目时要校验传过来的参数是否为空,手动判空很繁琐,所以使用注解判空,但默认的Exception异常拦截报错不准确,想要定义符合类型的报错返回值,所以查阅资料写了这篇博客
做检验的逻辑是在源码节的第10步

参考链接:

springboot2.3之后,hibernate-validator依赖缺失【踩坑】
Java注解校验参数 javax.validation 和 hibernate-validator(注解说明,全局异常处理)
Jakarta Bean Validation,Constrain once, validate everywhere!(javax和jakarta区别)

1. 不吹不擂,第一篇就能提升你对Bean Validation数据校验的认知
Bean Validation专栏

spring boot中使用Bean Validation做优雅的参数校验(注解说明,全局异常处理通用模板)
参数校验Jakarta Bean Validation学习

@Valid与@Validated区别
@Validated和@Valid的区别

Spring Validation最佳实践及其实现原理,参数校验没那么简单!(全局异常处理通用模板)
还在为参数校验发愁?spring-validation最佳实践指南(重要,全局异常处理通用模板)

理解java注解二
注解专栏

@NotBlank、@NotNull验空注解无效问题

10.2添加

数据校验JSR303快速入门(简单使用、分组效验、自定义注解效验)
springboot 参数异常拦截(3种)
SpringBoot学习笔记35——实现List校验@Validated
SpringBoot 之配置全局异常处理器捕获异常
使用SpringBoot进行优雅的数据验证


一、hibernate-validator

    不同版本的hibernate-validator的依赖也不尽相同

7.0.0之后
  内容**关键字**,内容。

7.0.0之前(不过其实6版本的最后一些版本已经是jakarta.validation-api依赖了)
 内容**关键字**,关键字**onApplicationEvent**,内容。

二、全局异常拦截校验参数注解

1.@RequestBody

POST、PUT请求一般会使用requestBody传递参数,这种情况下,后端使用DTO对象进行接收。只要给DTO对象加上@Validated注解就能实现自动参数校验。比如,有一个保存User的接口,要求userName长度是2-10,account和password字段长度是6-20。如果校验失败,会抛出MethodArgumentNotValidException异常,Spring默认会将其转为400(Bad Request)请求。

2.@RequestParam/@PathVariable

GET请求一般会使用requestParam/PathVariable传参。如果参数比较多(比如超过6个),还是推荐使用DTO对象接收。否则,推荐将一个个参数平铺到方法入参中。在这种情况下,必须在Controller类上标注@Validated注解,并在入参上声明约束注解(如@Min等)。如果校验失败,会抛出ConstraintViolationException异常。代码示例如下:

三、实践代码

@RestController
@Validated
@Slf4j
//@Valid
public class TestController {

    @RequestMapping("/test")
    public TestRepository.User test(@RequestParam Integer a) throws Exception {
        return  service.test(a);
    }

    /**
     * 对照组1 requestParam参数
     * 当前controller没有@Validated全都不生效
     * 加@Valid注解无用
     * 测试@NotNull不传任何参数即可,postman中的params不加这个参数,加上就是空串而不是null,这时候要使用@NotBlank
     * @param userId
     * @return
     */

    //异常类型:ConstraintViolationException

    //没有@Validated注解均不生效(必须是@Validated注解,@Valid注解无用)

    //不生效
    @GetMapping(value = "/user0")
    String getUserInfo0(String userId) {
        return userId;
    }
    //生效
    @GetMapping(value = "/user1")
    String getUserInfo1( @Valid @NotNull  String userId) {
        return userId;
    }
    //生效
    @GetMapping(value = "/user2")
    String getUserInfo2( @Validated @NotNull  String userId) {
        return userId;
    }
    //生效
    @GetMapping(value = "/user3")
    String getUserInfo3( @NotNull  String userId) {
        return userId;
    }


    /**
     * 对照组2 requestBody参数
     * 和当前controller是否有@Validated注解无关,去掉也不影响
     * @param user
     * @return
     */
    //异常类型: MethodArgumentNotValidException

    //不生效
    @PostMapping(value = "/user00")
    String saveUser0( @RequestBody  User user) {
        return user.getName();
    }

    //生效
    @PostMapping(value = "/user11")
    String saveUser1( @RequestBody @Validated User user) {
        return user.getName();
    }

    //生效
    @PostMapping(value = "/user22")
    String saveUser2( @RequestBody @Valid User user) {
        return user.getName();
    }
@Data
public class User {
  
    @NotBlank(message = "用户名不能为空")
    private String name;
}

postman调用截图:
param:在这里插入图片描述

body:
在这里插入图片描述

四、异常情况

  1. 使用@Min,@Max等注解时一般和@NotBlank搭配,否则null(即不传参)可以通过@Min@Max等的校验
    在这里插入图片描述
    注意:”null elements are considered valid“

五、源码

1.DispatchServlet的doDispatch方法:
在这里插入图片描述
2.AbstractHandlerMethodAdapter的handle方法
在这里插入图片描述
3.RequestMappingHandlerAdapter的handleInternal方法
在这里插入图片描述
进入这个else

在这里插入图片描述
4.RequestMappingHandlerAdapter的invokeHandlerMethod方法
在这里插入图片描述
invokeAndHandle
在这里插入图片描述

5.ServletInvocableHandlerMethod的invokeAndHandle方法
在这里插入图片描述
6.InvocableHandlerMethod的invokeForRequest方法
在这里插入图片描述
7.InvocableHandlerMethod的getMethodArgumentValues方法
在这里插入图片描述

8.HandlerMethodArgumentResolverComposite的resolveArgument方法
在这里插入图片描述

9 .分两类(param和body)
9.1 body
在这里插入图片描述
9.2 param

在这里插入图片描述
10.AbstractMessageConverterMethodArgumentResolver 的validateIfApplicable方法
在这里插入图片描述

  1. 回到InvocableHandlerMethod的doInvoke方法
    在这里插入图片描述

  2. doInvoke方法
    在这里插入图片描述

  3. 使用反射机制

总结

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值