優(yōu)雅的參數(shù)校驗(yàn) JSR303 javax.validation.constraints

1. controller層直接使用校驗(yàn)注解校驗(yàn)簡單參數(shù)。比如@Max等等

類上面打注解 @Validated
參數(shù)前面打注解 @Max

@Api(value = "分類", tags = "分類模塊")
@RestController
@RequestMapping("/category")
@Validated
public class CategoryController {

    // 舉例:id限制最大為10
    @ApiOperation(value = "單個查詢", notes = "1.0版本")
    @GetMapping("/id/{id}")
    public CategoryVO getById(@PathVariable @Max(10) Long id) {
        return null;
    }
}

2. controller層要校驗(yàn)請求對象

要校驗(yàn)的對象前面打注解 @Validated
對象內(nèi)部打上需要的注解
如果對象內(nèi)還有對象,則在內(nèi)部對象字段打注解@Valid,然后內(nèi)部對象類里的屬性打上各種校驗(yàn)注解

    @PostMapping("/add")
    public Boolean add(@RequestBody @Validated CategoryDTO categoryDTO) {
        CategoryDO categoryDO = new CategoryDO();
        BeanUtils.copyProperties(categoryDTO, categoryDO);
        return categoryService.save(categoryDO);
    }
/**
 * @author wangningbo
 */
@Getter
@Setter
@ApiModel(value = "CategoryDTO對象", description = "新增或修改對象")
public class CategoryDTO {

    @NotBlank
    @ApiModelProperty("名稱")
    private String name;

    @URL
    @ApiModelProperty("圖片")
    private String img;

    @ApiModelProperty("描述")
    private String description;

    @ApiModelProperty("父id")
    private Long parentId;

    @ApiModelProperty("上線:0->下架;1->上線;")
    private Boolean online;

    @ApiModelProperty("排序")
    private Integer sort;
}

3. @Validated 和 @Valid

有一定的相似性,他們都是開啟或關(guān)閉校驗(yàn)的開關(guān)

4. 自定義校驗(yàn)注解

場景舉例:假設(shè)用戶注冊賬號,要校驗(yàn)它2次輸入的密碼是否一致,并且密碼的長度要在8~16位

自定義校驗(yàn)注解

/**
 * 自定義校驗(yàn)注解
 * true 密碼長度要在8~16位,且兩次密碼相同
 *
 * @author wangningbo
 */
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE})
@Constraint(validatedBy = PasswordEqualValidator.class)
public @interface PasswordEqual {
    int min() default 8;

    int max() default 16;

    String message() default "passwords are not equal";

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

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

自定義注解的驗(yàn)證器

/**
 * passwordEqual 注解的驗(yàn)證器
 *
 * @author wangningbo
 */
public class PasswordEqualValidator implements ConstraintValidator<PasswordEqual, Map<String, String>> {

    int min;
    int max;

    @Override
    public void initialize(PasswordEqual constraintAnnotation) {
        this.min = constraintAnnotation.min();
        this.max = constraintAnnotation.max();
    }

    @Override
    public boolean isValid(Map<String, String> map, ConstraintValidatorContext constraintValidatorContext) {
        String password1 = map.get("password1");
        String password2 = map.get("password2");
        if (password1.length() < min || password1.length() > max) {
            return false;
        }
        return password1.equals(password2);
    }
}

以后在使用的時候,直接把注解打在類上即可

5. 分組校驗(yàn)

分組

/**
 * @author wangningbo
 */
public interface AddGroup {
}
/**
 * 空接口,用于 JSR303 分組校驗(yàn)
 *
 * @author wangningbo
 */
public interface UpdateGroup {
}

分組校驗(yàn)分為以下3種情況

5.1 單分組校驗(yàn)

場景舉例:我要指定新增新增的時候校驗(yàn)?zāi)男┳侄?br> 解決思路:新增接口入?yún)⒌臅r候指定對象使用的分組,對象內(nèi)的字段也指定分組

指定對象使用哪個分組進(jìn)行校驗(yàn) @Validated({AddGroup.class})

    @PostMapping("/add")
    public Boolean add(@RequestBody @Validated({AddGroup.class}) CategoryDTO categoryDTO) {
    }

注解的groups屬性指定在哪個分組的情況下進(jìn)行校驗(yàn)。沒有指定分組的注解在分組校驗(yàn)下不生效。

/**
 * @author wangningbo
 */
@Getter
@Setter
@ApiModel(value = "CategoryDTO對象", description = "新增或修改對象")
public class CategoryDTO {

    @Null(groups = {AddGroup.class})
    @ApiModelProperty("主鍵id")
    private Long id;

    @NotBlank(groups = {AddGroup.class})
    @ApiModelProperty("名稱")
    private String name;

