根据this link :
If you need to validate entities outside of resource endpoints, the validator can be accessed in the Environment when the application is first ran.
这意味着下面的@Valid
将不起作用,我必须以编程方式使用profile
对象上的 validator 并对返回的错误进行处理:
public class ProfilesManager {
...
public void createProfile(@Valid Profile profile) {
Set<ConstraintViolation<Profile>> errors = validator.validate(profile);
...
}
}
在 Spring Boot 中,我所要做的就是用 @Validated
注释它,然后会自动抛出 ConstraintViolationException
:
@Validated
@Component
public class ProfilesManager {
public void createProfile(@Valid Profile profile) {
// if invalid, exception thrown before getting here
}
}
Dropwizard、官方或第 3 方是否有等效的解决方案?
最佳答案
使用 HK2's interception service 自己实现这一点很容易。您需要做的就是提供一个 MethodInteceptor
来检查 @Valid
注释的方法参数,并使用 Validator
验证这些参数
public class ValidationMethodInterceptor implements MethodInterceptor {
ValidatorFactory factory = Validation.buildDefaultValidatorFactory();
Validator validator = factory.getValidator();
@Override
public Object invoke(MethodInvocation invocation) throws Throwable {
Object[] args = invocation.getArguments();
for (int i = 0; i < args.length; i++) {
Parameter parameter = invocation.getMethod().getParameters()[i];
if (parameter.getAnnotation(Valid.class) != null) {
handleValidation(args[i]);
}
}
return invocation.proceed();
}
private void handleValidation(Object arg) {
Set<ConstraintViolation<Object>> constraintViolations
= validator.validate(arg);
if (!constraintViolations.isEmpty()) {
throw new IllegalArgumentException(
"constraint violations in bean argument");
}
}
}
在您的 InterceptionService
实现中,您可以决定应使用自定义 Filter
来验证哪些服务,该过滤器会在以下位置查找自定义 @Validated
注释:服务等级
public class ValidatedFilter implements Filter {
@Override
public boolean matches(Descriptor descriptor) {
try {
return Class.forName(descriptor.getImplementation())
.isAnnotationPresent(Validated.class);
} catch (ClassNotFoundException e) {
throw new RuntimeException(e);
}
}
}
public class ValidationInterceptionService implements InterceptionService {
private final static MethodInterceptor METHOD_INTERCEPTOR = new ValidationMethodInterceptor();
private final static List<MethodInterceptor> METHOD_LIST = Collections.singletonList(METHOD_INTERCEPTOR);
@Override
public Filter getDescriptorFilter() {
return new ValidatedFilter();
}
@Override
public List<MethodInterceptor> getMethodInterceptors(Method method) {
for (Parameter parameter: method.getParameters()) {
if (parameter.isAnnotationPresent(Valid.class)) {
return METHOD_LIST;
}
}
return null;
}
@Override
public List<ConstructorInterceptor> getConstructorInterceptors(Constructor<?> c) {
return null;
}
}
请参阅 this GitHub repository 中包含测试用例的完整示例.
关于java - Dropwizard 支持非资源类中的验证 (JSR-303),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50290398/