当前位置: 首页 > article >正文

使用JSR303对数据进行校验【JAVA】

前言

1、SpringBoot项目中Controller的validator做参数校验不生效的问题

解决:

springboot 2.3之前的集成在spring-boot-starter-web里了,所以不需要额外引入包

springboot 2.3之后需要引入 spring-boot-starter-validation


简单校验

流程:

        ①在需要校验的属性上添加校验注解

        ②在controller方法内,在对应的实体类前面添加 @Valid 注解,开启属性校验功能

代码:

public class UserEntity {
    
    @Min(value = 0,message = "年龄不能小于0!")  //@Min该注解表示age的值要大于或等于0
    private Integer age;

    @NotBlank(message = "用户名不能为空!")  //@NotBlank注解表示该属性不能为空
    private String username;

    @NotBlank(message = "密码不能为空!")
    @Length(min = 6,message = "密码不能低于6位!")   //@Length该注解表示长度要大于6
    private String password;

    private String nickname;
}
/**
 * 简单的校验规则
 */
@RestController
public class SimpleValidRule {

    /**
     * @param user   要校验的实体类
     * @param result 如果不满足校验规则,可以通过该类接受异常信息
     * @return
     * @Valid 开启数据校验功能
     */
    @RequestMapping("/simpleSave")
    private Map saveUser(@Valid @RequestBody UserEntity user, BindingResult result) {
        Map<String, String> map = new HashMap<>();
        if (result.hasErrors()) {
            result.getFieldErrors().forEach(item -> {
                //获取失败信息
                map.put(item.getField(), item.getDefaultMessage());
            });
        } else {
            map.put("data", "数据校验成功");
        }
        return map;
    }

}

分组校验

ps:上面通过简单案例演示了数据校验,但是可以看到属性校验返回的异常信息是跟业务代码写在一起,这样看起来非常不优雅,同时也不利于后面维护,所以对于异常信息,我们应该使用一个全局异常处理。

流程:

        ①还是在需要校验属性的上面添加校验规则,但是这里还添加了一个分组属性。想象一下,如果执行save方法时,我们必须要求用户输入username属性,执行update方法时,必须用户传入age属性,那如果通过上面校验,发现并不能满足这种要求,所以这就是分组的意义。

        ②在controller方法内,通过注解@Validated开启属性校验,通过指定要校验的规则,如果不指定,则跟上面简单校验一样。

代码:

public class UserEntity2 {

    //这里可以看到,该属性校验多了一个groups分组属性
    @Min(value = 0, message = "年龄不能小于0!", groups = UpdateGroup.class)   
    private Integer age;
       
    //可以看到,username跟前面的age属性定义了不同组
    @NotBlank(message = "用户名不能为空!", groups = SaveGroup.class)    
    private String username;

    @NotBlank(message = "密码不能为空!")
    @Length(min = 6, message = "密码不能低于6位!")
    private String password;

    @NotBlank(message = "用户昵称不能为空", groups = {SaveGroup.class})
    private String nickname;
}
/**
 * 指定分组校验
 */
@RestController
public class GroupValidRule {
    
    //这里通过@Validated注解定义了只校验那个分组下的属性,其它分组,包括没写的,不会进行校验
    @PostMapping("/groupSave")
    private String saveUser(@Validated(value = SaveGroup.class) @RequestBody UserEntity user) {
        /* 执行一系列流程... */
        return "数据校验成功";
    }

    @PostMapping("/groupUpdate")
    private String updateUser(@Validated(value = UpdateGroup.class) @RequestBody UserEntity user) {
        /* 执行一系列流程... */
        return "数据校验成功";
    }
}
/**
 * 全局异常处理类
 */
@RestControllerAdvice
public class GlobalException {

    @ExceptionHandler
    public String handlerException(Exception e){
        return "数据校验失败!";
    }
}

上面如果执行saveUser方法,因为使用注解@Validated(value = SaveGroup.class)定义了只校验SaveGroup分组下的属性,所以只有username属性会被进行校验!

