杰瑞科技汇

Java如何根据WSDL生成客户端代码?

下面我将为你详细介绍几种主流的方法,从最经典到最现代,并提供完整的步骤和示例。

核心概念

  • WSDL (Web Services Description Language): 一个 XML 文件,它描述了 Web 服务的功能、位置、如何调用它(协议、数据格式等),你可以把它理解为 Web 服务的“说明书”。
  • 客户端代码: 生成的 Java 类,包含了与服务交互所需的所有逻辑,包括网络请求、数据序列化/反序列化等。
  • SOAP (Simple Object Access Protocol): WSDL 通常与 SOAP 协议相关联,SOAP 是一种基于 XML 的协议,用于在 Web 上交换结构化信息。

使用 wsimport (JDK 内置工具)

这是最经典、最官方的方法。wsimport 是 Java Development Kit (JDK) 自带的一个命令行工具,它基于 JAX-WS (Java API for XML Web Services) 规范。

优点

  • 无需安装额外工具,随 JDK 一起提供。
  • 是 JAX-WS 规范的参考实现,稳定可靠。

缺点

  • 命令行工具,需要手动执行。
  • 生成的代码有时可能比较“冗余”或不够现代化。

详细步骤

准备工作 确保你已经安装了 JDK,JAVA_HOME 环境变量配置正确,打开命令行工具(如 Windows 的 CMD 或 PowerShell,macOS/Linux 的 Terminal)。

找到 WSDL 文件 WSDL 文件通常是一个 URL 或者一个本地文件路径,这里我们以一个公共的 WSDL 服务为例: http://wsf.cdyne.com/WeatherWS/Weather.asmx?wsdl

运行 wsimport 命令 打开命令行,进入你希望生成代码的目录(D:\my-project\src),然后执行以下命令:

# 基本语法
wsimport -p <生成的包名> -keep <wsdl文件路径或URL>
# 示例
wsimport -p com.example.weather.client -keep http://wsf.cdyne.com/WeatherWS/Weather.asmx?wsdl

命令参数解释:

  • -p <package_name>: 指定生成 Java 类的包名。-p com.example.weather.client
  • -keep: 生成源代码文件(.java),如果不加此参数,默认只生成编译后的 .class 文件。
  • -d <directory>: 指定编译后的 .class 文件存放目录,默认是当前目录。
  • -s <directory>: 指定源代码 .java 文件存放目录。
  • -Xnocompile: 只生成源代码,不进行编译。
  • -extension: 允许使用扩展(非标准)的 WS-I 规范,这通常需要额外的库支持。

查看生成的文件 执行成功后,你会在指定的包路径下(com/example/weather/client)看到一系列生成的 Java 文件,通常包括:

  • WeatherSoap.java: 服务端点接口,定义了所有可用的方法(如 GetCityWeatherByZIP)。
  • Weather.java: 一个数据类(或称为 Bean),通常对应 WSDL 中的某个复杂类型。
  • GetCityWeatherByZIP.java, GetCityWeatherByZIPResponse.java: 请求和响应的数据类。
  • WeatherService.java: 服务类,用于获取 WeatherSoap 接口的实例。
  • ... 以及其他一些辅助类。

在 Java 代码中使用生成的客户端 将生成的所有 Java 文件(或编译后的 .jar 包)添加到你的项目中,然后就可以像下面这样调用服务了:

