简体   繁体   English

使用CXF对JAX-RS子资源进行Bean验证

[英]Bean validation for JAX-RS sub resource with CXF

I try to use Bean Validation for my REST API with Apache CXF. 我尝试将Bean Validation用于我的REST API与Apache CXF。 I read Apache CXF Documentation and it works fine for root resources, but it doesn't work with sub resource locators . 我阅读了Apache CXF文档 ,它适用于根资源,但它不适用于子资源定位器 The constraints are ignored for sub resources. 子资源会忽略约束。

Maven dependencies: Maven依赖:

<dependency>
    <groupId>org.apache.cxf</groupId>
    <artifactId>cxf-rt-frontend-jaxrs</artifactId>
    <version>3.1.5</version>
</dependency>
<dependency>
    <groupId>javax.validation</groupId>
    <artifactId>validation-api</artifactId>
    <version>1.1.0.Final</version>
</dependency>
<dependency>
    <groupId>org.apache.bval</groupId>
    <artifactId>bval-jsr</artifactId>
    <version>1.1.0</version>
</dependency>

Java code: Java代码:

@Named
@Path("test")
public class TestResource {

    @Inject
    private TestSubResource subResource;

    @Path("sub")
    public TestSubResource getSubResource() {
        return subResource;
    }

    @GET
    public void find(@NotNull @QueryParam("value") String value) {
    }
}

@Named
public class TestSubResource {

    @GET
    public void find(@NotNull @QueryParam("value") String value) {
    }
}

CXF configuration: CXF配置:

<bean id="validationProvider" class="org.apache.cxf.validation.BeanValidationProvider" />
<bean id="validationInInterceptor" class="org.apache.cxf.jaxrs.validation.JAXRSBeanValidationInInterceptor">
    <property name="provider" ref="validationProvider" />
</bean>
<jaxrs:server address="/rest" id="test" staticSubresourceResolution="true">
    <jaxrs:serviceBeans>
        <ref bean="testResource" />
    </jaxrs:serviceBeans>
    <jaxrs:inInterceptors>
        <ref bean="validationInInterceptor" />
    </jaxrs:inInterceptors> 
</jaxrs:server>

I found following issues: 我发现了以下问题:

but both are about validation of return value not about validation of request parameters. 但两者都是关于返回值的验证,而不是关于请求参数的验证。

The question CXF in Karaf: how to configure bean validation on subresources (preferably using Blueprint)? Karaf中的问题CXF:如何在子资源上配置bean验证(最好使用Blueprint)? is similar, but about Karaf and Blueprint and contains no solution for my question. 是类似的,但关于卡拉夫和蓝图,并没有解决我的问题。

I would say custom invoker is the way to go. 我会说自定义调用程序是要走的路。 But I guess you already knew that based on your comment. 但我想你已经根据你的评论知道了。

<bean id="validationProvider" class="org.apache.cxf.validation.BeanValidationProvider" />
<bean id="validationInInterceptor"
    class="org.apache.cxf.jaxrs.validation.JAXRSBeanValidationInInterceptor">
    <property name="provider" ref="validationProvider" />
</bean>
<bean id="validationInvoker" class="org.apache.cxf.jaxrs.validation.JAXRSBeanValidationInvoker"></bean>

<jaxrs:server address="/rest" id="test"
    staticSubresourceResolution="true">
    <jaxrs:serviceBeans>
        <ref bean="testResource" />
    </jaxrs:serviceBeans>
    <jaxrs:inInterceptors>
        <ref bean="validationInInterceptor" />
    </jaxrs:inInterceptors>
    <jaxrs:invoker>
        <ref bean="validationInvoker" />
    </jaxrs:invoker>
</jaxrs:server>

I tried that on your example, and it works. 我在你的例子上尝试过,它确实有效。 But I think you need to use an ExceptionMapper , as you don't get proper exceptions. 但我认为你需要使用ExceptionMapper ,因为你没有得到适当的例外。 I think ValidationExceptionMapper would be the right one. 我认为ValidationExceptionMapper是正确的。

Edit- Updated exception mapper class based on comment 编辑 - 基于注释更新了异常映射器类

I don't think bean validation will work on the subresource, refer to the source code for BeanValidationInInterceptor , which is extended by JAXRSBeanValidationInInterceptor and is used as the validation interceptor. 我认为bean验证不会BeanValidationInInterceptor资源起作用,请参考BeanValidationInInterceptor的源代码,它由JAXRSBeanValidationInInterceptor扩展并用作验证拦截器。 If you notice the method handleValidation , it is clear that the validation happens on the arguments of the resource object. 如果您注意到方法handleValidation ,则很明显验证发生在资源对象的参数上。 Now, this validation is happening before the actual service method is invoked on the resource (that's how it is looking at least) and at this time, the subresource instance is not known (does not exist), so in general, subresource parameters at this juncture cannot be validated. 现在,这个验证是在资源上调用实际服务方法之前发生的(至少它是如何查看的),此时,子资源实例是未知的(不存在),所以一般来说,这里的子资源参数关节无法验证。

My impression is that with the current mechanism in CXF under discussion (interceptor), subresource parameters probably cannot be bean validated in the normal way. 我的印象是,在CXF正在讨论的当前机制(拦截器)中,子资源参数可能无法以正常方式进行bean验证。

You could probably take a workaround, with reference to the JAX-RS Reference , you could try to bean validate the parameter (especially if it is a request JSON), manually ie instantiate a Validator object and then validate it with that eg 你可以采取一种解决方法,参考JAX-RS参考 ,你可以尝试bean验证参数(特别是如果它是一个请求JSON),手动即实例化Validator对象,然后用它验证它,例如

package validator;

import java.util.Set;

import javax.validation.ConstraintViolation;
import javax.validation.Validation;
import javax.validation.Validator;
import javax.validation.ValidatorFactory;
import javax.validation.constraints.Max;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Pattern;

import org.apache.bval.jsr303.ApacheValidationProvider;

public class DataBean {

    @Max(10)
    public int x = 0;

    @Pattern(regexp= "this_string")
    public String y =  "this_string"; // also matches null

    public static void main(String[] args) {

        ValidatorFactory avf =
            Validation.byProvider(ApacheValidationProvider.class).configure().buildValidatorFactory();

        DataBean bean = new DataBean();
        Validator validator = avf.getValidator();

        Set<ConstraintViolation<DataBean>> violations = validator.validate(bean);

        System.out.println(violations);
    }

} // calss closing

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM