如上所述,只能通过@Validated
类级别的注释来指定验证组。但是,这不是很方便,因为有时您有一个包含多个方法的类,这些方法具有相同的实体作为参数,但每个方法都需要不同的属性子集来验证。这也是我的情况,您可以在下面找到解决它的几个步骤。
1) 实现自定义注释,除了@Validated
在类级别指定的组之外,还可以在方法级别指定验证组。
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface ValidatedGroups {
Class<?>[] value() default {};
}
2) 扩展MethodValidationInterceptor
和覆盖determineValidationGroups
方法如下。
@Override
protected Class<?>[] determineValidationGroups(MethodInvocation invocation) {
final Class<?>[] classLevelGroups = super.determineValidationGroups(invocation);
final ValidatedGroups validatedGroups = AnnotationUtils.findAnnotation(
invocation.getMethod(), ValidatedGroups.class);
final Class<?>[] methodLevelGroups = validatedGroups != null ? validatedGroups.value() : new Class<?>[0];
if (methodLevelGroups.length == 0) {
return classLevelGroups;
}
final int newLength = classLevelGroups.length + methodLevelGroups.length;
final Class<?>[] mergedGroups = Arrays.copyOf(classLevelGroups, newLength);
System.arraycopy(methodLevelGroups, 0, mergedGroups, classLevelGroups.length, methodLevelGroups.length);
return mergedGroups;
}
3)实现自己的MethodValidationPostProcessor
(只需复制 Spring 之一)并在方法中afterPropertiesSet
使用步骤 2 中实现的验证拦截器。
@Override
public void afterPropertiesSet() throws Exception {
Pointcut pointcut = new AnnotationMatchingPointcut(Validated.class, true);
Advice advice = (this.validator != null ? new ValidatedGroupsAwareMethodValidationInterceptor(this.validator) :
new ValidatedGroupsAwareMethodValidationInterceptor());
this.advisor = new DefaultPointcutAdvisor(pointcut, advice);
}
4)注册您的验证后处理器,而不是 Spring 之一。
<bean class="my.package.ValidatedGroupsAwareMethodValidationPostProcessor"/>
而已。现在您可以按如下方式使用它。
@Validated(groups = Group1.class)
public class MyClass {
@ValidatedGroups(Group2.class)
public myMethod1(Foo foo) { ... }
public myMethod2(Foo foo) { ... }
...
}