方法概览
- JAX-WS (Java API for XML Web Services):这是目前 Java 官方、最主流的调用 WebService 的方式,它非常成熟,并且内置在 Java 标准库中(从 JDK 1.6 开始),我们主要使用它的客户端 API 来调用服务。
- Apache CXF:这是一个功能强大的、开源的、功能齐全的 WebService 框架,它不仅支持 JAX-WS 规范,还支持 RESTful 服务等,当 JAX-WS 无法满足复杂需求时,CXF 是一个非常好的选择。
- Spring Boot + WebService Template:在 Spring 生态中,通常不直接使用 JAX-WS 或 CXF 的客户端,而是使用
WebServiceTemplate,它提供了一个更简洁、更符合 Spring 风格的方式来调用 WebService。 - 生成客户端代码调用:这是最传统、最简单的方法,通过工具(如
wsimport)根据 WSDL 文件生成客户端 Java 代码,然后像调用本地方法一样调用远程服务。
场景设定
为了方便演示,我们假设有一个简单的 WebService,它提供以下功能:

- 服务地址:
http://www.webxml.com.cn/WebServices/WeatherWebService.asmx - WSDL 地址:
http://www.webxml.com.cn/WebServices/WeatherWebService.asmx?wsdl - 服务方法:
getWeatherbyCityName - 功能: 根据城市名查询天气。
- 参数:
string theCityName("北京") - 返回值: 一个
ArrayOfString对象,包含天气信息字符串。
使用 JAX-WS (无需生成客户端代码)
这是现代 Java 开发中推荐的方式,因为它更灵活,不需要预先生成一堆代码,核心类是 javax.xml.ws.Service。
步骤 1: 添加 Maven 依赖
虽然 JAX-WS 是 Java 标准库,但如果你使用 Maven,最好显式声明一下,以确保在所有环境下都能正常工作。
<dependency>
<groupId>javax.xml.ws</groupId>
<artifactId>jaxws-api</artifactId>
<version>2.3.x</version> <!-- 使用与 JDK 版本匹配的最新版本 -->
</dependency>
<!-- 对于较老的 JDK (如 1.6/1.7), 可能需要这个依赖来获取完整的实现 -->
<dependency>
<groupId>com.sun.xml.ws</groupId>
<artifactId>jaxws-rt</artifactId>
<version>2.3.x</version>
</dependency>
步骤 2: 编写 Java 调用代码

import javax.xml.namespace.QName;
import javax.xml.ws.Service;
import java.net.URL;
import java.util.List;
public class JaxwsClient {
public static void main(String[] args) throws Exception {
// 1. 定义 WSDL 文件的 URL
URL wsdlUrl = new URL("http://www.webxml.com.cn/WebServices/WeatherWebService.asmx?wsdl");
// 2. 创建 Service 实例
// 参数1: WSDL 中的 targetNamespace 命名空间
// 参数2: WSDL 中的 service name
QName qname = new QName("http://WebXml.com.cn/", "WeatherWebService");
Service service = Service.create(wsdlUrl, qname);
// 3. 获取 Port (服务端点接口),即我们要调用的接口
// 参数1: WSDL 中的 portType name
// 参数2: 动态代理的接口类型,这里使用 Object.class,因为 CXF 会处理
WeatherWebServiceSoap weatherService = service.getPort(WeatherWebServiceSoap.class);
// 4. 直接调用方法,就像调用本地方法一样
// 注意:getWeatherbyCityName 返回的是 ArrayOfString
ArrayOfString weatherInfo = weatherService.getWeatherbyCityName("北京");
// 5. 处理返回结果
List<String> result = weatherInfo.getString();
if (result != null && !result.isEmpty()) {
System.out.println("北京的天气信息:");
for (String info : result) {
System.out.println(info);
}
} else {
System.out.println("未能获取到天气信息。");
}
}
}
说明:
WeatherWebServiceSoap和ArrayOfString这些类名和接口名是从 WSDL 文档中解析出来的,IDE (如 IntelliJ IDEA 或 Eclipse) 通常可以智能提示,或者你可以通过wsimport工具生成一个小的 JAR 包来引用这些类型,这样代码会更清晰。
生成客户端代码调用 (传统方法)
这种方法非常直观,适合初学者,因为它将远程服务完全“翻译”成了本地 Java 对象。
步骤 1: 使用 wsimport 生成客户端代码
打开你的终端或命令行,进入你的项目目录,然后执行以下命令:

