29.4. 使用合同解析器
概述
在运行时解析 WSDL 文档位置的最涉及机制是实施您自己的自定义合同解析器。这要求您提供 Apache CXF 特定 ServiceContractResolver 接口的实现。您还需要使用总线注册自定义解析器。
注册正确注册后,将使用自定义合同解析器来解决所需的 WSDL 和架构文档的位置。
实施合同解析器
合同解析器是 org.apache.cxf.endpoint.ServiceContractResolver 接口的实现。如 例 29.3 “ServiceContractResolver Interface” 所示,此界面具有单一方法 getContractLocation ()
,需要实施该界面。getContractLocation ()
采用服务的 QName,并返回服务的 WSDL 合同的 URI。
例 29.3. ServiceContractResolver Interface
public interface ServiceContractResolver { URI getContractLocation(QName qname); }
解决 WSDL 合同位置的逻辑是特定于应用程序。您可以添加从 UDDI 注册表、数据库、文件系统上自定义位置或您选择的任何其他机制解析合同位置的逻辑。
以编程方式注册合同解析器
在 Apache CXF 运行时将使用合同解析器之前,您必须使用合同解析器 registry 注册。合同解析器 registry 实施 org.apache.cxf.endpoint.ServiceContractResolverRegistry 接口。但是,您不需要实施自己的 registry。Apache CXF 在 org.apache.cxf.endpoint.ServiceContractResolverRegistryImpl
类中提供默认实现。
使用您进行的默认 registry 注册合同解析器:
- 获取对默认总线对象的引用。
-
使用总线的
getExtension ()
方法从总线获取服务合同 registry。 - 创建合同解析器实例。
-
使用 registry 的
register ()
方法将合同解析器注册到注册表。
例 29.4 “注册合同 Resolver” 显示用于将合同解析器注册到默认注册表的代码。
例 29.4. 注册合同 Resolver
BusFactory bf=BusFactory.newInstance(); Bus bus=bf.createBus(); ServiceContractResolverRegistry registry = bus.getExtension(ServiceContractResolverRegistry); JarServiceContractResolver resolver = new JarServiceContractResolver(); registry.register(resolver);
例 29.4 “注册合同 Resolver” 中的代码执行以下操作:
获取总线实例。
获取总线合同解析器 registry。
创建合同解析器的实例。
使用 registry 注册合同解析器。
使用配置注册合同解析器
您也可以实施合同解析器,以便通过配置将其添加到客户端。合同解析器通过实现,从而使运行时读取配置并实例化解析器(解析器注册自身)的方法。由于运行时处理初始化,因此如果客户端需要使用合同解析器,您可以在运行时决定。
要实现合同解析器,请通过配置将其添加到客户端:
-
在您的合同解析器实施中添加
init ()
方法。 -
在您的
init ()
方法中添加逻辑,它使用合同解析器 registry 注册合同解析器,如 例 29.4 “注册合同 Resolver” 所示。 -
使用
@PostConstruct
注释声明init ()
方法。
例 29.5 “可以使用配置注册的 service Contract Resolver” 显示可以使用配置向客户端添加合同解析器实施。
例 29.5. 可以使用配置注册的 service Contract Resolver
import javax.annotation.PostConstruct; import javax.annotation.Resource; import javax.xml.namespace.QName; import org.apache.cxf.Bus; import org.apache.cxf.BusFactory; public class UddiResolver implements ServiceContractResolver { private Bus bus; ... @PostConstruct public void init() { BusFactory bf=BusFactory.newInstance(); Bus bus=bf.createBus(); if (null != bus) { ServiceContractResolverRegistry resolverRegistry = bus.getExtension(ServiceContractResolverRegistry.class); if (resolverRegistry != null) { resolverRegistry.register(this); } } } public URI getContractLocation(QName serviceName) { ... } }
要将合同解析器注册到客户端,您需要向客户端配置添加一个 bean
元素。bean
元素 的类
属性是实施合同解析器的类的名称。
例 29.6 “配置合同 Resolver” 显示用于添加由 org.apache.cxf.demos.myContractResolver
类实施的配置解析器的 bean。
例 29.6. 配置合同 Resolver
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> ... <bean id="myResolver" class="org.apache.cxf.demos.myContractResolver" /> ... </beans>
合同解析顺序
当创建新代理时,运行时使用合同 registry 解析器来查找远程服务的 WSDL 合同。合同解析器 registry 调用每个合同解析器的 getContractLocation ()
方法。它会返回从其中一个注册合同解析器返回的第一个 URI。
如果您注册了一个试图在已知共享文件系统中解决 WSDL 合同的合同解析器,则会使用它的唯一合同解析器。但是,如果您随后使用 UDDI 注册表来注册一个可解析 WSDL 位置的合同解析器,注册表可以使用两个解析器来查找服务的 WSDL 合同。注册表将首先尝试使用共享文件系统合同解析器查找合同。如果该合同解析器失败,registry 会尝试使用 UDDI 合同解析器查找它。