validated

前言:

在spring-boot学习中,遇到了有限定条件的值,前端传来的数据需要有格式限制,例如url,邮箱等限制,为了避免前端工作量太大,于是在后端传递数据是进行校验数据。

为了满足要求,使数据合法我们要对数据进行检验。

validated

spring-boot中可以用@validated来校验数据,如果数据异常则会统一抛出异常,方便异常中心统一处理。结尾有常用的validated注释方法。

后台校验(服务端校验):

  • Controller层:校验前台页面提交过来的参数的合法性
  • Service层:校验service接口中使用的参数
  • DAO层:一般不校验

正常使用:

本次使用中使用的Controller层的校验:

@Data
public class Article {

    private Integer id;//主键ID
    @NotEmpty
    @Pattern(regexp = "^\\S{1,10}$")
    private String title;//文章标题

    @NotEmpty
    private String content;//文章内容

    @NotEmpty
    @URL
    private String coverImg;//封面图像

    @State
    private String state;//发布状态 已发布|草稿

    @NotNull
    private Integer categoryId;//文章分类id
    private Integer createUser;//创建人ID
    private LocalDateTime createTime;//创建时间
    private LocalDateTime updateTime;//更新时间
}

使用@Validated注解

@Validated可以应用在控制器类上,也可以应用在方法级别,用来启用Bean Validation

@PostMapping
    public Result add(@RequestBody @Validated Article article){
        articleService.add(article);
        return Result.success();
    }

使用多个注释,对数据加以判断。其中有一个   @State为自定义注释,我们后续再说。

发现问题:

@Data
public class Category {
    @NotNull(groups = Update.class)
    private Integer id;//主键ID

    @NotEmpty
    private String categoryName;//分类名称

    @NotEmpty
    private String categoryAlias;//分类别名

    private Integer createUser;//创建人ID

    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    private LocalDateTime createTime;//创建时间

    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    private LocalDateTime updateTime;//更新时间

    public interface Add extends Default {

    }
    public interface Update extends Default {

    }
}

在使用实体Category时,发现id在添加和修改时的判断条件不同,由于前文在jwt令牌中封存了id,使用ThreadLocal传递id,而上文提到判断参数实在Contrioller层判断,而id是在service层传递的:

 @Override
    public Category findById(Integer id) {
       Category c = categoryMapper.findById(id);
        return c;
    }

导致在测试时出现该参数不能为空的错误,于是就在该实体类进行分组

Validated分组:

如果说某个校验项没有指定分组,默认属于Default分组,分组之间可以继承  A extend B A中有b的所有校验项

 @NotNull(groups = Update.class)
    private Integer id;//主键ID

   

    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    private LocalDateTime createTime;//创建时间

    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    private LocalDateTime updateTime;//更新时间

    
    public interface Add extends Default {

    }
    public interface Update extends Default {

    }

这样使得id在添加时必须存在,而修改时后续传参id为空也不影响。

自定义注释

在接口文档中,对state的注释是只能为已发布或者草稿,在现成的validated注解中,显然没有可以达成的,也可以创建一个枚举结构,使传入数据为枚举中其一,但是这里使用自定义注释的方法

自定义:

@Documented

@Target({ElementType.FIELD})

@Constraint(validatedBy = {StateValidation.class})

@Retention(RetentionPolicy.RUNTIME)

public @interface State {
    //提供校验失败后的信息
    String message() default "state参数的值只能说草稿或已发布";
    //指定分组
    Class<?>[] groups() default {};
    //负载,获取State注解的附加信息
    Class<? extends Payload>[] payload() default {};
}

元注解,可被抽取           :@Documented
元注解,可用于那些地方: @Target({ElementType.FIELD})
指定通过校验规则的类     :@Constraint(validatedBy = {StateValidation.class})
元注解,在那些阶段被保留,运行阶段:@Retention(RetentionPolicy.RUNTIME)

对应这些注解,我们可以从其中现成的注解中,进入源码照猫画虎即可:

以@NotEmpty为例

@Documented
@Constraint(
    validatedBy = {}
)
@Target({ElementType.METHOD, ElementType.FIELD, ElementType.ANNOTATION_TYPE, ElementType.CONSTRUCTOR, ElementType.PARAMETER, ElementType.TYPE_USE})
@Retention(RetentionPolicy.RUNTIME)
@Repeatable(List.class)
public @interface NotEmpty {
    String message() default "{jakarta.validation.constraints.NotEmpty.message}";

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

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

    @Target({ElementType.METHOD, ElementType.FIELD, ElementType.ANNOTATION_TYPE, ElementType.CONSTRUCTOR, ElementType.PARAMETER, ElementType.TYPE_USE})
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    public @interface List {
        NotEmpty[] value();
    }
}

完成后输入数据只能为已发布或者草稿,至于前段页面是输入框,还是选择框,这些就由前端程序员决定了。

常用的validated注解

// JSR提供的校验注解:         
@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(regex=,flag=)  被注释的元素必须符合指定的正则表达式    

// Hibernate Validator提供的校验注解:  
@NotBlank(message =)   验证字符串非null,且长度必须大于0    
@Email  被注释的元素必须是电子邮箱地址    
@Length(min=,max=)  被注释的字符串的大小必须在指定的范围内    
@NotEmpty   被注释的字符串的必须非空    
@Range(min=,max=,message=)  被注释的元素必须在合适的范围内

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值