40.3. 生成 Stub 代码
概述
调用异步样式需要额外的 stub 代码,用于 SEI 中定义的专用异步方法。默认不会生成这个特殊的 stub 代码。要切换异步功能并生成必需的存根代码,您必须使用 WSDL 2.0 规范中的映射自定义功能。
自定义可让您修改 Maven 代码生成插件生成 stub 代码的方式。特别是,它可让您修改 WSDL-to-Java 映射,并切换到某些功能。在这里,自定义用于切换异步调用功能。自定义通过绑定声明来指定,您可以使用 jaxws:bindings 标签(其中 jaxws 前缀与 http://java.sun.com/xml/ns/jaxws 命名空间关联)。指定绑定声明的方法有两种:
使用外部绑定声明
例 40.2 “Asynchronous Binding Declaration 模板” 中显示切换异步调用的绑定声明文件的模板。
例 40.2. Asynchronous Binding Declaration 模板
<bindings xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
wsdlLocation="AffectedWSDL"
xmlns="http://java.sun.com/xml/ns/jaxws">
<bindings node="AffectedNode">
<enableAsyncMapping>true</enableAsyncMapping>
</bindings>
</bindings>
其中 AffectedWSDL 指定受此绑定声明影响的 WSDL 合同的 URL。AffectedNode 是一个 XPath 值,用于指定来自 WSDL 合同的节点(或节点)会受到此绑定声明的影响。如果您希望整个 WSDL 合同会受到影响,您可以将 AffectedNode 设置为 wsdl:definitions。jaxws:enableAsyncMapping 元素设为 true,以启用异步调用功能。
例如,如果您只想为 GreeterAsync 接口生成异步方法,您可以在前面的绑定声明中指定 <bindings node="wsdl:definitions/wsdl:portType[@name='GreeterAsync']">。
假设绑定声明存储在文件 async_binding.xml 中,您可以设置 POM,如 例 40.3 “消费者代码生成” 所示。
例 40.3. 消费者代码生成
<plugin>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-codegen-plugin</artifactId>
<version>${cxf.version}</version>
<executions>
<execution>
<id>generate-sources</id>
<phase>generate-sources</phase>
<configuration>
<sourceRoot>outputDir</sourceRoot>
<wsdlOptions>
<wsdlOption>
<wsdl>hello_world.wsdl</wsdl>
<extraargs>
<extraarg>-client</extraarg>
<extraarg>-b async_binding.xml</extraarg>
</extraargs>
</wsdlOption>
</wsdlOptions>
</configuration>
<goals>
<goal>wsdl2java</goal>
</goals>
</execution>
</executions>
</plugin>
-b 选项告知代码生成器在哪里可以找到外部绑定文件。
有关代码生成器的更多信息,请参阅 第 44.2 节 “cxf-codegen-plugin”。
使用嵌入式绑定声明
您还可以通过将 jaxws:bindings 元素及其关联的 jaxws:enableAsynchMapping 子部分直接嵌入到 WSDL 中,将绑定自定义直接嵌入到定义服务的 WSDL 文档中。您还必须为 jaxws 前缀添加命名空间声明。
例 40.4 “带有嵌入式绑定声明的 WSDL 用于同步映射” 显示带有嵌入式绑定声明的 WSDL 文件,该文件激活某个操作的异步映射。
例 40.4. 带有嵌入式绑定声明的 WSDL 用于同步映射
<wsdl:definitions xmlns="http://schemas.xmlsoap.org/wsdl/"
...
xmlns:jaxws="http://java.sun.com/xml/ns/jaxws"
...>
...
<wsdl:portType name="GreeterAsync">
<wsdl:operation name="greetMeSometime">
<jaxws:bindings> <jaxws:enableAsyncMapping>true</jaxws:enableAsyncMapping> </jaxws:bindings>
<wsdl:input name="greetMeSometimeRequest"
message="tns:greetMeSometimeRequest"/>
<wsdl:output name="greetMeSometimeResponse"
message="tns:greetMeSometimeResponse"/>
</wsdl:operation>
</wsdl:portType>
...
</wsdl:definitions>
将绑定声明嵌入到 WSDL 文档中时,您可以通过更改放置声明的位置来控制受声明影响的范围。当声明作为 wsdl:definitions 元素的子项放置时,代码生成器会为 WSDL 文档中定义的所有操作创建异步方法。如果它作为 wsdl:portType 元素的子级放置,则代码生成器会为接口中定义的所有操作创建异步方法。如果它作为 wsdl:operation 元素的子项放置,则代码生成器仅为该操作创建异步方法。
在使用嵌入式声明时,不需要将任何特殊选项传递给代码生成器。代码生成器将识别它们并相应地操作。
生成的接口
以这种方式生成 stub 代码后,GreeterAsync SEI (在文件 GreeterAsync.java中)定义,如 例 40.5 “带有同步调用的方法的服务端点接口” 所示。
例 40.5. 带有同步调用的方法的服务端点接口
package org.apache.hello_world_async_soap_http;
import org.apache.hello_world_async_soap_http.types.GreetMeSometimeResponse;
...
public interface GreeterAsync
{
public Future<?> greetMeSometimeAsync(
java.lang.String requestType,
AsyncHandler<GreetMeSometimeResponse> asyncHandler
);
public Response<GreetMeSometimeResponse> greetMeSometimeAsync(
java.lang.String requestType
);
public java.lang.String greetMeSometime(
java.lang.String requestType
);
}