3

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

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

目标是摆脱 Web 服务实现中的所有验证方法。我想将验证作为横切关注点来处理。

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

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

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

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

任何不使用方面的解决方案都值得赞赏。

4

0 回答 0