Jakarta ee 我可以用ApacheWink(JAX/RS)实现Hibernate(JSR303)方法验证吗
我目前正在研究使用hibernate验证器支持使用JSR303注释进行方法验证。最初尝试使用代理(使用cglib生成)包装资源以执行验证,但是,这似乎已经走到了死胡同,因为我尝试的代理方法似乎没有复制参数注释,因此依赖于此的资源方法最终被调用时没有参数。我现在还有一个问题要问:Jakarta ee 我可以用ApacheWink(JAX/RS)实现Hibernate(JSR303)方法验证吗,jakarta-ee,jax-rs,bean-validation,hibernate-validator,apache-wink,Jakarta Ee,Jax Rs,Bean Validation,Hibernate Validator,Apache Wink,我目前正在研究使用hibernate验证器支持使用JSR303注释进行方法验证。最初尝试使用代理(使用cglib生成)包装资源以执行验证,但是,这似乎已经走到了死胡同,因为我尝试的代理方法似乎没有复制参数注释,因此依赖于此的资源方法最终被调用时没有参数。我现在还有一个问题要问: 有没有一种替代机制可以挂接到wink的请求链中,从而在不使用代理的情况下执行类似的操作?您可以通过创建一个,并重写实际的来返回包含请求处理程序的列表,这是一种部分受支持的方法。本文将讨论此功能的配置。该请求处理程序将直
有没有一种替代机制可以挂接到wink的请求链中,从而在不使用代理的情况下执行类似的操作?您可以通过创建一个,并重写实际的来返回包含请求处理程序的列表,这是一种部分受支持的方法。本文将讨论此功能的配置。该请求处理程序将直接插入到请求处理链中,位于InvokeMethodHandler之前(InvokeMethodHandler是最后一个调用的请求处理程序,这是实际调用资源方法的请求处理程序) 在阅读源代码的基础上(它实际上调用了您的JAX/RS资源),您可以获得如下参数、实例和方法参数:
// Get Method Validator from hibernate
MethodValidator validator = Validation.byProvider(HibernateValidator.class).configure()
.buildValidatorFactory().getValidator().unwrap(
MethodValidator.class);
// Extract the method parameters, object instance and method metadata from the JAX/RS internals.
Method javaMethod = null;
Object instance = null;
Object[] parameters = null;
SearchResult searchResult = context.getAttribute(SearchResult.class);
javaMethod = searchResult.getMethod().getMetadata()
.getReflectionMethod();
parameters = searchResult.getInvocationParameters();
instance = searchResult.getResource().getInstance(context);
// Use all this to perform validation...
Set<MethodConstraintViolation<Object>> violations = validator
.validateAllParameters(instance, javaMethod, parameters);
if (!violations.isEmpty()) {
// do something with the violations here
}
//从hibernate获取方法验证程序
MethodValidator validator=Validation.byProvider(HibernateValidator.class).configure()
.buildValidatorFactory().getValidator().unwrap(
MethodValidator.class);
//从JAX/RS内部提取方法参数、对象实例和方法元数据。
方法javaMethod=null;
对象实例=null;
Object[]参数=null;
SearchResult SearchResult=context.getAttribute(SearchResult.class);
javaMethod=searchResult.getMethod().getMetadata()
.getReflectionMethod();
parameters=searchResult.getInvocationParameters();
instance=searchResult.getResource().getInstance(上下文);
//使用所有这些来执行验证。。。
设置冲突=验证程序
.validateAllParameters(实例、javaMethod、参数);
如果(!inflictions.isEmpty()){
//对这里的违规行为做点什么
}
这有点骇人听闻,因为它依赖于wink的实现细节(据我所知是未文档化的)来获取实例、参数和元数据(如果它们提供了获取此信息的公共方式,那就太好了)。但是,使用代理有点可取,因为您不会从代理发生的反射中推断出多个开销。我通过添加EJB拦截器成功地使用wink执行了bean验证。在这里,我使用Openjpa验证程序作为提供程序:
@Interceptor
public class ValidationInterceptor {
Validator validator = Validation.byProvider(ApacheValidationProvider.class).configure().buildValidatorFactory().getValidator();
@AroundInvoke
public Object validate(InvocationContext ctx) throws Exception {
Object[] parameters = ctx.getParameters();
Set<ConstraintViolation<Object>> validateResult = new HashSet<>();
for (Object parameter : parameters) {
Set<ConstraintViolation<Object>> validateParam = validator.validate(parameter);
validateResult.addAll(validateParam);
}
if (!validateResult.isEmpty()) {
throw new RestValidationException(validateResult);
}
return ctx.proceed();
}
}
@拦截器
公共类验证接收器{
Validator Validator=Validation.byProvider(ApacheValidationProvider.class).configure().buildValidatorFactory().getValidator();
@阿隆登沃克
公共对象验证(InvocationContext ctx)引发异常{
Object[]parameters=ctx.getParameters();
Set validateResult=new HashSet();
用于(对象参数:参数){
设置validateParam=validator.validate(参数);
validateResult.addAll(validateParam);
}
如果(!validateResult.isEmpty()){
抛出新的RestValidationException(validateResult);
}
返回ctx.procedure();
}
}
要输出的自定义异常:
public class RestValidationException extends WebApplicationException {
List<String> validationErrors = new ArrayList<String>();
public RestValidationException(Set<? extends ConstraintViolation<?>> violations) {
for(ConstraintViolation<?> constraintViolation : violations) {
String error = constraintViolation.getPropertyPath().toString() + ": " + constraintViolation.getMessage();
validationErrors.add(error);
}
}
@Override
public Response getResponse() {
return Response.status(Status.BAD_REQUEST).type(MediaType.APPLICATION_JSON_TYPE).entity(validationErrors).build();
}
}
公共类RestValidationException扩展WebApplicationException{
List validationErrors=new ArrayList();
公共RestValidationException(集合>冲突){
对于(ConstraintViolation ConstraintViolation:违规){
字符串错误=constraintViolation.getPropertyPath().toString()+“:”+constraintViolation.getMessage();
validationErrors.add(错误);
}
}
@凌驾
公共响应getResponse(){
返回Response.status(status.BAD_REQUEST).type(MediaType.APPLICATION_JSON_type).entity(validationErrors.build();
}
}
现在,您必须使用@Interceptors(ValidationInterceptor.class)注释REST资源,并且在进入该方法之前验证所有参数。
如果您没有使用EJB,那么可以使用cglib的MethodInterceptor拦截它(Spring可以在这里提供帮助)