【问题标题】:Bean validation for JAX-RS sub resource with CXF使用 CXF 对 JAX-RS 子资源进行 Bean 验证
【发布时间】:2016-09-14 10:58:47
【问题描述】:

我尝试将Bean Validation 用于我的 REST API 和 Apache CXF。我阅读了Apache CXF Documentation,它适用于根资源,但不适用于sub resource locators。子资源的约束被忽略。

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 代码:

@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 配置:

<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>

我发现了以下问题:

但两者都是关于验证返回值而不是验证请求参数。

CXF in Karaf: how to configure bean validation on subresources (preferably using Blueprint)? 的问题类似,但关于 Karaf 和 Blueprint 并且不包含我的问题的解决方案。

【问题讨论】:

    标签: java jax-rs cxf bean-validation


    【解决方案1】:

    我会说自定义调用程序是要走的路。但我猜你已经根据你的评论知道了。

    <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>
    

    我在您的示例中尝试过,它有效。但我认为你需要使用ExceptionMapper,因为你没有得到适当的例外。我认为ValidationExceptionMapper 是正确的。

    编辑-根据注释更新异常映射器类

    【讨论】:

      【解决方案2】:

      我认为bean验证不会在子资源上工作,参考BeanValidationInInterceptor的源代码,由JAXRSBeanValidationInInterceptor扩展并用作验证拦截器。如果您注意到方法handleValidation,很明显验证发生在资源对象的参数上。现在,此验证发生在对资源调用实际服务方法之前(至少看起来是这样),此时,子资源实例是未知的(不存在),所以一般来说,子资源参数在这个无法验证接合点。

      我的印象是,在 CXF 中正在讨论的当前机制(拦截器)下,子资源参数可能无法以正常方式进行 bean 验证。

      您可能会采取一种解决方法,参考JAX-RS Reference,您可以尝试 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
      

      【讨论】:

        猜你喜欢
        • 2015-02-07
        • 2012-11-03
        • 1970-01-01
        • 1970-01-01
        • 2020-05-16
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-12-03
        相关资源
        最近更新 更多