import com.example.weather.client.Weather;
import com.example.weather.client.WeatherSoap;
import com.example.weather.client.WeatherService;
public class WeatherClient {
    public static void main(String[] args) {
        // 1. 创建服务实例
        WeatherService service = new WeatherService();
        // 2. 获取服务端点接口
        WeatherSoap port = service.getWeatherSoap();
        try {
            // 3. 调用远程方法
            // 注意:这里的方法名和参数需要根据你生成的接口来定
            // WSDL 中可能有一个操作名为 "GetCityWeatherByZIP"
            // wsimport 会将其映射为 Java 方法名 getCityWeatherByZIP
            Weather weather = port.getCityWeatherByZIP("10001");
            // 4. 处理返回结果
            if (weather != null) {
                System.out.println("城市: " + weather.getCity());
                System.out.println("温度: " + weather.getTemperature());
                System.out.println("天气状况: " + weather.getConditions());
            } else {
                System.out.println("未能获取天气信息。");
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

使用 Maven/Gradle 插件 (推荐)

在现代 Java 项目中,我们通常使用 Maven 或 Gradle 作为构建工具,使用它们自带的插件来生成客户端代码是最佳实践,因为它可以自动化整个流程,并将生成的代码集成到构建生命周期中。

这里以 Maven 为例。

优点

  • 自动化: 无需手动运行命令,mvn clean install 时会自动生成代码。
  • 可重复性: 每次构建都会重新生成代码,确保代码与 WSDL 同步。
  • 依赖管理: 可以方便地管理生成的代码源码或 JAR 包。

详细步骤

创建 Maven 项目 如果你还没有 Maven 项目,可以使用 IDE (如 IntelliJ IDEA, Eclipse) 或命令行创建一个。

配置 pom.xmlpom.xml 文件中添加 jaxws-maven-plugin 插件配置。

<project ...>
    ...
    <properties>
        <maven.compiler.source>1.8</maven.compiler.source>
        <maven.compiler.target>1.8</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <!-- 可以定义 WSDL 的版本,方便统一管理 -->
        <wsdl.url>http://wsf.cdyne.com/WeatherWS/Weather.asmx?wsdl</wsdl.url>
    </properties>
    <build>
        <plugins>
            <!-- JAX-WS Maven 插件 -->
            <plugin>
                <groupId>org.jvnet.jax-ws-commons</groupId>
                <artifactId>jaxws-maven-plugin</artifactId>
                <version>2.3</version> <!-- 使用较新版本 -->
                <executions>
                    <execution>
                        <id>generate-sources</id>
                        <phase>generate-sources</phase> <!-- 在 generate-sources 阶段执行 -->
                        <goals>
                            <goal>wsimport</goal>
                        </goals>
                        <configuration>
                            <!-- 源代码生成目录 -->
                            <sourceRoot>${project.build.directory}/generated-sources/jaxws</sourceRoot>
                            <!-- WSDL 文件路径,可以是本地文件或URL -->
                            <wsdlLocation>${wsdl.url}</wsdlLocation>
                            <wsdl>${wsdl.url}</wsdl>
                            <!-- 生成的代码包名 -->
                            <packageName>com.example.weather.client</packageName>
                            <!-- 保留生成的源文件 -->
                            <keep>true</keep>
                        </configuration>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>
    ...
</project>

运行 Maven 命令 在项目根目录下打开命令行,执行:

mvn clean generate-sources

或者直接执行完整的构建命令:

mvn clean install

Maven 会在 target/generated-sources/jaxws 目录下生成客户端代码。

在 IDE 中使用 生成代码后,如果你的 IDE (如 IntelliJ IDEA) 集成了 Maven,它会自动将 target/generated-sources/jaxws 目录标记为 "Generated Sources Root",这样你就可以像使用普通源代码一样直接导入和使用这些类了。

使用 Java 代码调用服务的部分与方法一完全相同。


使用 IDE (IntelliJ IDEA / Eclipse)

大多数现代 Java IDE 都集成了生成 Web Service 客户端的功能,使得这个过程图形化、非常简单。

以 IntelliJ IDEA 为例

  1. 打开项目
  2. 打开 "New" 窗口: File -> New -> Web Service Client
  3. 配置 WSDL: 在弹出的对话框中,选择 WSDL URLWSDL File,然后输入 WSDL 的地址或选择本地文件。
  4. 设置选项:
    • Package: 指定生成的代码包名。
    • Client library: 通常选择 Create client
    • 其他选项(如生成异步客户端等)可以根据需要勾选。
  5. 点击 "OK": IDEA 会自动下载 WSDL 文件并生成所有客户端代码,并将其放置在 src 目录下。
  6. 使用: 生成的代码会直接出现在你的项目结构中,直接复制粘贴方法一的调用代码即可。

优点

  • 图形化界面,简单直观。
  • 与 IDE 集成度高,方便调试。

缺点

  • IDE 特定,如果团队使用不同 IDE,需要统一配置。

常见问题与解决

  1. wsimport 报错:unsupported major.minor version 52.0

    • 原因: 你使用的 JDK 版本太低,JDK 8 默认使用 javac 1.8 (版本号 52.0),错误信息表明你正在尝试用 JDK 7 或更低版本的 javac 去编译 JDK 8 生成的字节码。
    • 解决: 确保 JAVA_HOME 指向 JDK 8 或更高版本。
  2. WSDL 包含了 XSD 引用,wsimport 找不到

    • 原因: WSDL 文件可能通过 <xsd:import><xsd:include> 引用了外部的 XSD (XML Schema Definition) 文件。
    • 解决: 将所有相关的 WSDL 和 XSD 文件放在同一个目录下,然后使用 -wsdllocation 参数来指定一个相对路径,或者直接使用本地文件路径而不是 URL。
  3. 生成的类名或方法名不符合预期

    • 原因: WSDL 中的命名可能与 Java 命名规范冲突。wsimport 会进行一些转换,但有时结果可能不理想。
    • 解决:
      • 使用 -XadditionalHeaders 等高级参数进行更精细的控制。
      • 使用 binding.xml 文件(通过 -binding 参数指定)来自定义命名转换规则,这是最灵活的方式。
方法 优点 缺点 适用场景
wsimport 无需额外安装,官方标准 手动操作,不够自动化 快速测试、小型项目、脚本化任务
Maven/Gradle 插件 自动化、可重复、集成度高 需要配置构建工具 所有现代 Java 项目(强烈推荐)
IDE 插件 图形化,简单直观 IDE 特定,可移植性差 个人开发、快速原型验证

对于任何正式的 Java 项目,强烈推荐使用 Maven 或 Gradle 插件,因为它能将客户端代码的生成过程无缝集成到你的持续集成/持续部署 流程中,对于快速验证或一次性的任务,使用 IDE 的图形化工具或直接运行 wsimport 命令都是非常高效的选择。

分享:
扫描分享到社交APP
上一篇
下一篇