SpringBoot使用Validation校验参数


原作传送: justry_deng
原作传送:

JSR(Java Specification Requests)是Java界的重要标准;JSR又细分很多标准,其中JSR303就代表Bean Validation。更多细节可参考:https://jcp.org/en/jsr/detail?id=303

JSR303定义的校验类型

空检查
@Null			验证对象是否为null
@NotNull		验证对象是否不为null, 无法查检长度为0的字符串
@NotBlank		检查约束字符串是不是Null还有被Trim的长度是否大于0,只对字符串,且会去掉前后空格.
@NotEmpty		检查约束元素是否为NULL或者是EMPTY. 

Booelan检查
@AssertTrue		验证 Boolean 对象是否为 true  
@AssertFalse	验证 Boolean 对象是否为 false  

长度检查
@Size(min=, max=)		验证对象(Array,Collection,Map,String)长度是否在给定的范围之内  
@Length(min=, max=)		验证注解的元素值长度在min和max区间内

日期检查
@Past		验证 Date 和 Calendar 对象是否在当前时间之前  
@Future		验证 Date 和 Calendar 对象是否在当前时间之后  
@Pattern	验证 String 对象是否符合正则表达式的规则

数值检查,建议使用在Stirng,Integer类型,不建议使用在int类型上,因为表单值为“”时无法转换为int,但可以转换为Stirng为"",Integer为null
@Min			验证 Number 和 String 对象是否大等于指定的值  
@Max			验证 Number 和 String 对象是否小等于指定的值  
@DecimalMax		被标注的值必须不大于约束中指定的最大值. 这个约束的参数是一个通过BigDecimal定义的最大值的字符串表示.小数存在精度
@DecimalMin		被标注的值必须不小于约束中指定的最小值. 这个约束的参数是一个通过BigDecimal定义的最小值的字符串表示.小数存在精度
@Digits			验证 Number 和 String 的构成是否合法  
@Digits(integer=,fraction=)		验证字符串是否是符合指定格式的数字,interger指定整数精度,fraction指定小数精度。

@Range(min=, max=)	验证注解的元素值在最小值和最大值之间
@Range(min=10000,max=50000,message="range.bean.wage")
private BigDecimal wage;

@Valid 递归的对关联对象进行校验, 如果关联对象是个集合或者数组,那么对其中的元素进行递归校验,如果是一个map,则对其中的值部分进行校验.(是否进行递归验证)
@CreditCardNumber信用卡验证
@Email  验证是否是邮件地址,如果为null,不进行验证,算通过验证。
@ScriptAssert(lang= ,script=, alias=)
@URL(protocol=,host=, port=,regexp=, flags=)

环境

SpringBoot引入相关依赖:

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-validation</artifactId>
        </dependency>

约束性注解

常用的注解

@AssertFalse
可以为null,如果不为null的话必须为false
@AssertTrue
可以为null,如果不为null的话必须为true
@DecimalMax
设置不能超过最大值
@DecimalMin
设置不能超过最小值
@Digits
设置必须是数字且数字整数的位数和小数的位数必须在指定范围内
@Future
日期必须在当前日期的未来
@Past
日期必须在当前日期的过去
@Max
最大不得超过此最大值
@Min
最大不得小于此最小值
@NotNull
不能为null,可以是空
@Null
必须为null
@Pattern
必须满足指定的正则表达式
@Size
集合、数组、map等的size()值必须在指定范围内
@Email
必须是email格式
@Length
长度必须在指定范围内
@NotBlank
字符串不能为null,字符串trim()后也不能等于“”
@NotEmpty
不能为null,集合、数组、map等size()不能为0;字符串trim()后可以等于“”
@Range
值必须在指定范围内
@URL
必须是一个URL

@Validated的使用时机

@Validated的使用位置较多(可详见源码),但其主流的使用位置却是以下两种:

1、在Controller层中,放在模型参数对象前
当Controller层中参数是一个对象模型时,只有将@Validated直接放在该模型前,该模型内部的字段才会被
校验(如果有对该模型的字段进行约束的话)。

