如何在JAX-WS WebMethod上使用JSR-303 Bean验证?

时间:2013-03-05 12:17:44

标签: jax-ws bean-validation

我想在我的Web服务中使用bean验证。最好的方法类似于这样的Spring MVC绑定:

@WebMethod void sayHello(@Valid HelloDTO hello) {...}

目标是摆脱Web服务实现中的所有验证方法。我想将验证作为一个跨领域的问题处理。

据我所知,Hibernate Validator> 4.2以及Apache BeanValidation应该能够验证方法参数。但我不知道如何挂钩JAX-WS方法参数绑定。

我试图编写一个拦截消息的处理程序,但是我有一些困难以一般方式解组有效负载,因为我无法确定参数是什么。此外,处理程序将是一个非常严格的验证。我想让Web服务的开发人员决定是否要验证输入参数。

修改
与此同时,我找到了一个使用Spring AOP来拦截对端点的调用的解决方案。但是,使用Handler的解决方案会更好,因为验证的交叉关注点将在更好的预定义位置定义:处理程序链。

这是Spring解决方案:

创建一个方面:

@Aspect
public class ValidationAspect {
    @Autowired private Validator validator;

    // Alternative: use @annotation(javax.validation.Valid) to validate only methods annotated with @Valid
    @Pointcut("execution(* (@javax.jws.WebService *).*(..))")
    public void webServiceWebMethods() {}

    @Before("webServiceWebMethods()")
    public void validateWebService(JoinPoint jp) throws WebParamValidationFault {
        for (Object arg : jp.getArgs()) {
            Collection<ConstraintViolation<Object>> errors = validator.validate(arg);
            // check validation and throw exception if errors occured
        }
    }

配置Spring-AOP:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd">

    <aop:aspectj-autoproxy proxy-target-class="true" />
    <bean id="validator" class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean" />
    <bean id="validationAspect" class="ValidationAspect" />
</beans>

proxy-target-class="true"将启用cglib代理。这是必要的,因为JAX-WS运行时无法使用Web服务的JDK动态代理。原因是,@WebService不可继承,代理声明缺少注释。解决方案是使用cglib 声明Web服务Spring绑定的实现类:

<wss:binding url="/demo">
    <wss:service>
        <ws:service bean="#DemoEndpoint" impl="com.example.DemoEndpoint" />
    </wss:service>
</wss:binding>

任何不使用方面的解决方案都表示赞赏。

0 个答案:

没有答案