• 【校验处理】三、Spring Validation 校验处理


    在真实的开发中,我们经常会遇到需要对数据进行校验的业务,那么本篇文章对此进行总结。暂时总结三种方法,大家可以根据需要选择使用。

    一、Java Bean Validation 验证  【校验处理】一、Java Bean Validation验证  

    二、SpringBoot Validate 统一处理  【校验处理】二、SpringBoot Validate 统一处理

    三、Spring Validation 校验处理   【校验处理】三、Spring Validation 校验处理

    本篇文章采用第三种Spring Validation的验证方式。话不多说,直接上代码。

    1. 背景

    Java API规范(JSR303)定义了Bean校验的标准validation-api,但没有提供实现。hibernate validation是对这个规范的实现,并增加了校验注解如@Email、@Length等。Spring Validation是对hibernate validation的二次封装,用于支持spring mvc参数自动校验。

    POST、PUT请求一般会使用requestBody传递参数,这种情况下,后端使用DTO对象进行接收。只要给DTO对象加上@Validated注解就能实现自动参数校验。如果校验失败,会抛出MethodArgumentNotValidException异常,Spring默认会将其转为400(Bad Request)请求。DTO表示数据传输对象(Data Transfer Object),用于服务器和客户端之间交互传输使用的。在spring-web项目中可以表示用于接收请求参数的Bean对象。

    2. 依赖

    <!--引入依赖-->
    <!--如果spring-boot版本小于2.3.x,spring-boot-starter-web会自动传入hibernate-validator依赖。-->
    <!--如果spring-boot版本大于2.3.x,则需要手动引入依赖 -->
    <dependency>
        <groupId>org.hibernate</groupId>
        <artifactId>hibernate-validator</artifactId>
        <version>6.0.1.Final</version>
    </dependency>

    3. 校验处理

    3.1 简单处理

    3.1.1 代码实现

    @Data
    public class Test {
        @Length(min = 1,max = 5,message = "姓名长度应该在1-5之间")
        private String name;
        @Range(min = 1,max = 100,message = "年龄应该在1-100之间")
        private Integer age;
    }
    
    @ApiOperation("测试")
    @PostMapping("/test")
    public R test(@RequestBody @Valid Test test){
        return R.ok();
    }
    
    @ApiOperation("测试")
    @PostMapping("/test")
    public R test(@RequestBody @Validated Test test){
        return R.ok();
    }
    
    
    {
        "name":"张三张三张三",
        "age":"0"
    }

    3.1.2 效果

    3.1.3 注意

    此处的校验注解写成Validated或者Valid都可以,不过他俩之间有一些区别:

    1. 分组:

      @Validated:提供了一个分组功能,可以在入参验证时,根据不同的分组采用不同的验证机制,这个网上也有资料,不详述。

      @Valid:作为标准JSR-303规范,还没有吸收分组的功能。

    2. 注解位置:

      @Validated:可以用在类型、方法和方法参数上。但是不能用在成员属性(字段)上

      @Valid:可以用在方法、构造函数、方法参数和成员属性(字段)上

    3. 嵌套验证:

      @Valid //嵌套验证必须使用@Valid

      private List< Student> student;

    4. @Valid一般用于方法入口,@Validated用于校验实体类的接口参数,用于controller上

    3.2 嵌套校验

    嵌套校验一定要在要校验的对象类型的属性/list上使用@Valid注解:

    3.2.1 代码实现

    @Data
    public class Test {
        @Length(min = 1,max = 5,message = "姓名长度应该在1-5之间")
        private String name;
        @Range(min = 1,max = 100,message = "年龄应该在1-100之间")
        private Integer age;
        @Valid
        private Test2 test;
        @Valid
        private List<Test2> test2;
    }
    
    @Data
    public class Test2 {
        @Max(value = 1)
        private Integer sex;
        @Length(min = 0,max = 2)
        private String jobname;
    }
    
    @ApiOperation("测试")
    @PostMapping("/test")
    public R test(@RequestBody @Validated Test test){
        return R.ok();
    }
    
    {
        "name":"张三张三张三",
        "age":"0",
        "test":{
            "sex":"11",
            "jobname":"李四李四李四"
        },
        "test2":[{
            "sex":"222",
            "jobname":"王五王五王五王五"
        },{
            "sex":"3333",
            "jobname":"赵六赵六赵六赵六"
        }]
    }

    3.2.2 结果

    3.3 分组校验

    在实际项目中,可能多个方法需要使用同一个DTO类来接收参数,而不同方法的校验规则很可能是不一样的。这个时候,简单地在DTO类的字段上加约束注解无法解决这个问题。因此,spring-validation支持了分组校验的功能,专门用来解决这类问题。

    3.3.1 代码实现

    //这里定义四种规则
    public class GroupValidator {
        public interface Arules{}
        public interface Brules{}
        public interface Crules{}
        public interface Drules{}
    }
    
    //实体类属性注解上加上分组标志
    @Data
    public class Test {
        @Length(min = 1,max = 5,groups = {GroupValidator.Arules.class, GroupValidator.Brules.class})
        private String name;
        @Range(min = 1,max = 100,groups = {GroupValidator.Crules.class, GroupValidator.Drules.class})
        private Integer age;
    }
    
    //参数列表里指定要校验的分组
    @PostMapping("/test")
    public R test(@RequestBody @Validated(GroupValidator.Arules.class) Test test){
        return R.ok();
    }
    
    //json
    {
        "name":"张三张三张三",
        "age":"0"
    }

    3.3.2 结果

    3.4 自定义校验

    3.4.1 代码实现

    //首先自定义一个注解
    @Target({METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER})
    @Retention(RUNTIME)
    @Documented
    @Constraint(validatedBy = {TestValidator.class})
    public @interface TestAnnotation {
        // 默认错误消息
        String message() default "此值只能为1";
    
        // 分组
        Class<?>[] groups() default {};
    
        // 负载
        Class<? extends Payload>[] payload() default {};
    }
    
    //对这个注解写验证的逻辑
    public class TestValidator implements ConstraintValidator<TestAnnotation, String> {
        @Override
        public boolean isValid(String s, ConstraintValidatorContext constraintValidatorContext) {
            if(!"1".equals(s)){
                return false;
            }else{
                return true;
            }
        }
    }
    
    //实体类中使用这个注解
    @Data
    public class Test {
        //@Length(min = 1,max = 5)
        @TestAnnotation
        private String name;
        @Range(min = 1,max = 100)
        private Integer age;
    }
    
    //验证
    @PostMapping("/test")
    public R test(@RequestBody @Validated Test test){
        return R.ok();
    }
    
    //传入json
    {
        "name":"张三张三张三",
        "age":"0"
    }

    3.4.2 结果

    持续更新!!!

  • 相关阅读:
    Python开发环境Spyder介绍
    Python干货整理之数据结构篇
    通过Python爬虫按关键词抓取相关的新闻
    疫情后来场说走就走的旅行,Python制作一份可视化的旅行攻略
    详细介绍去一年在 PyPI 上下载次数最多的 Python 包
    Python错误与异常
    python爬虫爬取2020年中国大学排名
    微信史上最短的一行功能代码:拍一拍
    Python爬取某宝商品数据案例:100页的价格、购买人数等数据
    我的SAS菜鸟之路7
  • 原文地址:https://www.cnblogs.com/flyinghome/p/14597461.html
Copyright © 2020-2023  润新知