2、在Controller层中,放在类上
当一些约束是直接出现在Controller层中的参数前时,只有将@Validated放在类上时,参数前的约束才会生效。

以下是简单的测试代码:

@Validated与@Valid的简单对比说明

@Valid注解与@Validated注解功能大部分类似;两者的不同主要在于:

@Valid属于javax下的,而@Validated属于spring下;
@Valid支持嵌套校验、而@Validated不支持,
@Validated支持分组,而@Valid不支持。

测试一下上述各注解

测试所用模型为:

import lombok.Getter;
import lombok.Setter;
import org.hibernate.validator.constraints.Length;
import org.hibernate.validator.constraints.Range;
import org.hibernate.validator.constraints.URL;
 
import javax.validation.constraints.*;
import java.util.Date;
import java.util.List;
import java.util.Map;
 
/**
 * Validation注解
 *
 * @author JustryDeng
 * @date 2019/1/15 0:43
 */
 
public class ValidationBeanModel {
 
    @Setter
    @Getter
    public class AbcAssertFalse {
 
        @AssertFalse
        private Boolean myAssertFalse;
    }
 
    @Setter
    @Getter
    public class AbcAssertTrue {
 
        @AssertTrue
        private Boolean myAssertTrue;
    }
 
    @Setter
    @Getter
    public class AbcDecimalMax {
 
        @DecimalMax(value = "12.3")
        private String myDecimalMax;
    }
 
    @Setter
    @Getter
    public class AbcDecimalMin {
 
        @DecimalMin(value = "10.3")
        private String myDecimalMin;
    }
 
    @Setter
    @Getter
    public class AbcDigits {
 
        @Digits(integer = 5, fraction = 3)
        private Integer myDigits;
    }
 
    @Setter
    @Getter
    public class AbcEmail {
 
        @Email
        private String myEmail;
    }
 
    @Setter
    @Getter
    public class AbcFuture {
 
        @Future
        private Date myFuture;
    }
 
    @Setter
    @Getter
    public class AbcLength {
 
        @Length(min = 5, max = 10)
        private String myLength;
    }
 
    @Setter
    @Getter
    public class AbcMax {
 
        @Max(value = 200)
        private Long myMax;
    }
 
    @Setter
    @Getter
    public class AbcMin {
 
        @Min(value = 100)
        private Long myMin;
    }
 
    @Setter
    @Getter
    public class AbcNotBlank {
 
        @NotBlank
        private String myStringNotBlank;
 
        @NotBlank
        private String myObjNotBlank;
    }
 
    @Setter
    @Getter
    public class AbcNotEmpty {
 
        @NotEmpty
        private String myStringNotEmpty;
 
        @NotEmpty
        private String myNullNotEmpty;
 
        @NotEmpty
        private Map<String, Object> myMapNotEmpty;
 
        @NotEmpty
        private List<Object> myListNotEmpty;
 
        @NotEmpty
        private Object[] myArrayNotEmpty;
    }
 
    @Setter
    @Getter
    public class AbcNotNull {
 
        @NotNull
        private String myStringNotNull;
 
        @NotNull
        private Object myNullNotNull;
 
        @NotNull
        private Map<String, Object> myMapNotNull;
    }
 
    @Setter
    @Getter
    public class AbcNull {
 
        @Null
        private String myStringNull;
 
        @Null
        private Map<String, Object> myMapNull;
    }
 
    @Setter
    @Getter
    public class AbcPast {
 
        @Past
        private Date myPast;
    }
 
    @Setter
    @Getter
    public class AbcPattern {
 
        @Pattern(regexp = "\\d+")
        private String myPattern;
    }
 
    @Setter
    @Getter
    public class AbcRange {
 
        @Range(min = 100, max = 100000000000L)
        private Double myRange;
    }
 
    @Setter
    @Getter
    public class AbcSize {
 
