2016-09-14 93 views
3

我嘗試將Bean Validation用於具有Apache CXF的REST API。我讀Apache CXF Documentation,它對根資源很好,但它不適用於sub resource locators。子資源的約束被忽略。使用CXF進行JAX-RS子資源的Bean驗證

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)?是類似的,但關於卡拉夫和藍圖,並不包含我的問題的解決方案。

回答

2

我會說自定義調用者是要走的路。但我想你已經知道這是根據你的評論。

<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將是正確的。

編輯 - 基於評論更新的異常映射器類

1

我不認爲bean驗證將在子資源上工作,請參閱BeanValidationInInterceptor的源代碼,該代碼被JAXRSBeanValidationInInterceptor擴展並用作驗證攔截器。如果您注意到方法handleValidation,則顯然驗證發生在資源對象的參數上。現在,這個驗證發生在資源上調用實際的服務方法之前(至少它看起來如此),並且此時子資源實例是未知的(不存在),因此通常這個子資源參數關口無法驗證。

我的印象是,在討論CXF中的當前機制(攔截器)時,子資源參數可能無法以正常方式進行bean驗證。您可以嘗試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 
相關問題