    @NotBlank(groups = {AddGroup.class})
    @URL(groups = {AddGroup.class)
    @ApiModelProperty("圖片")
    private String img;

    @ApiModelProperty("描述")
    private String description;

    @ApiModelProperty("父id")
    private Long parentId;

    @ApiModelProperty("上線:0->下架;1->上線;")
    private Boolean online;

    @ApiModelProperty("排序")
    private Integer sort;
}

結(jié)果:從上面可以看字段id、name、img這三個字段指定了分組校驗(yàn)的AddGroup分組,到進(jìn)行新增的時候,就會校驗(yàn)這三個字段

5.2 多分組校驗(yàn)

場景舉例:img字段,新增的時候必須填寫,且必須為url。修改的時候可以不填寫,但是填寫了就必須為url。
解決思路:新增接口入?yún)⒌臅r候指定對象使用的分組,新增和修改都要對img這個字段有一定的限制,根據(jù)不同的場景限制不同的分組即可

指定對象使用哪個分組進(jìn)行校驗(yàn) @Validated({UpdateGroup.class})

    @PostMapping("/update")
    public Boolean update(@RequestBody @Validated({UpdateGroup.class}) CategoryDTO categoryDTO) {
    }

注解的groups屬性指定在哪個分組的情況下進(jìn)行校驗(yàn)。沒有指定分組的注解在分組校驗(yàn)下不生效。

@Getter
@Setter
@ApiModel(value = "CategoryDTO對象", description = "新增或修改對象")
public class CategoryDTO {

    @NotNull(groups = {UpdateGroup.class})
    @Null(groups = {AddGroup.class})
    @ApiModelProperty("主鍵id")
    private Long id;

    @NotBlank(groups = {AddGroup.class})
    @ApiModelProperty("名稱")
    private String name;

    @NotBlank(groups = {AddGroup.class})
    @URL(groups = {AddGroup.class, UpdateGroup.class})
    @ApiModelProperty("圖片")
    private String img;

    @ApiModelProperty("描述")
    private String description;

    @ApiModelProperty("父id")
    private Long parentId;

    @ApiModelProperty("上線:0->下架;1->上線;")
    private Boolean online;

    @ApiModelProperty("排序")
    private Integer sort;
}

結(jié)果:從上面可以看出字段id和字段img上有的注解指定了update分組。在修改的時候,id必傳遞,img可以不傳,但是如果傳了就必須為url格式。否則就會報參數(shù)異常錯

5.3 不指定分組校驗(yàn)

場景舉例:@Validated 注解在controller沒有指定校驗(yàn)對象的分組

    @PostMapping("/add")
    public Boolean add(@RequestBody @Validated CategoryDTO categoryDTO) {
    }
/**
 * @author wangningbo
 */
@Getter
@Setter
@ApiModel(value = "CategoryDTO對象", description = "新增或修改對象")
public class CategoryDTO {

    @NotNull(groups = {UpdateGroup.class})
    @Null(groups = {AddGroup.class})
    @ApiModelProperty("主鍵id")
    private Long id;

    @NotBlank(groups = {AddGroup.class})
    @ApiModelProperty("名稱")
    private String name;

    @NotBlank(groups = {AddGroup.class})
    @URL(groups = {AddGroup.class, UpdateGroup.class})
    @ApiModelProperty("圖片")
    private String img;

    @ApiModelProperty("描述")
    private String description;

    @ApiModelProperty("父id")
    private Long parentId;

    @ApiModelProperty("上線:0->下架;1->上線;")
    private Boolean online;

    @NotNull
    @ApiModelProperty("排序")
    private Integer sort;
}

結(jié)果:可以看到controller層的@Validated沒有指定分組,所以校驗(yàn)的對象的屬性上的校驗(yàn)注解沒有指定分組的才會生效,所以只會校驗(yàn)sort字段。

6. 常用校驗(yàn)注解

@Null 被注釋的元素必須為 null
@NotNull 被注釋的元素必須不為 null
@AssertTrue 被注釋的元素必須為 true
@AssertFalse 被注釋的元素必須為 false
@Min(value) 被注釋的元素必須是一個數(shù)字,其值必須大于等于指定的最小值
@Max(value) 被注釋的元素必須是一個數(shù)字,其值必須小于等于指定的最大值
@DecimalMin(value) 被注釋的元素必須是一個數(shù)字,其值必須大于等于指定的最小值
@DecimalMax(value) 被注釋的元素必須是一個數(shù)字,其值必須小于等于指定的最大值
@Size(max=, min=) 被注釋的元素的大小必須在指定的范圍內(nèi)
@Digits (integer, fraction) 被注釋的元素必須是一個數(shù)字,其值必須在可接受的范圍內(nèi)
@Past 被注釋的元素必須是一個過去的日期
@Future 被注釋的元素必須是一個將來的日期
@Pattern(regex=,flag=) 被注釋的元素必須符合指定的正則表達(dá)式
Hibernate Validator 附加的 constraint
@NotBlank(message =) 驗(yàn)證字符串非null,且長度必須大于0
@Email 被注釋的元素必須是電子郵箱地址
@Length(min=,max=) 被注釋的字符串的大小必須在指定的范圍內(nèi)
@NotEmpty 被注釋的字符串的必須非空
@Range(min=,max=,message=) 被注釋的元素必須在合適的范圍內(nèi)

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容