文章

🍀SpringBoot:RequestParam方式参数校验实现

一、创建参数校验注解

@Documented
@Constraint(validatedBy = FieldValidatorHandler.class)
@Target({ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
public @interface FieldValidator {
    String message() default "Invalid value";

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

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

    /**
     * 数值或字符串的最小长度/值
     *
     * @return 字符串最小长度,数字最小值
     */
    int min() default Integer.MIN_VALUE;

    /**
     * 数值或字符串的最大长度/值
     *
     * @return 字符串最大长度,数字最大值
     */
    int max() default Integer.MAX_VALUE;

    /**
     * 字段是否可以为空
     *
     * @return true or false
     */
    boolean notNull() default false;
}

二、通用字段校验器实现

  1. 实现ConstraintValidator接口

public class FieldValidatorHandler implements ConstraintValidator<FieldValidator, Object> {
    private int min;
    private int max;
    private boolean notNull;

    // 存储类型与校验逻辑的映射
    private static final Map<Class<?>, FieldValidatorFunction<?>> VALIDATOR_MAP = new HashMap<>();

    static {
        // 注册字符串类型的校验器
        VALIDATOR_MAP.put(String.class, (value, min, max) -> {
            int length = ((String) value).length();
            return length >= min && length <= max;
        });

        // 注册 Integer 类型的校验器
        VALIDATOR_MAP.put(Integer.class, (value, min, max) -> {
            int intValue = (Integer) value;
            return intValue >= min && intValue <= max;
        });

        // 注册 Long 类型的校验器
        VALIDATOR_MAP.put(Long.class, (value, min, max) -> {
            long longValue = (Long) value;
            return longValue >= min && longValue <= max;
        });

        // 注册 Double 类型的校验器
        VALIDATOR_MAP.put(Double.class, (value, min, max) -> {
            double doubleValue = (Double) value;
            return doubleValue >= min && doubleValue <= max;
        });

        // 注册 Float 类型的校验器
        VALIDATOR_MAP.put(Float.class, (value, min, max) -> {
            float floatValue = (Float) value;
            return floatValue >= min && floatValue <= max;
        });
    }

    @Override
    public void initialize(FieldValidator fieldValidator) {
        this.min = fieldValidator.min();
        this.max = fieldValidator.max();
        this.notNull = fieldValidator.notNull();
    }

    @Override
    public boolean isValid(Object value, ConstraintValidatorContext context) {
        // 如果值为 null,检查是否允许为空
        if (value == null) {
            return !notNull;
        }
        // 获取值的类型
        Class<?> valueType = value.getClass();

        // 根据类型查找对应的校验器并校验
        @SuppressWarnings("unchecked") // 注册时确保了泛型类型正确, 这里强转是安全的
        FieldValidatorFunction<Object> validator = (FieldValidatorFunction<Object>) VALIDATOR_MAP.get(valueType);
        if (validator != null) {
            return validator.validate(value, min, max);
        }

        // 如果是没有注册的类型,则直接放行
        return true;
    }

  1. 字段有效性校验函数式接口

@FunctionalInterface
public interface FieldValidatorFunction<T> {

    /**
     * 校验字段值是否有效
     *
     * @param value 字段值
     * @param min   最小值
     * @param max   最大值
     * @return true or false
     */
    boolean validate(T value, int min, int max);
}

License:  CC BY 4.0