使用 CXF 对 JAX-RS 子资源进行 Bean 验证
Bean validation for JAX-RS sub resource with CXF
我尝试使用Bean Validation for my REST API with Apache CXF. I read Apache CXF Documentation and it works fine for root resources, but it doesn't work with 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>
我发现了以下问题:
但两者都是关于 return 值的验证,而不是关于请求参数的验证。
问题 CXF in Karaf: how to configure bean validation on subresources (preferably using Blueprint)? 很相似,但是关于 Karaf 和 Blueprint 并且没有包含我的问题的解决方案。
我认为bean 验证不会对子资源起作用,请参阅BeanValidationInInterceptor
的源代码,它由JAXRSBeanValidationInInterceptor
扩展并用作验证拦截器。如果您注意到方法 handleValidation
,则很明显验证发生在资源对象的参数上。现在,这种验证发生在对资源调用实际服务方法之前(至少看起来是这样),此时,子资源实例是未知的(不存在),所以一般来说,子资源参数在这个接合点无法验证。
我的印象是,根据正在讨论的 CXF 中的当前机制(拦截器),子资源参数可能无法以正常方式进行 bean 验证。
您可能会采取一种解决方法,参考 JAX-RS Reference,您可以尝试对参数进行 bean 验证(特别是如果它是一个请求 JSON),即手动实例化一个验证器对象然后验证它,例如
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
我会说自定义调用程序是可行的方法。但我猜你已经根据你的评论知道了。
<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
是正确的。
编辑 - 根据评论
更新了异常映射器class
我尝试使用Bean Validation for my REST API with Apache CXF. I read Apache CXF Documentation and it works fine for root resources, but it doesn't work with 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>
我发现了以下问题:
但两者都是关于 return 值的验证,而不是关于请求参数的验证。
问题 CXF in Karaf: how to configure bean validation on subresources (preferably using Blueprint)? 很相似,但是关于 Karaf 和 Blueprint 并且没有包含我的问题的解决方案。
我认为bean 验证不会对子资源起作用,请参阅BeanValidationInInterceptor
的源代码,它由JAXRSBeanValidationInInterceptor
扩展并用作验证拦截器。如果您注意到方法 handleValidation
,则很明显验证发生在资源对象的参数上。现在,这种验证发生在对资源调用实际服务方法之前(至少看起来是这样),此时,子资源实例是未知的(不存在),所以一般来说,子资源参数在这个接合点无法验证。
我的印象是,根据正在讨论的 CXF 中的当前机制(拦截器),子资源参数可能无法以正常方式进行 bean 验证。
您可能会采取一种解决方法,参考 JAX-RS Reference,您可以尝试对参数进行 bean 验证(特别是如果它是一个请求 JSON),即手动实例化一个验证器对象然后验证它,例如
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
我会说自定义调用程序是可行的方法。但我猜你已经根据你的评论知道了。
<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
是正确的。
编辑 - 根据评论
更新了异常映射器class