Springboot中如何优雅的进行字段校验

开发web项目有时候我们需要对controller层传过来的参数进行一些基本的校验,比如非空,非null,整数值的范围,字符串的个数,日期,邮箱等等。最常见的就是我们直接写代码校验,这样以后比较繁琐,而且不够灵活。

前段时间提交代码审核,同事提了一个代码规范缺陷:参数校验应该放在controller层。到底应该如何做参数校验呢?

Controller层 VS Service层

service负责数据的读写以及根据各种条件读写,action确保数据正确的读写。action就相当于一个窗口,它就应该筛选出满足条件的和过滤掉不满足条件的,属于基本校验。

service就相当于一个服务者,为action分派的任务进行处理,比如service接收到一个用户id,但是这个用户不存在,属于业务校验,可以在service层抛出。

Bean Validation 1.0(JSR-303)是一个校验规范,在spring Boot项目由于自带了hibernate validator 5(http://hibernate.org/validator/)实现,所以我们可以非常方便的使用这个特性 。

常用校验工具类

使用Hibernate Validate

引入依赖


    org.hibernate
    hibernate-validator
    4.3.1.Final

常用注解说明

注解 说明
@Length(min=,max=) 检查所属的字段的长度是否在min和max之间,只能用于字符串
@Range(min=,max=,message=) 被注释的元素必须在合适的范围内
@Max 该字段的值只能小于或等于该值
@Min 该字段的值只能大于或等于该值
@NotNull 不能为null
@NotBlank 不能为空, 检查时会将空格忽略
@NotEmpty 不能为空, 这里的空是指空字符串
@Pattern(regex=,flag=) 被注释的元素必须符合指定的正则表达式

使用姿势需要搭配在Controller中搭配@Validated或@Valid注解一起使用,@Validated和@Valid注解区别不是很大,一般情况下任选一个即可,区别如下:

注解 @Validated @Valid
所属的包 属于org.springframework.validation.annotation包下的,是spring提供的 属于javax.validation包下,是jdk给提供的
是否支持分组和排序

虽然@Validated比@Valid更加强大,在@Valid之上提供了分组功能和验证排序功能,不过在实际项目中一直没有用到过 Hibernate-validate框架中的注解是需要加在实体中一起使用的

定义一个实体
public class DataSetSaveVO {
    //唯一标识符为空
    @NotBlank(message = user uuid is empty)
    //用户名称只能是字母和数字
    @Pattern(regexp = ^[a-z0-9]+$, message = user names can only be alphabetic and numeric)
    @Length(max = 48, message = user uuid length over 48 byte)
    private String userUuid;

    //数据集名称只能是字母和数字
    @Pattern(regexp = ^[A-Za-z0-9]+$, message = data set names can only be letters and Numbers)
    //文件名称过长
    @Length(max = 48, message = file name too long)
    //文件名称为空
    @NotBlank(message = file name is empty)
    private String name;

    //数据集描述最多为256字节
    @Length(max = 256, message = data set description length over 256 byte)
    //数据集描述为空
    @NotBlank(message = data set description is null)
    private String description;
}

说明:message字段为不符合校验规则时抛出的异常信息

Controller层中的方法
@PostMapping
public ResponseVO createDataSet(@Valid @RequestBody DataSetSaveVO dataSetVO) {
    return ResponseUtil.success(dataSetService.saveDataSet(dataSetVO));
}

说明:在校验的实体DataSetSaveVO旁边添加@Valid或@Validated注解

补充:使用自定义参数注解

1.我们这里创建一个身份证校验注解


@Documented
@Target({ElementType.PARAMETER, ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = IdentityCardNumberValidator.class)
public @interface IdentityCardNumber {
    String message() default "身份证号码不合法";
    Class[] groups() default {};
    Class[] payload() default {};
 
}

这个注解是作用在Field字段上,运行时生效,触发的是IdentityCardNumber这个验证类。

message 定制化的提示信息,主要是从ValidationMessages.properties里提取,也可以依据实际情况进行定制
groups 这里主要进行将validator进行分类,不同的类group中会执行不同的validator操作
payload 主要是针对bean的,使用不多。

2.自定义Validator


import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;
 
public class IdentityCardNumberValidator implements ConstraintValidator {
    @Override
    public void initialize(IdentityCardNumber identityCardNumber) {
    }
    @Override
    public boolean isValid(Object o, ConstraintValidatorContext constraintValidatorContext) {
        return IdCardValidatorUtils.isValidate18Idcard(o.toString());
    }
}


校验工具类IdCardValidatorUtils.class

3. 使用自定义的注解

@NotBlank(message = "身份证号不能为空")
@IdentityCardNumber(message = "身份证信息有误,请核对后提交")
private String clientCardNo;

你可能感兴趣的:(java,spring)