SpringBoot使用Validation校验参数

准备工作

引入相关依赖:

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

注:我们知道maven依赖都是环环相扣的,例如我们在项目中spring-boot-starter-web,它也会将validation的依赖引入,因此我们引入依赖的是时候,有时是可以忽略的。

约束性注解(简单)说明

注解

功能

@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

注:此表格只是简单的对注解功能的说明,并没有对每一个注解的属性进行说明;可详见源码。

下面简单测试一下上述各注解:
测试所用模型为:

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());
        }
    }
 }

@Validated与@Valid的简单对比

这里参考了另一个博主的文章:https://blog.csdn.net/qq_27680317/article/details/79970590

结论

@Valid注解与@Validated注解功能大部分类似;两者的不同主要在于:@Valid属于javax下的,而@Validated属于spring下;@Valid支持嵌套校验、而@Validated不支持,@Validated支持分组,而@Valid不支持。笔者这里只简单介绍@Validated的使用时机。

简介

Spring Validation验证框架对参数的验证机制提供了@Validated(Spring’s JSR-303规范,是标准JSR-303的一个变种),javax提供了@Valid(标准JSR-303规范),配合BindingResult可以直接提供参数验证结果。其中对于字段的特定验证注解比如@NotNull等网上到处都有,这里不详述

在检验Controller的入参是否符合规范时,使用@Validated或者@Valid在基本验证功能上没有太多区别。但是在分组、注解地方、嵌套验证等功能上两个有所不同:

1. 分组

@Validated:提供了一个分组功能,可以在入参验证时,根据不同的分组采用不同的验证机制,这个网上也有资料,不详述。@Valid:作为标准JSR-303规范,还没有吸收分组的功能。

2. 使用位置

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

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

两者是否能用于成员属性(字段)上直接影响能否提供嵌套验证的功能。

3. 嵌套验证

在比较两者嵌套验证时,先说明下什么叫做嵌套验证。比如我们现在有个实体叫做Item:

public class Item {

    @NotNull(message = "id不能为空")
    @Min(value = 1, message = "id必须为正整数")
    private Long id;

    @NotNull(message = "props不能为空")
    @Size(min = 1, message = "至少要有一个属性")
    private List<Prop> props;
}

Item带有很多属性,属性里面有属性id,属性值id,属性名和属性值,如下所示:

public class Prop {

    @NotNull(message = "pid不能为空")
    @Min(value = 1, message = "pid必须为正整数")
    private Long pid;

    @NotNull(message = "vid不能为空")
    @Min(value = 1, message = "vid必须为正整数")
    private Long vid;

    @NotBlank(message = "pidName不能为空")
    private String pidName;

    @NotBlank(message = "vidName不能为空")
    private String vidName;
}

属性这个实体也有自己的验证机制,比如属性和属性值id不能为空,属性名和属性值不能为空等。
现在我们有个ItemController接受一个Item的入参,想要对Item进行验证,如下所示:

@RestController
public class ItemController {

    @RequestMapping("/item/add")
    public void addItem(@Validated Item item, BindingResult bindingResult) {
        doSomething();
    }
}

上述代码是不能实现嵌套校验的,只在入参加了@Validated(或@Valid),Item实体的props属性不额外加注释也只有@NotNull和@Size,Spring Validation框架只会对Item的id和props做非空和数量验证,不会对props字段里的Prop实体进行字段验证。

为了能够进行嵌套验证,必须手动在Item实体的props字段上明确指出这个字段里面的实体也要进行验证。由于@Validated不能用在成员属性(字段)上,但是@Valid能加在成员属性(字段)上,而且@Valid类注解上也说明了它支持嵌套验证功能,那么我们能够推断出:@Valid加在方法参数时并不能够自动进行嵌套验证,而是用在需要嵌套验证类的相应字段上,来配合方法参数上@Validated或@Valid来进行嵌套验证。

我们修改Item类如下所示:

public class Item {

    @NotNull(message = "id不能为空")
    @Min(value = 1, message = "id必须为正整数")
    private Long id;

    @Valid // 嵌套验证必须用@Valid
    @NotNull(message = "props不能为空")
    @Size(min = 1, message = "props至少要有一个自定义属性")
    private List<Prop> props;
}

然后我们在ItemController的addItem函数上再使用@Validated或者@Valid,就能对Item的入参进行嵌套验证。此时Item里面的props如果含有Prop的相应字段为空的情况,Spring Validation框架就会检测出来,bindingResult就会记录相应的错误。

@Validated和@Valid区别小结

总结一下@Validated和@Valid在嵌套验证功能上的区别:

@Validated:用在方法入参上无法单独提供嵌套验证功能(要配合嵌套验证注解@Valid进行嵌套验证)。不能用在成员属性(字段)上,也无法提示框架进行嵌套验证。

