Springboot自定义字符串形式的日期验证注解,支持自定义格式

2022-02-08 / 5 阅读 / Java

自定义注解验证主要实现两个类

1. 注解类
2. 注解对应的校验器类

注解类代码示例:

package ****.validation;

import javax.validation.Constraint;
import javax.validation.Payload;
import java.lang.annotation.ElementType;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target({ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = StringDateValidator.class)
@Inherited
public @interface StringDate {
    String message() default "日期验证错误";

    String value() default "yyyy-MM-dd";

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

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

校验器类代码示例:

package ***.validation;

import ***.utils.DateUtil;
import ***.StringUtil;
import org.hibernate.validator.internal.engine.constraintvalidation.ConstraintValidatorContextImpl;

import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;
import java.util.Date;
import java.util.Locale;

public class StringDateValidator implements ConstraintValidator<StringDate, String> {

    private String value;

    @Override
    public void initialize(StringDate constraintAnnotation) {
        value = constraintAnnotation.value();
    }

    @Override
    public boolean isValid(String o, ConstraintValidatorContext constraintValidatorContext) {
        String fieldName = "";
        // 获取注解的字段名称,用于快速定位排查
        if (constraintValidatorContext instanceof ConstraintValidatorContextImpl) {
            ConstraintValidatorContextImpl validatorContext = (ConstraintValidatorContextImpl) constraintValidatorContext;
            if (validatorContext.getConstraintViolationCreationContexts() != null
                    && validatorContext.getConstraintViolationCreationContexts().size() > 0
                    && validatorContext.getConstraintViolationCreationContexts().get(0).getPath() != null) {
                fieldName = validatorContext.getConstraintViolationCreationContexts().get(0).getPath().asString();
            }
        }

        if (StringUtil.isEmpty(o)) {// 当值为空字符时,认为值有效
            return true;
        }

        String pattern = value.replaceAll("y|M|d|H|h|m|s|S", "[0-9]");
        boolean matches = o.matches(pattern);
        if (!matches) {
            // 禁用默认错误信息,防止错误信息与自定义信息乱串
            constraintValidatorContext.disableDefaultConstraintViolation();
            String message = String.format(Locale.CHINESE, "[%s]日期字符串(%s)不符合格式(%s)!", fieldName, o, value);
            constraintValidatorContext.buildConstraintViolationWithTemplate(message).addConstraintViolation();
            return false;
        }
        Date parse = DateUtil.parse(o, value);
        String format = DateUtil.format(parse, value);
        if (!format.equals(o)) {
            // 禁用默认错误信息,防止错误信息与自定义信息乱串
            constraintValidatorContext.disableDefaultConstraintViolation();
            String message = String.format(Locale.CHINESE, "[%s]日期字符串(%s)有误,请检查!", fieldName, o);
            constraintValidatorContext.buildConstraintViolationWithTemplate(message).addConstraintViolation();
            return false;
        }
        return true;
    }
}
相关推荐