Springboot使用validator进行参数校验

Posted 小妖云汐

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Springboot使用validator进行参数校验相关的知识,希望对你有一定的参考价值。

Springboot使用validator进行参数校验

添加数据效验

<dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-web</artifactId>
      </dependency>
<dependency>
      <groupId>org.hibernate</groupId>
      <artifactId>hibernate-validator</artifactId>
      <version>6.0.15.Final</version>
 </dependency>

单字段效验

  • 添加效验注解
@Data
public class Users 
    private int id;

    @NotBlank(message="用户名不能为空")
    @Length(min = 1, max = 20, message = "用户名长度需要在20个字以内")
    private String name;

    @Pattern(regexp = "^[1][3,4,5,6,7,8,9][0-9]9$", message = "手机号格式有误")
    private String phone;

    @Pattern(regexp="^[0-9]4-[0-9]2-[0-9]2$",message="出生日期格式不正确")
    private String birthday;

    @Email(message="请输入正确的邮箱")
    private String email;

    @Size(min = 1, max = 5)
    private List<String> strings;

  • 其他常用的注解
注解说明
@Range(min=最小值, max=最大值)验证注解的元素值在最小值和最大值之间
@Min(value=值)验证注解的元素值大于等于@Min指定的value值
@Max(value=值)验证注解的元素值小于等于@Max指定的value值
@Past验证注解的元素值(日期类型)比当前时间早
@Future验证注解的元素值(日期类型)比当前时间晚
@AssertFalse可以为null,如果不为null的话必须为false
@AssertTrue可以为null,如果不为null的话必须为true
@Digits设置必须是数字且数字整数的位数和小数的位数必须在指定范围内

级联效验

带校验的成员里存在级联对象时,也进行校验

@Data
public class Users 
	@Valid
    private Collections collections;

分组效验与组序列

分组效验:将实体类的属性进行分组,标记后,在进行效验时,可以指定分组进行效验
组序列:指定分组执行效验的顺序,Default.class为默认分组

/****新增时,需要效验的字段分组****/
public interface AddGroup 
/****更新时,需要效验的字段分组****/
public interface UpdateGroup 


@Data
public class Collections 
    @NotBlank(message="修改时,id不能为空!",groups = UpdateGroup.class)
    private int id;
    @NotBlank(message="新增时,name不能为空!",groups = AddGroup.class)
    private String name;
    @NotBlank(message="新增和修改时,userid都不能为空!",groups = AddGroup.class,UpdateGroup.class)
    private int userId;
    private String content;
    private String remark;
    
	//组序列
    @GroupSequence(Default.class, AddGroup.class, UpdateGroup.class)
    public interface Group  

多字段关联效验

场景描述:根据某个字段的值不同,对其他不同的属性进行效验
    occupation字段为1时,说明该用户为学生,学校、入学时间、毕业时间为必填项
    occupation字段为2时,说明该用户为在职员工,公司和职位为必填项

  • 添加效验注解
@GroupSequenceProvider(UsersGroupSequenceProvider.class)
@Data
public class Users 
	private int occupation;//职业:学生 1 / 职工 2

    @NotBlank(message = "学校不能为空!",groups = StudentGroup.class)
    private String school;//学校
    @NotNull(message = "入学时间为必填项!",groups = StudentGroup.class)
    private Date admissionTime; //入学时间
    @NotNull(message = "毕业时间为必填项!",groups = StudentGroup.class)
    private Date graduationTime; //毕业时间

    @NotNull(message = "公司不能为空!",groups = WorkGroup.class)
    private String company; //公司
    @NotNull(message = "职位不能为空!",groups = WorkGroup.class)
    private String position;//职位

    public interface StudentGroup 
    public interface WorkGroup 

    @GroupSequence(Default.class, StudentGroup.class, WorkGroup.class)
    public interface Group 

  • 自定义分组序列提供器

实现DefaultGroupSequenceProvider接口,根据当前对象实例的occupation值,动态来决定加载哪些校验组进入默认校验组。

public class UsersGroupSequenceProvider implements DefaultGroupSequenceProvider<Users> 

    @Override
    public List<Class<?>> getValidationGroups(Users users) 
        List<Class<?>> defaultGroupSequence = new ArrayList<>();
        defaultGroupSequence.add(Users.class);

        if (users != null)  
            int occupation = users.getOccupation();
            if (occupation == 1) //为学生时,效验StudentGroup分组的字段
                defaultGroupSequence.add(Users.StudentGroup.class);
             else //为在职员工时,效验WorkGroup分组的字段
                defaultGroupSequence.add(Users.WorkGroup.class);
            
        
        return defaultGroupSequence;
    