# -keep: 生成源代码 # -d: 指定编译后的 .class 文件存放目录 # -p: 指定生成的包名 wsimport -keep -d src/main/java -p com.example.weather.client http://www.webxml.com.cn/WebServices/WeatherWebService.asmx?wsdl
执行成功后,你的 src/main/java/com/example/weather/client 目录下会生成一堆 Java 文件(.java)和类文件(.class)。
步骤 2: 编写调用代码
你可以像使用任何本地 JavaBean 一样使用这些生成的类。
import com.example.weather.client.ArrayOfString;
import com.example.weather.client.WeatherWebService;
import com.example.weather.client.WeatherWebServiceSoap;
public class GeneratedClient {
public static void main(String[] args) {
// 1. 创建服务实例
WeatherWebService service = new WeatherWebService();
// 2. 获取服务端口
WeatherWebServiceSoap port = service.getWeatherWebServiceSoap();
// 3. 调用方法
ArrayOfString weatherInfo = port.getWeatherbyCityName("上海");
// 4. 处理结果
if (weatherInfo != null) {
System.out.println("上海的天气信息:");
for (String info : weatherInfo.getString()) {
System.out.println(info);
}
}
}
}
优点:
- 代码非常直观,IDE 的代码提示和重构功能都能完美支持。
- 类型安全,编译时就能检查错误。
缺点:
- 每当服务端 WSDL 发生变化时,都需要重新生成代码,比较麻烦。
使用 Apache CXF (功能更强大)
CXF 是一个功能更全面的框架,如果你需要处理 WS-Security、SOAP 消息拦截、RESTful 服务等高级特性,CXF 是不二之选。
步骤 1: 添加 Maven 依赖
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-spring-boot-starter-jaxws</artifactId>
<version>3.x.x</version> <!-- 使用最新稳定版 -->
</dependency>
步骤 2: 编写调用代码
CXF 的调用方式与 JAX-WS 非常相似,因为它本身就是 JAX-WS 的一个实现。
import org.apache.cxf.jaxws.JaxWsProxyFactoryBean;
import java.util.List;
public class CxfClient {
public static void main(String[] args) {
// 1. 创建 JaxWsProxyFactoryBean
JaxWsProxyFactoryBean factory = new JaxWsProxyFactoryBean();
// 2. 设置服务地址
factory.setAddress("http://www.webxml.com.cn/WebServices/WeatherWebService.asmx");
// 3. 设置服务接口 (需要从 wsimport 生成的或通过 CXF 工具生成)
factory.setServiceClass(WeatherWebServiceSoap.class);
// 4. 创建客户端代理
WeatherWebServiceSoap weatherService = factory.create(WeatherWebServiceSoap.class);
// 5. 调用方法
ArrayOfString weatherInfo = weatherService.getWeatherbyCityName("广州");
// 6. 处理结果
if (weatherInfo != null) {
System.out.println("广州的天气信息:");
weatherInfo.getString().forEach(System.out::println);
}
}
}
说明:
- CXF 提供了
JaxWsProxyFactoryBean,它比 JAX-WS 原生的方式配置更灵活,可以方便地设置如outInterceptors(出站拦截器)、inInterceptors(入站拦截器) 等,用于添加日志、安全头等。
使用 Spring Boot 的 WebServiceTemplate
在 Spring Boot 项目中,这是最优雅、最集成的方式。
步骤 1: 添加依赖
<dependency>
<groupId>org.springframework.boot</groupId>
< 