        @Size(min = 3, max = 5)
        private List<Integer> mySize;
    }
 
    @Setter
    @Getter
    public class AbcURL {
 
        @URL
        private String myURL;
    }
}
import com.aspire.model.*;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
 
import javax.validation.ConstraintViolation;
import javax.validation.Validation;
import javax.validation.Validator;
import javax.validation.ValidatorFactory;
import java.util.*;
 
@RunWith(SpringRunner.class)
@SpringBootTest
public class ValidationDemoApplicationTests {
 
    private Validator validator;
 
 
    @Before
    public void initValidator() {
        ValidatorFactory validatorFactory = Validation.buildDefaultValidatorFactory();
        validator = validatorFactory.getValidator();
    }
 
    /**
     * 在myAssertTrue属性上加@AssertTrue注解
     * <p>
     * 程序输出:  com.aspire.model.ValidationBeanModel$AbcAssertTrue类的myAssertTrue属性 -> 只能为true
     */
    @Test
    public void testAssertTrue() {
        ValidationBeanModel.AbcAssertTrue vm = new ValidationBeanModel().new AbcAssertTrue();
        vm.setMyAssertTrue(false);
        fa(vm);
    }
 
    /**
     * 在myAssertFalse属性上加@AssertFalse注解
     * <p>
     * 程序输出:  com.aspire.model.ValidationBeanModel$AbcAssertFalse类的myAssertFalse属性 -> 只能为false
     */
    @Test
    public void testAssertFalse() {
        ValidationBeanModel.AbcAssertFalse vm = new ValidationBeanModel().new AbcAssertFalse();
        vm.setMyAssertFalse(true);
        fa(vm);
    }
 
 
    /**
     * 在myDecimalMax属性上加@DecimalMax(value = "12.3")注解
     * <p>
     * 程序输出:  com.aspire.model.ValidationBeanModel$AbcDecimalMax类的myDecimalMax属性 -> 必须小于或等于12.3
     */
    @Test
    public void testDecimalMax() {
        ValidationBeanModel.AbcDecimalMax vm = new ValidationBeanModel().new AbcDecimalMax();
        vm.setMyDecimalMax("123");
        fa(vm);
    }
 
    /**
     * 在myDecimalMin属性上加@DecimalMin(value = "10.3")注解
     * <p>
     * 程序输出:  com.aspire.model.ValidationBeanModel$AbcDecimalMin类的myDecimalMin属性 -> 必须大于或等于10.3
     */
    @Test
    public void testDecimalMin() {
        ValidationBeanModel.AbcDecimalMin vm = new ValidationBeanModel().new AbcDecimalMin();
        vm.setMyDecimalMin("1.23");
        fa(vm);
    }
 
    /**
     * 在myDigits属性上加@Digits(integer = 5, fraction = 3)注解
     * <p>
     * 程序输出:  com.aspire.model.ValidationBeanModel$AbcDigits类的myDigits属性 -> 数字的值超出了允许范围(只允许在5位整数和3位小数范围内)
     */
    @Test
    public void testDigits() {
        ValidationBeanModel.AbcDigits vm = new ValidationBeanModel().new AbcDigits();
        vm.setMyDigits(1000738);
        fa(vm);
    }
 
    /**
     * 在myEmail属性上加@Email注解
     * <p>
     * 程序输出:  com.aspire.model.ValidationBeanModel$AbcEmail类的myEmail属性 -> 不是一个合法的电子邮件地址
     */
    @Test
    public void testEmail() {
        ValidationBeanModel.AbcEmail vm = new ValidationBeanModel().new AbcEmail();
        vm.setMyEmail("asd@.com");
        fa(vm);
    }
 
    /**
     * 在myFuture属性上加@Future注解
     * <p>
     * 程序输出:  com.aspire.model.ValidationBeanModel$AbcFuture类的myFuture属性 -> 需要是一个将来的时间
     */
    @Test
    public void testFuture() {
        ValidationBeanModel.AbcFuture vm = new ValidationBeanModel().new AbcFuture();
        vm.setMyFuture(new Date(10000L));
        fa(vm);
    }
 
