15.5.2 在客户端代理 JAX-WS 服务

使用 Spring 发布 Web 服务与我们使用 RMI、Hessian、Burlap 和 HTTP invoker 发布服务是有所不同的。但是我们很快就会发现,借助 Spring 使用 Web 服务所涉及的客户端代理的工作方式与基于 Spring 的客户端使用其他远程调用技术是相同的。

使用 JaxWsProxyFactoryBean,我们可以在 Spring 中装配 Spitter Web 服务,与任意一个其他的 bean 一样。JaxWsProxyFactoryBean 是 Spring 工厂 bean,它能生成一个知道如何与 SOAP Web 服务交互的代理。所创建的代理实现了服务接口(如图 15.10 所示)。因此,JaxWsProxyFactoryBean 让装配和使用一个远程 Web 服务变成了可能,就像这个远程 Web 服务是本地 POJO 一样。

我们可以像下面这样配置 JaxWsPortProxyFactoryBean 来引用 Spitter 服务:

@Bean
public JaxWsProxyFactoryBean spitterService() {
  JaxWsProxyFactoryBean proxy = new JaxWsProxyFactoryBean();
  proxy.setWsdlDocument("http://localhost:8080/services/SpitterService?wsdl");
  proxy.setServiceName("spitterService");
  proxy.setPortName("spitterServiceHttpPort");
  proxy.setServiceInterface(SpitterService.class);
  proxy.setNamespaceUrl("http://spitter.com");
  return proxy;
}

我们可以看到,为 JaxWsPortProxyFactoryBean 设置几个属性就可以工作了。wsdlDocumentUrl 属性标识了远程 Web 服务定义文件的位置。JaxWsPortProxyFactory bean 将使用这个位置上可用的 WSDL 来为服务创建代理。由 JaxWsPortProxyFactoryBean 所生成的代理实现了 serviceInterface 属性所指定的 SpitterService 接口。

剩下的三个属性的值通常可以通过查看服务的 WSDL 来确定。为了演示,我们假设为 Spitter 服务的 WSDL 如下所示:

<wsdl:definitions targetNamespace="http://spitter.com">
...
  <wsdl:service name="spitterService">
    <wsdl:port name="spitterServiceHttpPort" binding="tns:spitterServiceHttpBinding">
...
    </wsdl:port>
  </wsdl:service>
</wsdl:definitions>

虽然不太可能这么做,但是在服务的 WSDL 中定义多个服务和端口是允许的。鉴于此,JaxWsPortProxyFactoryBean 需要我们使用 portName 和 serviceName 属性指定端口和服务名称。WSDL 中 <wsdl:port> 和 <wsdl:service> 元素的 name 属性可以帮助我们识别出这些属性该设置成什么。

最后,namespaceUri 属性指定了服务的命名空间。命名空间将有助于 JaxWsPortProxyFactoryBean 去定位 WSDL 中的服务定义。正如端口和服务名一样,我们可以在 WSDL 中找到该属性的正确值。它通常会在 <wsdl:definitions> 的 targetNamespace 属性中。

Last updated