自定义校验

可能以上校验规则并不一定符合我们,所以这时候可以通过自定义校验规则

流程:

        ①new一个自定义注解类

        ②创建具体的校验规则类,需要实现ConstraintValidator接口,重写两个方法:initialize()和isValid()

        ③在需要自定义校验属性上添加该注解,并指定校验规则

代码:

@Data
public class UserEntity3 {

    //这里自定义校验规则,要求必须输入name的值为张三
    @CustomValidAnnotation(name = "张三") 
    private String name;
}
/**
 * 自定义校验
 */
@RestController
public class CustomValidRule {

    @RequestMapping("/customSave")
    private String saveUser(@Validated @RequestBody UserEntity user) {
        return "属性校验成功";
    }
}
/**
 * 自定义校验注解
 */
@Constraint(
        validatedBy = {CustomValid.class} //自定义具体的校验器,可以指定多个
)
@Target({ElementType.METHOD, ElementType.FIELD, ElementType.ANNOTATION_TYPE, ElementType.CONSTRUCTOR, ElementType.PARAMETER, ElementType.TYPE_USE})
@Retention(RetentionPolicy.RUNTIME)
public @interface CustomValidAnnotation {
    String message() default "";

    Class<?>[] groups() default {};

    Class<? extends Payload>[] payload() default {};

    String name();  //添加一个name属性作为校验规则

}
/**
 * 自定义校验器,需要实现ConstraintValidator并传入两个泛型,第一个是自定义校验的注解,第二个校验属性的类型
 */
public class CustomValid implements ConstraintValidator<CustomValidAnnotation, String> {
    private String name;

    /**
     * 这个方法可以获取我们自定义校验属性的值,也就是在实体类定义属性校验规则
     * @param constraintAnnotation  自定义注解
     */
    @Override
    public void initialize(CustomValidAnnotation constraintAnnotation) {
        String name = constraintAnnotation.name();  //获取自定义注解上的value
        this.name = name;
    }

    /**
     * 这个方法是获取用户传入的数据,我们可以通过上面拿到的校验规则与用户输入进行校验匹配,判断用户输入是否满足我们要求的参数格式
     * @param s 用户输入的值
     * @param constraintValidatorContext
     * @return 返回false表示输入的数据不合法,true则相反
     */
    @Override
    public boolean isValid(String s, ConstraintValidatorContext constraintValidatorContext) {
        if (name.equals(name)){
            return true;
        }
        return false;
    }
}

http://www.kler.cn/a/6533.html

相关文章:

  • Nginx - 负载均衡及其配置(Balance)
  • 使用C语言编写UDP循环接收并打印消息的程序
  • STM32 高级 物联网通信之CAN通讯
  • 多个Echart遍历生成 / 词图云
  • RunCam WiFiLink连接手机图传测试
  • C++ 面向对象编程:友元、
  • Linux reset子系统和驱动实例
  • GEE:栅格转矢量
  • Jackson之ObjectMapper常用用法
  • 【异常解决】java: 无法访问org.springframework.boot.SpringApplication的解决方案
  • 中级软考有没有必要考?
  • php+mysql仓储进销存仓库管理系统
  • 【C++】多态(二)
  • 从零开始学习InfluxDB:安装和使用入门教程
  • C++ using:软件设计中的面向对象编程技巧
  • 分库分表笔记
  • MVVM理解、object.defineProperty、数据代理
  • Android动态换肤框架实现小结
  • 射频接收机概述
  • PyTorch模型保存方法对比及其实现原理详解
  • 大数据领域的发展及其对现实世界的价值
  • BloombergGPT(LLM大模型用于金融科技)
  • Qt源码阅读(三) 对象树管理
  • java程序中常见的漏洞类型
  • 五 MySQL 存储过程
  • [jetson]pillow 报ImportError: The _imagingft C module is not installed