    /**
     * 在myLength属性上加@Length(min = 5, max = 10)注解
     * <p>
     * 程序输出:  com.aspire.model.ValidationBeanModel$AbcLength类的myLength属性 -> 长度需要在5和10之间
     */
    @Test
    public void testLength() {
        ValidationBeanModel.AbcLength vm = new ValidationBeanModel().new AbcLength();
        vm.setMyLength("abcd");
        fa(vm);
    }
 
    /**
     * 在myMax属性上加@Max(value = 200)注解
     * <p>
     * 程序输出:  com.aspire.model.ValidationBeanModel$AbcMax类的myMax属性 -> 最大不能超过200
     */
    @Test
    public void testMax() {
        ValidationBeanModel.AbcMax vm = new ValidationBeanModel().new AbcMax();
        vm.setMyMax(201L);
        fa(vm);
    }
 
    /**
     * 在myMin属性上加@Min(value = 200)注解
     * <p>
     * 程序输出:  com.aspire.model.ValidationBeanModel$AbcMin类的myMin属性 -> 最小不能小于100
     */
    @Test
    public void testMin() {
        ValidationBeanModel.AbcMin vm = new ValidationBeanModel().new AbcMin();
        vm.setMyMin(99L);
        fa(vm);
    }
 
    /**
     * 在myStringNotBlank属性上加@NotBlank注解
     * 在myObjNotBlank属性上加@NotBlank注解
     *
     * 注:如果属性值为null 或者 .trim()后等于"",那么会提示 不能为空
     * <p>
     * 程序输出:   com.aspire.model.ValidationBeanModel$AbcNotBlank类的myObjNotBlank属性 -> 不能为空
     *            com.aspire.model.ValidationBeanModel$AbcNotBlank类的myStringNotBlank属性 -> 不能为空
     */
    @Test
    public void testNotBlank() {
        ValidationBeanModel.AbcNotBlank vm = new ValidationBeanModel().new AbcNotBlank();
        vm.setMyObjNotBlank(null);
        vm.setMyStringNotBlank(" ");
        fa(vm);
    }
 
    /**
     * 在myStringNotEmpty属性上加@NotEmpty注解
     * 在myNullNotEmpty属性上加@NotEmpty注解
     * 在myMapNotEmpty属性上加@NotEmpty注解
     * 在myListNotEmpty属性上加@NotEmpty注解
     * 在myArrayNotEmpty属性上加@NotEmpty注解
     *
     * 注:String可以是.trim()后等于""的字符串,但是不能为null
     * 注:MAP、Collection、Array既不能是空,也不能是null
     *
     * <p>
     * 程序输出: com.aspire.model.ValidationBeanModel$AbcNotEmpty类的myNullNotEmpty属性 -> 不能为空
     *           com.aspire.model.ValidationBeanModel$AbcNotEmpty类的myListNotEmpty属性 -> 不能为空
     *           com.aspire.model.ValidationBeanModel$AbcNotEmpty类的myArrayNotEmpty属性 -> 不能为空
     *           com.aspire.model.ValidationBeanModel$AbcNotEmpty类的myMapNotEmpty属性 -> 不能为空
     */
    @Test
    public void testNotEmpty() {
        ValidationBeanModel.AbcNotEmpty vm = new ValidationBeanModel().new AbcNotEmpty();
        vm.setMyStringNotEmpty(" ");
        vm.setMyNullNotEmpty(null);
        vm.setMyMapNotEmpty(new HashMap<>(0));
        vm.setMyListNotEmpty(new ArrayList<>(0));
        vm.setMyArrayNotEmpty(new String[]{});
        fa(vm);
    }
 
