Web サービス内で Bean 検証を使用したいと考えています。最良のアプローチは、次のような Spring MVC バインディングに似ています。
@WebMethod void sayHello(@Valid HelloDTO hello) {...}
目標は、Web サービスの実装ですべての検証メソッドを取り除くことです。検証は横断的な関心事として扱いたいと思います。
私が知っているように、Hibernate Validator > 4.2 と Apache BeanValidation はメソッドパラメーターを検証できるはずです。しかし、JAX-WS メソッドのパラメーター バインディングにフックする方法がわかりません。
メッセージを傍受するハンドラーを作成しようとしましたが、パラメーターが何であるかを判断できなかったため、一般的な方法でペイロードを非整列化するのが困難でした。さらに、ハンドラーは非常に厳密な検証になります。入力パラメーターを検証するかどうかは、Web サービスの開発者に決めてもらいたいと思います。
編集:
その間、Spring AOPを使用してエンドポイントへの呼び出しを傍受するソリューションを見つけました。ただし、ハンドラーを使用したソリューションの方が優れています。これは、検証の横断的な関心事が、より適切で事前定義された場所 (ハンドラー チェーン) で定義されるためです。
これは春の解決策です:
アスペクトを作成します。
@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>
アスペクトを使用しないソリューションは高く評価されます。