SpringBoot参数校验的使用(validator)

x33g5p2x  于2021-11-19 转载在 Spring  
字(5.3k)|赞(0)|评价(0)|浏览(381)

项目源码地址:https://gitee.com/huanglei1111/springboot-demo/tree/master/springboot-validator

SpringBoot参数校验的使用(validator)

一、validator简介

Bean Validation是Java定义的一套基于注解的数据校验规范,目前已经从JSR 303的1.0版本升级到JSR 349的1.1版本,再到JSR 380的2.0版本(2.0完成于2017.08),已经经历了三个版本 。需要注意的是,JSR只是一项标准,它规定了一些校验注解的规范,但没有实现,比如@Null、@NotNull、@Pattern等,它们位于 javax.validation.constraints这个包下。而hibernate validator是对这个规范的实现,并增加了一些其他校验注解,如 @NotBlank、@NotEmpty、@Length等,它们位于org.hibernate.validator.constraints这个包下

如果我们的项目使用了Spring Boot,hibernate validator框架已经集成在 spring-boot-starter-web中,所以无需再添加其他依赖。如果不是Spring Boot项目,需要添加如下依赖。

<dependency>
  	<groupId>org.hibernate.validator</groupId>
  	<artifactId>hibernate-validator</artifactId>
  	<version>6.0.8.Final</version>
</dependency>

二、注解介绍

内置注解

注解说明
@Null被注释的元素必须为null
@NotNull被注释的元素不能为null
@AssertTrue被注释的元素必须为true
@AssertFalse被注释的元素必须为false
@Min(value)被注释的元素必须是一个数字,其值必须大于等于指定的最小值
@Max(value)被注释的元素必须是一个数字,其值必须小于等于指定的最大值
@DecimalMin(value)被注释的元素必须是一个数字,其值必须大于等于指定的最小值
@DecimalMax(value)被注释的元素必须是一个数字,其值必须小于等于指定的最大值
@Size(max,min)被注释的元素的大小必须在指定的范围内
@Digits(integer, fraction)被注释的元素必须是一个数字,其值必须必须在可接受的范围内
@Past被注释的元素必须是一个过去的日期
@Future被注释的元素必须是一个将来的日期
@Pattern(value)被注释的元素必须符合指定的正则表达式

扩展注解

注解说明
@NotBlank被注释的元素不能为null,且长度必须大于0,只能用于注解字符串
@Email被注释的元素必须是电子邮箱地址
@Length(min=,max=)被注释的字符串的大小必须在指定的范围内
@NotEmpty被注释的元素值不为null且不为空,支持字符串、集合、Map和数组类型
@Range被注释的元素必须在规定的范围内

三、validator的使用

创建校验工具类

package com.hl.springbootvalidator.util;

import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.hl.springbootcommon.exception.ParamException;
import org.apache.commons.collections.MapUtils;

import javax.validation.ConstraintViolation;
import javax.validation.Validation;
import javax.validation.Validator;
import javax.validation.ValidatorFactory;
import java.util.*;

public class BeanValidatorUtil {
    private static final ValidatorFactory VALIDATOR_FACTORY = Validation.buildDefaultValidatorFactory();
    //返回map
    public static <T> Map<String,String> validate(T t, Class... groups){
        Validator validator=VALIDATOR_FACTORY.getValidator();
        Set validateResult=validator.validate(t,groups);
        //如果为空
        if (validateResult.isEmpty()){
            return Collections.emptyMap();
        }else{
            //不为空时表示有错误
            LinkedHashMap errors= Maps.newLinkedHashMap();
            //遍历
            Iterator iterator=validateResult.iterator();
            while (iterator.hasNext()){
                ConstraintViolation violation=(ConstraintViolation) iterator.next();
                errors.put(violation.getPropertyPath().toString(),violation.getMessage());
            }
            return errors;
        }
    }
    //返回list
    public static Map<String,String> validateList(Collection<?> collection){
        //基础校验collection是否为空
        com.google.common.base.Preconditions.checkNotNull(collection);
        //遍历collection
        Iterator iterator=collection.iterator();
        Map errors;
        do {
            //如果循环下一个为空直接返回空
            if (!iterator.hasNext()){
                return Collections.emptyMap();
            }
            Object object=iterator.next();
            errors=validate(object,new Class[0]);
        }while (errors.isEmpty());
        return errors;
    }

     // 校验某一对象是否合法
    public static Map<String,String> validateObject(Object first,Object... objects){
        if (objects !=null && objects.length > 0 ){
            return validateList(Lists.asList(first,objects));
        } else {
            return validate(first , new Class[0]);
        }
    }
    //校验参数方法
    public static void check(Object param) throws ParamException {
        Map<String,String> map= BeanValidatorUtil.validateObject(param);
        //如果错误集合map不为空则抛出异常
        if (MapUtils.isNotEmpty(map)){
            throw  new ParamException(map.toString());
        }
    }
}

对一个对象进行校验

@RestController
@RequestMapping("/user")
public class UserController {

    @PostMapping("/insert")
    public HttpResponseTemp<?> getUser2(@RequestBody UserParam userParam){
        Map<String, String> map = BeanValidatorUtil.validateObject(userParam);
        if (MapUtils.isNotEmpty(map)){
            throw ApiException.wrapMessage(ResultStat.SERVER_INTERNAL_ERROR,map.toString());
        }
        return ResultStat.OK.wrap(map,"校验完成");
    }
@Data
public class UserParam {

    private Integer id;

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

    @NotBlank(message = "电话不可以为空")
    @Pattern(regexp = "^[1](([3][0-9])|([4][5-9])|([5][0-3,5-9])|([6][5,6])|([7][0-8])|([8][0-9])|([9][1,8,9]))[0-9]{8}$",message = "只能是数字")
    @Length(min = 1, max = 13, message = "电话长度需要在13个字以内")
    private String telephone;

    @NotBlank(message = "邮箱不允许为空")
    @Pattern(regexp = "^([a-zA-Z]|[0-9])(\\w|\\-)+@[a-zA-Z0-9]+\\.([a-zA-Z]{2,4})$",message = "邮箱格式不正确")
    @Length(min = 5, max = 50, message = "邮箱长度需要在50个字符以内")
    private String mail;

    @NotEmpty
    private List<Integer> lists;
  }

当邮箱格式和电话号码格式错误的时候

对象内嵌进行校验

@Data
public class UserParam {

    private Integer id;

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

    @NotBlank(message = "电话不可以为空")
    @Length(min = 1, max = 13, message = "电话长度需要在13个字以内")
    private String telephone;

    @NotBlank(message = "邮箱不允许为空")
    @Length(min = 5, max = 50, message = "邮箱长度需要在50个字符以内")
    private String mail;

    @Valid
    private Phone phone;

  }

@Data
public class Phone {
	@NotBlank
  	private String operatorType;        
  	@NotBlank    
  	private String phoneNum;
}
@RestController
@RequestMapping("/user")
public class UserController {
    @PostMapping("/insert2")
    public HttpResponseTemp<?> getUser3(@RequestBody UserParam userParam){
        Map<String, String> map = BeanValidatorUtil.validateObject(userParam);
        if (MapUtils.isNotEmpty(map)){
            throw ApiException.wrapMessage(ResultStat.SERVER_INTERNAL_ERROR,map.toString());
        }
        return ResultStat.OK.wrap(map,"校验完成");
    }
}

相关文章