    /**
     * 在myStringNotNull属性上加@NotNull注解
     * 在myNullNotNull属性上加@NotNull注解
     * 在myMapNotNull属性上加@NotNull注解
     *
     * 注:属性值可以是空的, 但是就是不能为null
     * <p>
     * 程序输出:   com.aspire.model.ValidationBeanModel$AbcNotNull类的myNullNotNull属性 -> 不能为null
     */
    @Test
    public void testNotNull() {
        ValidationBeanModel.AbcNotNull vm = new ValidationBeanModel().new AbcNotNull();
        vm.setMyStringNotNull("   ");
        vm.setMyNullNotNull(null);
        vm.setMyMapNotNull(new HashMap<>(0));
        fa(vm);
    }
 
    /**
     * 在myStringNull属性上加@Null注解
     * 在myMapNotNull属性上加@Null注解
     *
     * 注:属性值必须是null, 是空都不行
     * <p>
     * 程序输出:   com.aspire.model.ValidationBeanModel$AbcNull类的myMapNull属性 -> 必须为null
     *            com.aspire.model.ValidationBeanModel$AbcNull类的myStringNull属性 -> 必须为null
     */
    @Test
    public void testNull() {
        ValidationBeanModel.AbcNull vm = new ValidationBeanModel().new AbcNull();
        vm.setMyStringNull("   ");
        vm.setMyMapNull(new HashMap<>(0));
        fa(vm);
    }
 
    /**
     * 在myPast属性上加@Past注解
     *
     * <p>
     * 程序输出:   com.aspire.model.ValidationBeanModel$AbcPast类的myPast属性 -> 需要是一个过去的时间
     */
    @Test
    public void testPast() {
        ValidationBeanModel.AbcPast vm = new ValidationBeanModel().new AbcPast();
        vm.setMyPast(new Date(20000000000000000L));
        fa(vm);
    }
 
    /**
     * 在myPattern属性上加@Pattern(regexp = "\\d+")注解
     *
     * <p>
     * 程序输出:   com.aspire.model.ValidationBeanModel$AbcPattern类的myPattern属性 -> 需要匹配正则表达式"\d"
     */
    @Test
    public void testPattern() {
        ValidationBeanModel.AbcPattern vm = new ValidationBeanModel().new AbcPattern();
        vm.setMyPattern("ABC");
        fa(vm);
    }
 
    /**
     * 在myRange属性上加@Range(min = 100, max = 100000000000L)注解
     *
     * <p>
     * 程序输出:   com.aspire.model.ValidationBeanModel$AbcRange类的myRange属性 -> 需要在100和100000000000之间
     */
    @Test
    public void testRange() {
        ValidationBeanModel.AbcRange vm = new ValidationBeanModel().new AbcRange();
        vm.setMyRange(32222222222222222222222222222222.323);
        fa(vm);
    }
 
    /**
     * 在mySize属性上加@Size(min = 3, max = 5)注解
     *
     * <p>
     * 程序输出:   com.aspire.model.ValidationBeanModel$AbcSize类的mySize属性 -> 个数必须在3和5之间
     */
    @Test
    public void testSize() {
        ValidationBeanModel.AbcSize vm = new ValidationBeanModel().new AbcSize();
        List<Integer> list = new ArrayList<>(4);
        list.add(0);
        list.add(1);
        vm.setMySize(list);
        fa(vm);
    }
 
    /**
     * 在myURL属性上加@URL注解
     *
     * <p>
     * 程序输出:   com.aspire.model.ValidationBeanModel$AbcURL类的myURL属性 -> 需要是一个合法的URL
     */
    @Test
    public void testURL() {
        ValidationBeanModel.AbcURL vm = new ValidationBeanModel().new AbcURL();
        vm.setMyURL("www.baidu.xxx");
        fa(vm);
    }
 
    private <T> void fa(T obj) {
        Set<ConstraintViolation<T>> cvSet = validator.validate(obj);
        for (ConstraintViolation<T> cv : cvSet) {
            System.err.println(cv.getRootBean().getClass().getName() + "类的"
                    + cv.getPropertyPath() + "属性 -> " + cv.getMessage());
        }
    }
 
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值