下面我将为你详细介绍几种主流的方法,从最经典到最现代,并提供完整的步骤和示例。
核心概念
- 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.xml
在 pom.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 为例
- 打开项目。
- 打开 "New" 窗口:
File->New->Web Service Client。 - 配置 WSDL: 在弹出的对话框中,选择
WSDL URL或WSDL File,然后输入 WSDL 的地址或选择本地文件。 - 设置选项:
- Package: 指定生成的代码包名。
- Client library: 通常选择
Create client。 - 其他选项(如生成异步客户端等)可以根据需要勾选。
- 点击 "OK": IDEA 会自动下载 WSDL 文件并生成所有客户端代码,并将其放置在
src目录下。 - 使用: 生成的代码会直接出现在你的项目结构中,直接复制粘贴方法一的调用代码即可。
优点
- 图形化界面,简单直观。
- 与 IDE 集成度高,方便调试。
缺点
- IDE 特定,如果团队使用不同 IDE,需要统一配置。
常见问题与解决
-
wsimport报错:unsupported major.minor version 52.0- 原因: 你使用的 JDK 版本太低,JDK 8 默认使用
javac 1.8(版本号 52.0),错误信息表明你正在尝试用 JDK 7 或更低版本的javac去编译 JDK 8 生成的字节码。 - 解决: 确保
JAVA_HOME指向 JDK 8 或更高版本。
- 原因: 你使用的 JDK 版本太低,JDK 8 默认使用
-
WSDL 包含了 XSD 引用,
wsimport找不到- 原因: WSDL 文件可能通过
<xsd:import>或<xsd:include>引用了外部的 XSD (XML Schema Definition) 文件。 - 解决: 将所有相关的 WSDL 和 XSD 文件放在同一个目录下,然后使用
-wsdllocation参数来指定一个相对路径,或者直接使用本地文件路径而不是 URL。
- 原因: WSDL 文件可能通过
-
生成的类名或方法名不符合预期
- 原因: WSDL 中的命名可能与 Java 命名规范冲突。
wsimport会进行一些转换,但有时结果可能不理想。 - 解决:
- 使用
-XadditionalHeaders等高级参数进行更精细的控制。 - 使用
binding.xml文件(通过-binding参数指定)来自定义命名转换规则,这是最灵活的方式。
- 使用
- 原因: WSDL 中的命名可能与 Java 命名规范冲突。
| 方法 | 优点 | 缺点 | 适用场景 |
|---|---|---|---|
wsimport |
无需额外安装,官方标准 | 手动操作,不够自动化 | 快速测试、小型项目、脚本化任务 |
| Maven/Gradle 插件 | 自动化、可重复、集成度高 | 需要配置构建工具 | 所有现代 Java 项目(强烈推荐) |
| IDE 插件 | 图形化,简单直观 | IDE 特定,可移植性差 | 个人开发、快速原型验证 |
对于任何正式的 Java 项目,强烈推荐使用 Maven 或 Gradle 插件,因为它能将客户端代码的生成过程无缝集成到你的持续集成/持续部署 流程中,对于快速验证或一次性的任务,使用 IDE 的图形化工具或直接运行 wsimport 命令都是非常高效的选择。
