java注解实现对参数的校验

基本思想也比较简单,就是基于反射来实现对模型中参数的校验

定义注解
/**
 * @Author: feifei
 * @Date: 2023/02/13/10:44 上午
 * @Description:
 */
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD, ElementType.PARAMETER})
public @interface ValidateFei {
    /**
     * 小数位数 >0
     */
    int digit() default 0;

    /**
     * @see {@link BigDecimal} Number舍入模式ROUND_*
     */
    int round() default BigDecimal.ROUND_HALF_UP;

    /**
     * null时设置默认值
     */
    String defValue() default "null";

    /**
     * 是否可以为空
     */
    boolean nullable() default true;

    /**
     * 自定义异常说明
     *
     * @return
     */
    String nullableDesc() default "";

    /**
     * 最大长度
     */
    int maxLength() default 0;

    String maxLengthDesc() default "";

    /**
     * 最小长度
     */
    int minLength() default 0;

    String minLengthDesc() default "";

    /**
     * 中文最大长度
     */
    int maxChineseLenghth() default 0;

    String maxChineseLenghthDesc() default "";


    /**
     * 中文最小长度
     */
    int minChineseLength() default 0;

    String minChineseLengthDesc() default "";


    /**
     * Number 金额不为0
     */
    boolean notZero() default false;

    String notZeroDesc() default "";


    /**
     * @see {@link RegexTypeEnum} 提供几种常用的正则验证
     */
    RegexTypeEnum regexType() default RegexTypeEnum.NONE;

    String regexTypeDesc() default "";


    /**
     * 自定义正则验证
     */
    String regexExpression() default "";

    String regexExpressionDesc() default "";

    /**
     * 参数或者字段描述,这样能够显示友好的异常信息
     */
    String description() default "";

    /**
     * 集合非空
     */
    boolean notEmpty() default false;

    /**
     * 对象非null
     */
    boolean notNull() default false;

    /**
     * 字符串非空
     */
    boolean notBlank() default false;
}

同时附上基本正则校验规则的枚举

public enum RegexTypeEnum {
    NONE,
    SPECIAL_CHAR,
    CHINESE,
    EMAIL,
    IP,
    NUMBER,
    PHONE_NUMBER;

    private RegexTypeEnum() {
    }
}
定义校验工具类
/**
 * @Author: feifei
 * @Date: 2023/02/13/10:44 上午
 * @Description:
 */
public class ValidateFeiUtils {
    /**
     *
     * @param object 要被校验的对象
     * @throws Exception
     */
    public static void valid(Object object) throws  Exception {
        // 获取object的类型
        Class<? extends Object> clazz = object.getClass();
        // 获取该类型声明的成员
        Field[] fields = clazz.getDeclaredFields();
        //循环遍历对象中的属性
        for (Field field : fields) {
            // 获取对象的成员的注解信息
            ValidateFei validator = field.getAnnotation(ValidateFei.class);
            if (validator == null) {
                continue;
            }
            if (!field.isAccessible()) {
                field.setAccessible(true);
            }
            Object value = field.get(object);
            validField(value, validator, field, object);
        }
    }

    private static void validField(Object value, ValidateFei validator, Field field, Object object) throws  Exception {
        /*************注解解析工作开始******************/
        setAmountDigit(value, validator, field, object);

        setDefaultValue(value, validator, field, object);

        String description;
        if (StringUtil.isBlank(validator.description())) {
            description = field.getName();
        } else {
            description = validator.description();
        }

        validateNullable(description, value, validator);

        validateNotEmpty(description,value,validator);

        validateNotNull(description,value,validator);

        validateNotBlank(description,value,validator);

        validateNotZero(description, value, validator);

        validateLength(description, value, validator);

        validateRegexType(description, value, validator);

        validateRegexExpression(description, value, validator);
        /*************注解解析工作结束******************/
    }
    private static void setAmountDigit(Object value, ValidateFei validator, Field field, Object object) throws IllegalAccessException {
        if (value != null && validator.digit() > 0 && value instanceof BigDecimal) {
            field.set(object, ((BigDecimal) value).setScale(validator.digit(), validator.round()));
        }
    }

