自定义校验注解

自定义校验注解,需要新建注解,注解中必须包含必须的基础字段:message、groups、payload。然后可以添加自己自定义的字段。

想要被@Validated 注解自动校验,需要指定注解的规则校验类:@Constraint(validatedBy = {校验类})

所以也就还需要一个规则校验的类。这个类需要实现 ConstraintValidator接口,实现initialize方法 和isValid方法。 initialize方法做一些初始化操作,isValid用来判断是否符合规则,校验通过返回true校验失败返回false

示例:车牌号校验注解。

package com.baidu.internalsdk.annotation.validation;


import cn.hutool.core.lang.Validator;
import cn.hutool.core.util.StrUtil;

import javax.validation.Constraint;
import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;
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.ANNOTATION_TYPE;
import static java.lang.annotation.ElementType.FIELD;
import static java.lang.annotation.RetentionPolicy.RUNTIME;

/**
 * 车牌号检车注解
 */
@Documented
@Target({FIELD, ANNOTATION_TYPE})
@Constraint(validatedBy = {CheckVehicleNo.CheckVehicleNoHandler.class}) // 约束校验的类,需要实现接口 ConstraintValidator
@Retention(RUNTIME)
public @interface CheckVehicleNo {
    /**
     * 错误消息
     */
    String message() default "不是中国的车牌号";

    /**
     * 如果同一个参数,需要在不同场景下应用不同的校验规则,就需要用到分组校验了
     * 如果使用请参考:
     *
     */
    Class<?>[] groups() default {};

    /**
     * 校验结束后,如果出现错误,指定默认错误严重级别,进行不同的处理
     * ConstraintViolation.getConstraintDescriptor().getPayload() 来得到错误等级
     *
     */
    Class<? extends Payload>[] payload() default {};

    /**
     * 是否忽略空值校验,如果为 {@code true} 且被修改的字属性为空,不进行校验,直接返回通过
     */
    boolean ignoreBlank() default false;

    /**
     * 处理 车牌号校验 校验规则的处理类
     */
    class CheckVehicleNoHandler implements ConstraintValidator<CheckVehicleNo, String> {

        // 是否忽略空值校验,如果为true且被校验的值为空,直接校验通过
        private boolean ignoreEmpty;

        @Override
        public void initialize(CheckVehicleNo constraintAnnotation) {
            ignoreEmpty = constraintAnnotation.ignoreBlank();
        }

        @Override
        public boolean isValid(String value, ConstraintValidatorContext context) {
            // 如果为空不进行校验且传入的值为空,直接返回校验通过
            if (ignoreEmpty && StrUtil.isEmpty(value)) {
                return true;
            }
            return Validator.isPlateNumber(value);
        }
    }


}

其中,如果项目中没有使用Hutool工具包的话,可以使用自定义的正则规则校验车牌号。
摘抄一下Hutool的中国的车牌号正则表达式:

// import java.util.regex.Pattern; 导入的是这个包的Pattern

public final static Pattern PLATE_NUMBER = Pattern.compile(
    //https://gitee.com/loolly/hutool/issues/I1B77H?from=project-issue
    "^(([京津沪渝冀豫云辽黑湘皖鲁新苏浙赣鄂桂甘晋蒙陕吉闽贵粤青藏川宁琼使领][A-Z](([0-9]{5}[ABCDEFGHJK])|([ABCDEFGHJK]([A-HJ-NP-Z0-9])[0-9]{4})))|" +
    //https://gitee.com/loolly/hutool/issues/I1BJHE?from=project-issue
    "([京津沪渝冀豫云辽黑湘皖鲁新苏浙赣鄂桂甘晋蒙陕吉闽贵粤青藏川宁琼使领]\\d{3}\\d{1,3}[领])|" +
    "([京津沪渝冀豫云辽黑湘皖鲁新苏浙赣鄂桂甘晋蒙陕吉闽贵粤青藏川宁琼使领][A-Z][A-HJ-NP-Z0-9]{4}[A-HJ-NP-Z0-9挂学警港澳使领]))$");



// 附上使用方法:
// 判断是否是中国车牌号
public boolean isPlateNumber(String value) {
    return PLATE_NUMBER.matcher(value).matches();
}

然后在想要限制的的字段上使用注解即可。

@NotBlank(message = "请输入车牌号")
@CheckVehicleNo(ignoreBlank = true)
private String carNo;

使用@Validated注解使其自动校验。

@ApiOperation(value = "修改批次信息")
@PutMapping("/{id}")
public ResponseResult<?> update(@Validated @RequestBody BatchUpdateReqVO req, @PathVariable Long id) {
    batchService.update(req, id);
    return ResponseResult.success();
}