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
相关产品推荐
相关产品推荐

