我想在我的 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>
任何不使用方面的解决方案都值得赞赏。