准备工作:安装 Apache CXF
你需要确保你的环境中已经安装了 Apache CXF,最简单的方式是下载它的二进制包。

- 下载:访问 Apache CXF 官网下载页面。
- 选择版本:下载最新的稳定版本(
apache-cxf-<version>-bin.zip)。 - 解压:将下载的 ZIP 文件解压到一个你方便管理的目录,
D:\dev\apache-cxf-3.4.0。 - 配置环境变量 (推荐):
- 将解压后的
bin目录(D:\dev\apache-cxf-3.4.0\bin)添加到系统的PATH环境变量中。 - 这样你就可以在任何地方直接使用
wsdl2java命令,而无需每次都输入完整路径。
- 将解压后的
配置完成后,打开一个新的命令行窗口,输入以下命令验证是否安装成功:
wsdl2java -version
如果能看到 CXF 的版本信息,说明安装和配置成功。
wsdl2java 常用参数
wsdl2java 提供了丰富的参数来定制生成的代码,以下是一些最常用的参数:
| 参数 | 简写 | 描述 | 示例 |
|---|---|---|---|
| -d | 指定生成代码的输出目录。 | -d D:/generated-code |
|
| -client | 生成客户端调用代码(默认包含)。 | -client |
|
| -server | 生成服务端实现代码。 | -server |
|
| -p | 指定生成的 Java 包名,非常重要! | -p com.example.client |
|
| -wsdlLocation | 指定 WSDL 文件的最终位置(在代码中作为常量)。 | -wsdlLocation http://example.com/service?wsdl |
|
| -frontend | 指定前端模式,如 jaxws (默认) 或 jaxb。 |
-frontend jaxws |
|
| -autoNameResolution | 自动解决命名冲突问题(重命名同名类)。 | -autoNameResolution |
|
| -compile | 编译生成的 Java 文件。 | -compile |
|
| -help | 显示帮助信息。 | -help |
生成客户端代码的步骤
我们通过一个具体的例子来演示,假设你有一个 WSDL 文件,http://www.webservicex.net/globalweather.asmx?wsdl (这是一个公共的天气服务 WSDL)。