执行数据效验

/**
 * 统一结果类
 */
@Data
public class ResultCode 
    private Integer code;
    private String msg;
    public ResultCode(Integer code, String msg) 
        this.code = code;
        this.msg = msg;
    

@Valid注解

处理validator异常

validator进行参数效验时,未通过效验会抛出MethodArgumentNotValidException异常,捕获并封装为统一结果类返回给前端。

@RestControllerAdvice
public class ResultExceptionHandler 
    @ExceptionHandler(MethodArgumentNotValidException.class)
    public ResultCode handleMethodArgumentNotValidException(MethodArgumentNotValidException e)
        Map<String,String> errors = new HashMap<>();
        e.getBindingResult().getAllErrors().forEach((error) -> 
            errors.put(((FieldError)error).getField(),error.getDefaultMessage());
        );
        return new ResultCode(500,errors.values().toString());
    

controller接口处理

使用@Valid注解进行参数效验,不指定具体分组

@RestController
@RequestMapping("/users")
public class UsersController 
	@PostMapping("checkUsers")
    public ResultCode checkUsers(@RequestBody @Valid Users user)
        //usersService.save(user);
        return ResultCode.success();
    

ValidatorUtils工具类

自定义异常及处理

自定义参数效验异常:ParamException

public class ParamException extends RuntimeException 
    private int code = 500;
    private String msg;

    public ParamException() 
        super();
    

    public ParamException(String msg) 
        super(msg);
        this.msg = msg;
    

    public ParamException(int code,String msg) 
        super(msg);
        this.msg = msg;
        this.code = code;
    

    public ParamException(String msg, Throwable cause) 
        super(msg, cause);
        this.msg = msg;
    

    public int getCode() 
        return code;
    

    public String getMsg() 
        return msg;
    



捕获自定义ParamException异常并封装为统一结果类返回给前端。

@RestControllerAdvice
public class ResultExceptionHandler 
    @ExceptionHandler(ParamException.class)
    public ResultCode handleParamException(ParamException e)
        return new ResultCode(e.getCode(),e.getMsg());
    

ValidatorUtils与接口

ValidatorUtils工具类,可以指定分组,或,只执行默认分组的效验

public class ValidatorUtils 
    private static Validator validator;

    static 
        validator = Validation.buildDefaultValidatorFactory().getValidator();
    

    /**
     * 校验对象
     * @param object        待校验对象
     * @throws ParamException  校验不通过,则报ParamException异常
     */
    public static void validateEntity(Object object)
            throws ParamException 
        Set<ConstraintViolation<Object>> constraintViolations = validator.validate(object, Default.class);
        if (!constraintViolations.isEmpty()) 
            ConstraintViolation<Object> constraint = constraintViolations.iterator().next();
            throw new ParamException(constraint.getMessage());
        
    

    /**
     * 分组校验对象
     * @param object        待校验对象
     * @param groups        待校验的组
     * @throws ParamException  校验不通过,则报ParamException异常
     */
    public static void validateEntity(Object object, Class<?>... groups)
            throws ParamException 
        Set<ConstraintViolation<Object>> constraintViolations = validator.validate(object, groups);
        if (!constraintViolations.isEmpty()) 
            ConstraintViolation<Object> constraint = constraintViolations.iterator().next();
            throw new ParamException(constraint.getMessageTemplate());
        
    

controller接口调用ValidatorUtils方法进行效验,并传参分组

@PostMapping("checkUsersByGroup")
public ResultCode checkUsersByGroup(@RequestBody Users user)
	ValidatorUtils.validateEntity(user,Users.Group.class);
	//usersService.save(user);
	return ResultCode.success();

以上是关于Springboot使用validator进行参数校验的主要内容,如果未能解决你的问题,请参考以下文章

Springboot使用validator进行参数校验

Springboot使用validator进行参数校验

SpringBoot入门二十二,使用Validation进行参数校验

开发错误记录SpringBoot2.3.0使用validation无法校验参数的问题

SpringBoot 巧用全局处理器,优雅的解决参数校验!

Spring Boot 进行Bean Validate和Method Validate