    private static void setDefaultValue(Object value, ValidateFei validator, Field field, Object object) throws ParseException, IllegalAccessException {
        if (value == null && !"null".equals(validator.defValue())) {
            // 获取POJO中属性为null的默认值
            Object defaultValue = getDefaultValue(field.getType(), validator.defValue());
            if (defaultValue != null) {
                field.set(object, defaultValue);
            }
        }
    }

    private static Object getDefaultValue(Class<?> type, String value) throws ParseException {
        if (type == Long.class) {
            return Long.valueOf(value);
        }
        if (type == Byte.class) {
            return Byte.valueOf(value);
        }
        if (type == BigDecimal.class) {
            return new BigDecimal(value);
        }
        if (type == Date.class) {
            return DateUtil.parse(value);
        }
        if (type == String.class) {
            return value;
        }
        return null;
    }

    private static void validateNullable(String description, Object value, ValidateFei validator) {
        if (validator.nullable()) {
            return;
        }
        if (StringUtils.isNotBlank(validator.nullableDesc())) {
            description = validator.nullableDesc();
        } else {
            description = description + "不能为空";
        }
        if(value instanceof java.util.List &&
                CollectionUtils.isEmpty((Collection<?>) value)){
            throw new IllegalArgumentException(description);
        }
        if (value == null) {
            throw new IllegalArgumentException(description);
        }
        if (value instanceof String && StringUtils.isBlank(value.toString())) {
            throw new IllegalArgumentException(description);
        }
    }

    private static void validateNotEmpty(String description, Object value, ValidateFei validator){
        if (!validator.notEmpty()) {
            return;
        }
        if (StringUtils.isNotBlank(validator.description())) {
            description = validator.description();
        } else {
            description = description + "不能为空";
        }
        if (value == null) {
            throw new IllegalArgumentException(description);
        }
        if(value instanceof Collection && CollectionUtils.isEmpty((Collection<?>) value)){
            throw new IllegalArgumentException(description);
        }
    }

    private static void validateNotNull(String description, Object value, ValidateFei validator){
        if (!validator.notNull()) {
            return;
        }
        if (StringUtils.isNotBlank(validator.description())) {
            description = validator.description();
        } else {
            description = description + "不能为空";
        }
        if (value == null) {
            throw new IllegalArgumentException(description);
        }
    }

    private static void validateNotBlank(String description, Object value, ValidateFei validator){
        if (!validator.notBlank()) {
            return;
        }
        if (StringUtils.isNotBlank(validator.description())) {
            description = validator.description();
        } else {
            description = description + "不能为空";
        }
        if (value == null) {
            throw new IllegalArgumentException(description);
        }
        if(value instanceof String && StringUtils.isBlank((String) value)){
            throw new IllegalArgumentException(description);
        }
    }

    private static void validateNotZero(String description, Object value, ValidateFei validator) {
        if (!validator.notZero()) {
            return;
        }
        if (value instanceof Number) {
            if (((Number) value).doubleValue() == 0) {
                if (StringUtils.isNotBlank(validator.notZeroDesc())) {
                    throw new IllegalArgumentException(validator.notZeroDesc());
                }
                throw new IllegalArgumentException(description + "不能为0");
            }
        }
    }

    private static void validateLength(String description, Object value, ValidateFei validator) {
        if (value != null && validator.maxLength() != 0 && value.toString().length() > validator.maxLength()) {
            if (StringUtils.isNotBlank(validator.maxLengthDesc())) {
                throw new IllegalArgumentException(validator.maxLengthDesc());
            }
            throw new IllegalArgumentException(description + "长度不能超过" + validator.maxLength());
        }
        if (value != null && validator.maxChineseLenghth() != 0 && ChineseCheckUtil.getChineseLength(value.toString()) > validator.maxChineseLenghth()) {
            if (StringUtils.isNotBlank(validator.maxChineseLenghthDesc())) {
                throw new IllegalArgumentException(validator.maxChineseLenghthDesc());
            }
            throw new IllegalArgumentException(description + "中文长度不能超过" + validator.maxChineseLenghth());
        }
        if (value != null && validator.minLength() != 0 && value.toString().length() < validator.minLength()) {
            if (StringUtils.isNotBlank(validator.minLengthDesc())) {
                throw new IllegalArgumentException(validator.minLengthDesc());
            }
            throw new IllegalArgumentException(description + "长度不能小于" + validator.minLength());
        }
        if (value != null && validator.minChineseLength() != 0 && ChineseCheckUtil.getChineseLength(value.toString()) < validator.minChineseLength()) {
            if (StringUtils.isNotBlank(validator.minChineseLengthDesc())) {
                throw new IllegalArgumentException(validator.minChineseLengthDesc());
            }
            throw new IllegalArgumentException(description + "中文长度不能小于" + validator.minChineseLength());
        }
    }