@Valid:用在方法入参上无法单独提供嵌套验证功能(也要配合嵌套验证注解@Valid进行嵌套验证)。能够用在成员属性(字段)上,提示验证框架进行嵌套验证。

自定义注解

虽然Bean Validation和Hibernate Validator已经提供了非常丰富的校验注解,但是在实际业务中,难免会碰到一些现有注解不足以校验的情况;这时,我们可以考虑自定义Validation注解。
示例:

第一步:创建自定义注解

import com.aspire.constraints.impl.JustryDengValidator;
 
import javax.validation.Constraint;
import javax.validation.Payload;
import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
 
import static java.lang.annotation.ElementType.FIELD;
import static java.lang.annotation.ElementType.PARAMETER;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
 
/**
 * 自定义校验注解
 * 提示:
 *     1、message、contains、payload是必须要写的
 *     2、还需要什么方法可根据自己的实际业务需求,自行添加定义即可
 *
 * 注:当没有指定默认值时,那么在使用此注解时,就必须输入对应的属性值
 *
 * @author JustryDeng
 * @date 2019/1/15 1:17
 */
@Target({FIELD, PARAMETER})
@Retention(RUNTIME)
@Documented
// 指定此注解的实现,即:验证器
@Constraint(validatedBy ={JustryDengValidator.class})
public @interface ConstraintsJustryDeng {
 
    // 当验证不通过时的提示信息
    String message() default "JustryDeng : param value must contais specified value!";
 
    // 根据实际需求定的方法
    String contains() default "";
 
    // 约束注解在验证时所属的组别
    Class<?>[] groups() default { };
 
    // 负载
    Class<? extends Payload>[] payload() default { };

}

第二步:编写(第一步中的校验器实现类)该注解


import com.aspire.constraints.anno.ConstraintsJustryDeng;
import org.hibernate.validator.internal.engine.ValidationContext;
import org.hibernate.validator.internal.engine.ValueContext;
import org.hibernate.validator.internal.engine.constraintvalidation.ConstraintTree;
 
import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;
 
/**
 * ConstraintsJustryDeng注解 校验器 实现
 * <p>
 * 注:验证器需要实现ConstraintValidator<U, V>, 其中 U为对应的注解类, V为被该注解标记的字段的类型(或其父类型)
 *
 * 注: 当项目启动后,会(懒加载)创建ConstraintValidator实例,在创建实例后会初始化调
 *     用{@link ConstraintValidator#initialize}方法。
 *     所以, 只有在第一次请求时,会走initialize方法, 后面的请求是不会走initialize方法的。
 *
 * 注: (懒加载)创建ConstraintValidator实例时, 会走缓存; 如果缓存中有,则直接使用相
 *     同的ConstraintValidator实例; 如果缓存中没有,那么会创建新的ConstraintValidator实例。
 *     由于缓存的key是能唯一定位的, 且 ConstraintValidator的实例属性只有在
 *     {@link ConstraintValidator#initialize}方法中才会写;在{@link ConstraintValidator#isValid}
 *     方法中只是读。
 *     所以不用担心线程安全问题。
 *
 * 注: 如何创建ConstraintValidator实例的,可详见源码
 *     @see ConstraintTree#getInitializedConstraintValidator(ValidationContext, ValueContext)
 *
 * @author JustryDeng
 * @date 2019/1/15 1:19
 */
public class JustryDengValidator implements ConstraintValidator<ConstraintsJustryDeng, Object> {
 
    /** 错误提示信息 */
    private String contains;
 
    /**
     * 初始化方法, 在(懒加载)创建一个当前类实例后,会马上执行此方法
     *
     * 注: 此方法只会执行一次,即:创建实例后马上执行。
     *
     * @param constraintAnnotation
     *         注解信息模型,可以从该模型中获取注解类中定义的一些信息,如默认值等
     * @date 2019/1/19 11:27
     */
    @Override
    public void initialize(ConstraintsJustryDeng constraintAnnotation) {
        System.out.println(constraintAnnotation.message());
        this.contains = constraintAnnotation.contains();
    }
 
    /**
     * 校验方法, 每个需要校验的请求都会走这个方法
     *
     * 注: 此方法可能会并发执行,需要根据实际情况看否是需要保证线程安全。
     *
     * @param value
     *         被校验的对象
     * @param context
     *         上下文
     *
     * @return 校验是否通过
     */
    @Override
    public boolean isValid(Object value, ConstraintValidatorContext context) {
        if (value == null) {
            return false;
        }
        if (value instanceof String) {
            String strMessage = (String) value;
            return strMessage.contains(contains);
        } else if (value instanceof Integer) {
            return contains.contains(String.valueOf(value));
        }
        return false;
    }
 }

第三步:自定义注解简单使用测试

Controller层中是这样的:
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值