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 registry、数据库、文件系统上的自定义位置或您选择的任何其他机制的逻辑。
以编程方式注册合同解析器
在 Apache CXF 运行时将使用您的合同解析器前,您必须将其注册到合同解析器 registry。合同解析器 registry 实施 org.apache.cxf.endpoint.ServiceContractResolverRegistry 接口。但是,您不需要实施自己的 registry。Apache CXF 在 org.apache.cxf.endpoint.ServiceContractResolverRegistryImpl
类中提供默认实现。
要将合同解析器注册到默认 registry,请执行以下操作:
- 获取对默认总线对象的引用。
-
使用总线的
getExtension ()
方法从总线获取服务合同 registry。 - 创建合同解析器的实例。
-
使用 registry 的
register ()
方法将合同解析器注册到 registry。
例 29.4 “注册合同解析器” 显示将合同解析器注册到默认 registry 的代码。
例 29.4. 注册合同解析器
BusFactory bf=BusFactory.newInstance(); Bus bus=bf.createBus(); ServiceContractResolverRegistry registry = bus.getExtension(ServiceContractResolverRegistry); JarServiceContractResolver resolver = new JarServiceContractResolver(); registry.register(resolver);
例 29.4 “注册合同解析器” 中的代码执行以下操作:
获取总线实例。
获取总线的合同解析器 registry。
创建合同解析器实例。
将合同解析器注册到 registry。
使用配置注册合同解析器
您还可以实施合同解析器,以便通过配置将其添加到客户端。合同解析器采用这样一种方式,即当运行时读取配置并实例化解析器(解析器)时,解析器会自行注册。由于运行时处理初始化,因此您可以在运行时决定客户端是否需要使用合同解析器。
要实现合同解析器,以便可以通过配置将其添加到客户端中:
-
在您的合同解析器实施中添加
init ()
方法。 -
在您的
init ()
方法中添加逻辑,以将合同解析器注册到合同解析器 registry,如 例 29.4 “注册合同解析器” 所示。 -
使用
@PostConstruct
注释拒绝init ()
方法。
例 29.5 “可使用配置注册的服务合同解析器” 显示了可以使用 配置添加到客户端中的合同解析器实施。
例 29.5. 可使用配置注册的服务合同解析器
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
元素的 class
属性是实施合同解析器的类的名称。
例 29.6 “Bean 配置合同解析器” 显示一个 bean,用于添加由 org.apache.cxf.demos.myContractResolver
类实现的配置解析器。
例 29.6. Bean 配置合同解析器
<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>
合同解析顺序
创建新代理时,运行时使用合同注册表解析器来查找远程服务的 WSDL 合同。合同解析器 registry 按照注册解析器的顺序调用每个合同解析器的 getContractLocation ()
方法。它返回从其中一个注册的合同解析器返回的第一个 URI。
如果您注册了一个在已知已知共享文件系统上解析 WSDL 合同的合同解析器,则它是唯一使用的合同解析器。但是,如果您随后注册了一个使用 UDDI 注册表解析 WSDL 位置的合同解析器,registry 就可以使用两个解析器来定位服务的 WSDL 合同。该注册表首先会尝试使用共享文件系统合同解析器查找合同。如果该合同解析器失败,registry 将尝试使用 UDDI 合同解析器查找它。