    private static void validateRegexType(String description, Object value, ValidateFei validator) {
        if (value == null || validator.regexType() == RegexTypeEnum.NONE) {
            return;
        }
        switch (validator.regexType()) {
            case NONE:
                break;
            case SPECIAL_CHAR:
                if (RegexUtils.hasSpecialChar(value.toString())) {
                    if (StringUtils.isNotBlank(validator.regexTypeDesc())) {
                        throw new IllegalArgumentException(validator.regexTypeDesc());
                    }
                    throw new IllegalArgumentException(description + "不能含有特殊字符");
                }
                break;
            case CHINESE:
                if (RegexUtils.isChinese2(value.toString())) {
                    if (StringUtils.isNotBlank(validator.regexTypeDesc())) {
                        throw new IllegalArgumentException(validator.regexTypeDesc());
                    }
                    throw new IllegalArgumentException(description + "不能含有中文字符");
                }
                break;
            case EMAIL:
                if (!RegexUtils.isEmail(value.toString())) {
                    if (StringUtils.isNotBlank(validator.regexTypeDesc())) {
                        throw new IllegalArgumentException(validator.regexTypeDesc());
                    }
                    throw new IllegalArgumentException(description + "地址格式不正确");
                }
                break;
            case IP:
                if (!RegexUtils.isIp(value.toString())) {
                    if (StringUtils.isNotBlank(validator.regexTypeDesc())) {
                        throw new IllegalArgumentException(validator.regexTypeDesc());
                    }
                    throw new IllegalArgumentException(description + "地址格式不正确");
                }
                break;
            case NUMBER:
                if (!RegexUtils.isNumber(value.toString())) {
                    if (StringUtils.isNotBlank(validator.regexTypeDesc())) {
                        throw new IllegalArgumentException(validator.regexTypeDesc());
                    }
                    throw new IllegalArgumentException(description + "不是数字");
                }
                break;
            case PHONE_NUMBER:
                if (!RegexUtils.isPhoneNumber(value.toString())) {
                    if (StringUtils.isNotBlank(validator.regexTypeDesc())) {
                        throw new IllegalArgumentException(validator.regexTypeDesc());
                    }
                    throw new IllegalArgumentException(description + "格式不正确");
                }
                break;
            default:
                break;
        }
    }

    private static void validateRegexExpression(String description, Object value, ValidateFei validator) {
        if (StringUtil.isBlank(validator.regexExpression())) {
            return;
        }
        if (value != null && !value.toString().matches(validator.regexExpression())) {
            if (StringUtils.isNotBlank(validator.regexExpressionDesc())) {
                throw new IllegalArgumentException(validator.regexExpressionDesc());
            }
            throw new IllegalArgumentException(description + "格式不正确");
        }
    }
}
基本测试

测试的model定义

/**
 * @Author: feifei
 * @Date: 2023/02/13/11:00 上午
 * @Description:
 */
@Data
@AllArgsConstructor
@NoArgsConstructor
public class TestModel {
    @ValidateFei(notEmpty = true,description = "姓名集合")
    private List<String> nameList;
    @ValidateFei(regexType = RegexTypeEnum.PHONE_NUMBER,description = "手机号码")
    private String number;
}

测试的main方法

/**
 * @Author: feifei
 * @Date: 2023/02/13/11:02 上午
 * @Description:
 */
public class Test {
    public static void main(String[] args) throws  Exception {
        TestModel testModel = new TestModel();
        testModel.setNumber("13279930454");
        ValidateFeiUtils.valid(testModel);
    }
}

至此结束,同样的可以自己添加适合自己业务需求的校验规则

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Quare_feifei

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值