获取 WSDL 文件
你可以将 WSDL 文件的 URL 下载到本地,或者直接使用 URL,为了稳定性和离线开发,推荐先下载到本地。
假设我们将 WSDL 文件保存为 GlobalWeather.wsdl 在 D:/wsdl_files/ 目录下。
执行 wsdl2java 命令
打开命令行窗口,进入你想要存放生成代码的目录(D:/),然后执行以下命令:
wsdl2java -p com.example.weather.client -d D:/generated-code -client D:/wsdl_files/GlobalWeather.wsdl
命令解析:
wsdl2java: 执行工具。-p com.example.weather.client: 将生成的所有 Java 类放在com.example.weather.client这个包下。强烈建议使用这个参数,否则类可能会被放在默认的org.tempuri等不规范的包中。-d D:/generated-code: 将所有生成的文件(.java, .class 等)输出到D:/generated-code目录。-client: 明确告诉工具我们需要生成客户端代码。D:/wsdl_files/GlobalWeather.wsdl: 指定 WSDL 文件的路径。
执行成功后,你会看到命令行工具开始解析 WSDL,并输出类似 [INFO] ... 的日志信息,最后在 D:/generated-code 目录下生成一套完整的 Java 代码。
查看生成的代码结构
生成的代码目录结构通常如下:
D:/generated-code/
└── com/
└── example/
└── weather/
└── client/
├── GlobalWeather.java // 主要的服务接口 (SEI)
├── GlobalWeatherService.java // 服务工厂类,用于获取接口实例
├── ObjectFactory.java // JAXB 相关的工厂类
├── package-info.java
└── ... (其他一些 JAXB 模型类)
使用生成的代码调用 Web Service
生成的代码中最核心的两个类是:
GlobalWeather.java: 这是服务端点接口,里面定义了 WSDL 中描述的所有操作(方法),你需要像调用普通 Java 接口一样调用它。GlobalWeatherService.java: 这是一个工厂类,提供了一个getGlobalWeatherPort()方法,该方法返回一个GlobalWeather接口的实例。
下面是一个完整的 Java 调用示例:
package com.example.weather.client;
public class WeatherClient {
public static void main(String[] args) {
// 1. 创建服务工厂实例
GlobalWeatherService service = new GlobalWeatherService();
// 2. 从工厂获取服务接口的代理对象
// 方法名 "getGlobalWeatherPort()" 是根据 WSDL 中的 Port 名称生成的
GlobalWeather port = service.getGlobalWeatherPort();
// 3. 调用接口方法,传入 WSDL 中定义的参数
// 注意:根据 WSDL,第一个参数是城市名,第二个是国家名
String weatherData = port.getWeather("Beijing", "China");
// 4. 打印返回结果
System.out.println("北京的天气信息:");
System.out.println(weatherData);
}
}
如何运行这个客户端?
-
将
GlobalWeather.java和GlobalWeatherService.java等生成的.java文件复制到你的项目中。 -
确保你的项目依赖了 Apache CXF 的库,如果你使用 Maven,可以在
pom.xml中添加:<dependency> <groupId>org.apache.cxf</groupId> <artifactId>cxf-rt-frontend-jaxws</artifactId> <version>3.4.0</version> <!-- 使用与你 wsdl2java 工具匹配的版本 --> </dependency> <dependency> <groupId>org.apache.cxf</groupId> <artifactId>cxf-rt-transports-http</artifactId> <version>3.4.0</version> </dependency> -
编译并运行
WeatherClient的main方法。
高级用法与最佳实践
使用 -wsdlLocation 参数
在生成的代码中,WSDL 的位置被硬编码为一个常量,WSDL 地址变了,你需要重新生成代码,使用 -wsdlLocation 参数可以更灵活地处理这个问题。
wsdl2java -p com.example.weather.client -d D:/generated-code -wsdlLocation "classpath:GlobalWeather.wsdl" D:/wsdl_files/GlobalWeather.wsdl
这样生成的代码中,WSDL 位置会是 classpath:GlobalWeather.wsdl,你只需要将 GlobalWeather.wsdl 文件放到你项目的 src/main/resources 目录下,运行时会自动从 classpath 中加载。
处理复杂的 WSDL 和命名冲突
对于一些复杂的 WSDL,可能会出现命名冲突(多个不同命名空间下的类型恰好同名)。
-autoNameResolution: 这个参数会自动为冲突的类名添加后缀(如_1,_2),通常能解决大部分问题。- 手动重命名: 如果自动重命名不符合你的预期,你可能需要手动编辑 WSDL 文件,或者使用更高级的参数(如
-exshtrue)来排除一些 schema,但这需要更深入的理解。
与 Spring 集成
在企业级应用中,通常不会手动创建客户端,而是通过 Spring 框架来管理,CXF 提供了与 Spring 集成的能力。
你可以在 Spring 的配置文件(如 applicationContext.xml)中定义一个客户端代理:
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:jaxws="http://cxf.apache.org/jaxws"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://cxf.apache.org/jaxws
http://cxf.apache.org/schemas/jaxws.xsd">
<!-- 定义一个 Web Service 客户端 -->
<jaxws:client id="globalWeatherClient"
serviceClass="com.example.weather.client.GlobalWeather"
address="http://www.webservicex.net/globalweather.asmx" />
</beans>
然后在你的 Java 代码中,可以直接通过 Spring 的依赖注入来使用这个客户端:
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Component
public class WeatherService {
@Autowired // Spring 会自动注入上面定义的客户端代理
private GlobalWeather globalWeatherClient;
public void getWeather() {
String weatherData = globalWeatherClient.getWeather("Shanghai", "China");
System.out.println("上海的天气信息: " + weatherData);
}
}
这种方式更加灵活,便于管理和测试。
使用 wsdl2java 生成 Java 客户端代码是一个非常标准化的流程:
- 安装工具:确保
wsdl2java在PATH中。 - 分析 WSDL:了解 WSDL 提供的服务、操作和参数。
- 执行命令:使用
-d,-p,-client等关键参数生成代码。 - 使用代码:通过
Service类获取Port接口实例,并调用其方法。 - 高级集成:对于复杂项目,考虑使用
-wsdlLocation和 Spring 框架进行集成。
通过这个流程,你可以快速地将任何符合标准的 Web Service 集成到你的 Java 应用程序中。
