You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spring Validation自定义模式:从配置文件加载正则校验DTO字段

没问题,我来帮你把这个从配置文件加载正则的自定义校验逻辑补全!先理清楚整个流程,我们一步步来:

第一步:先确认你的@CustomPattern注解定义

首先得确保你的自定义注解能正确携带配置文件的key和错误提示,比如:

@Target(ElementType.FIELD) // 标注在DTO字段上
@Retention(RetentionPolicy.RUNTIME) // 运行时可见,方便反射读取
public @interface CustomPattern {
    // 配置文件中对应正则表达式的key
    String regexKey();
    // 校验失败时的提示消息,默认值可选
    String message() default "字段格式不符合要求";
}
第二步:完善AOP的校验方法

你原代码的切点表达式需要调整——因为@CustomPattern是标注在DTO字段上的,不是方法上,所以AOP要拦截的是接收DTO参数的业务方法(比如Controller的接口方法),然后在方法执行前校验参数里的DTO字段。下面是补全后的代码:

@Component
@Aspect
public class CustomerValidationAdvice {

    // 注入配置文件读取工具,比如Spring的Environment
    @Autowired
    private Environment applicationProps;

    // 切点:拦截所有Controller的方法(你可以根据自己的需求调整,比如指定包路径)
    @Before("execution(* com.yourteam.yourproject.controller.*.*(..))")
    public void validateWithPropertyFileValue(JoinPoint joinPoint) throws Throwable {
        // 1. 获取方法的所有入参
        Object[] methodArgs = joinPoint.getArgs();
        if (methodArgs == null || methodArgs.length == 0) {
            return;
        }

        // 2. 遍历每个参数,处理带@CustomPattern注解的字段
        for (Object arg : methodArgs) {
            if (arg == null) continue;

            // 获取当前参数类的所有字段(包括私有字段)
            Field[] fields = arg.getClass().getDeclaredFields();
            for (Field field : fields) {
                // 检查字段是否标注了@CustomPattern
                CustomPattern customPattern = field.getAnnotation(CustomPattern.class);
                if (customPattern == null) continue;

                // 3. 从配置文件读取对应的正则表达式
                String regexKey = customPattern.regexKey();
                String regex = applicationProps.getProperty(regexKey);
                if (regex == null || regex.isBlank()) {
                    throw new IllegalArgumentException("配置文件未找到正则表达式配置项:" + regexKey);
                }

                // 4. 读取字段的值(因为字段是private,需要开启可访问权限)
                field.setAccessible(true);
                Object fieldValue = field.get(arg);

                // 5. 校验逻辑:如果字段值不为空,就用正则匹配
                if (fieldValue != null) {
                    String valueStr = fieldValue.toString();
                    if (!valueStr.matches(regex)) {
                        // 抛出和原生校验一致的异常,方便全局统一处理
                        Set<ConstraintViolation<?>> violations = new HashSet<>();
                        violations.add(new ConstraintViolationImpl<>(
                                customPattern.message(),
                                null, null, null, null,
                                fieldValue, null, null
                        ));
                        throw new ConstraintViolationException(violations, customPattern.message());
                    }
                }
            }
        }
    }
}
几个关键细节说明
  • 切点调整:我这里用的是拦截Controller的方法,你可以根据实际需求修改,比如只拦截特定包下的服务层方法,或者用自定义注解标注需要校验的方法,再用@annotation()作为切点。
  • 配置读取:这里用了Spring的Environment来读取配置,如果你用的是@ConfigurationProperties绑定的配置类,直接注入对应的Bean就行。
  • 异常处理:抛出ConstraintViolationException是为了和JSR380原生的@Pattern等校验异常保持一致,这样你可以用全局异常处理器统一捕获返回错误信息。
  • 字段访问:因为DTO的字段一般是private的,所以必须调用field.setAccessible(true)才能读取值,校验完后可以再设置为false(不过AOP方法执行完后字段的可访问性会自动恢复,也可以不用管)。
使用示例

在你的DTO字段上标注注解:

public class CustomerDTO {
    @CustomPattern(regexKey = "customer.phone.regex", message = "手机号格式不正确")
    private String phone;

    @CustomPattern(regexKey = "customer.idcard.regex", message = "身份证号格式不正确")
    private String idCard;

    // 其他字段、getter/setter省略
}

在配置文件(比如application.properties)里添加正则配置:

customer.phone.regex=^1[3-9]\\d{9}$
customer.idcard.regex=^[1-9]\\d{5}(18|19|20)\\d{2}((0[1-9])|(1[0-2]))(([0-2][1-9])|10|20|30|31)\\d{3}[0-9Xx]$

这样,只要Controller的方法接收CustomerDTO参数,AOP就会自动校验标注了@CustomPattern的字段,用配置文件里的正则做校验。

内容的提问来源于stack exchange,提问作者mavriksc

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.25 06:32:22