什么是 WebService?
在开始之前,简单理解一下 WebService,它是一种跨编程语言、跨操作系统、跨平台的远程调用技术,通过标准的 XML 格式进行数据交换,并使用 SOAP (Simple Object Access Protocol) 协议作为通信规范,最常用的描述 WebService 接口的语言是 WSDL (Web Services Description Language)。

使用 JDK 自带的 javax.xml.ws (JAX-WS API)
这是 Java 标准库提供的方法,无需添加任何第三方依赖,非常适合快速开发和简单的 WebService 调用。
适用场景
- 调用基于 SOAP 协议的、符合 JAX-WS 规范的 WebService。
- 不想引入第三方库,追求轻量级。
实现步骤
假设我们要调用一个公开的天气查询 WebService(http://www.webxml.com.cn/WebServices/WeatherWebService.asmx?wsdl)。
第1步:获取 WSDL 地址
WSDL 文件是 WebService 的“说明书”,里面定义了所有可用的方法、参数和返回值,通常是一个 .asmx?wsdl 结尾的 URL。

第2步:生成客户端代码
你需要使用 JDK 自带的 wsimport 工具,根据 WSDL 文件生成一系列 Java 代码(客户端存根)。
- 打开命令行(CMD 或 PowerShell)。
- 执行以下命令:
# -keep: 生成源代码后保留 .java 文件 # -d: 指定编译后的 .class 文件存放目录 # -p: 指定生成的包名 wsimport -keep -d D:\temp -p com.example.weather http://www.webxml.com.cn/WebServices/WeatherWebService.asmx?wsdl
执行成功后,
D:\temp目录下会生成com/example/weather包,里面包含一堆.class和.java文件,你只需要关注WeatherWebService和WeatherWebServiceSoap这两个核心接口。
第3步:编写 Java 调用代码

将生成的 Java 文件(或其编译后的 .class 文件)导入到你的项目中,然后编写调用逻辑。
import com.example.weather.WeatherWebService;
import com.example.weather.WeatherWebServiceSoap;
import com.example.weather.ArrayOfString;
public class JaxwsClient {
public static void main(String[] args) {
// 1. 创建服务视图 (Service)
// WeatherWebService 是 wsimport 生成的类,用于获取服务端口
WeatherWebService service = new WeatherWebService();
// 2. 获取服务端点接口 (Service Endpoint Interface, SEI)
// WeatherWebServiceSoap 是 wsimport 生成的接口,包含了所有可用的方法
WeatherWebServiceSoap port = service.getWeatherWebServiceSoap();
// 3. 调用具体的方法
String cityCode = "北京";
ArrayOfString result = port.getWeather(cityCode, "");
// 4. 处理返回结果
// 返回结果通常是一个 List<String>,包含了天气信息
System.out.println("查询 " + cityCode + " 的天气信息:");
for (String info : result.getString()) {
System.out.println(info);
}
}
}
使用 Apache CXF 框架
Apache CXF 是一个功能强大、灵活的开源框架,它不仅支持 SOAP,还支持 RESTful 服务,对于复杂的 WebService 或需要更多自定义的场景,CXF 是更好的选择。
适用场景
- 需要更高级的、可配置的 SOAP 功能。
- 项目中已经集成了 CXF 框架。
- 需要同时支持 SOAP 和 RESTful 调用。
实现步骤
第1步:添加 Maven 依赖
在你的 pom.xml 文件中添加 CXF 的核心依赖。
<dependencies>
<!-- CXF 核心依赖 -->
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-core</artifactId>
<version>3.4.5</version> <!-- 使用较新版本 -->
</dependency>
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-frontend-jaxws</artifactId>
<version>3.4.5</version>
</dependency>
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-transports-http</artifactId>
<version>3.4.5</version>
</dependency>
</dependencies>
第2步:生成客户端代码 (可选)
CXF 也提供了一个更强大的代码生成工具 cxf-xjc-utils 或 wsdl2java,它比 JDK 自带的 wsimport 功能更全,支持更多数据类型的绑定。
# 下载 cxf-xjc-utils 并解压 # 运行 wsdl2java.bat (Windows) 或 wsdl2java.sh (Linux/Mac) # 示例命令: # bin\wsdl2java -p com.example.weather -d D:\temp http://www.webxml.com.cn/WebServices/WeatherWebService.asmx?wsdl
第3步:编写 Java 调用代码
CXF 的调用方式与 JAX-WS 非常相似,因为 CXF 本身就是 JAX-WS 的一个实现。
import com.example.weather.WeatherWebService;
import com.example.weather.WeatherWebServiceSoap;
import com.example.weather.ArrayOfString;
public class CxfClient {
public static void main(String[] args) {
// 1. 创建服务视图
WeatherWebService service = new WeatherWebService();
// 2. 获取服务端口
WeatherWebServiceSoap port = service.getWeatherWebServiceSoap();
// 3. 调用方法
String cityCode = "上海";
ArrayOfString result = port.getWeather(cityCode, "");
// 4. 处理结果
System.out.println("查询 " + cityCode + " 的天气信息:");
for (String info : result.getString()) {
System.out.println(info);
}
}
}
使用 Spring Boot + CXF (企业级推荐)
在现代 Spring Boot 项目中,集成 CXF 来调用 WebService 是最优雅、最企业级的方式,它将 WebService 客户端的创建交由 Spring 容器管理,便于配置、注入和生命周期管理。
适用场景
- 基于 Spring Boot 的项目。
- 需要集成到现有的 Spring 生态系统中。
- 希望通过配置文件管理 WebService 的地址、超时等信息。
实现步骤
第1步:添加 Maven 依赖
除了 CXF 的依赖,还需要添加 Spring Boot 的 Web starter。
<dependencies>
<!-- Spring Boot Starter Web -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- CXF Dependencies -->
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-spring-boot-starter-jaxws</artifactId>
<version>3.4.5</version> <!-- 注意版本要与 Spring Boot 兼容 -->
</dependency>
</dependencies>
第2步:生成客户端代码
同方法二,使用 wsdl2java 生成客户端代码。
第3步:创建配置类
创建一个配置类,将生成的 WebService 客户端类注册为 Spring Bean。
import com.example.weather.WeatherWebService;
import com.example.weather.WeatherWebServiceSoap;
import org.apache.cxf.jaxws.JaxWsProxyFactoryBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
@Configuration
public class CxfClientConfig {
// @Bean 定义一个 Spring Bean
// @Primary 表示当有多个相同类型的 Bean 时,优先使用这个
@Bean
@Primary
public WeatherWebServiceSoap weatherWebServiceSoap() {
// 1. 创建 JaxWsProxyFactoryBean
JaxWsProxyFactoryBean factory = new JaxWsProxyFactoryBean();
// 2. 设置服务接口
factory.setServiceClass(WeatherWebServiceSoap.class);
// 3. 设置 WebService 的地址 (注意:这里不是 WSDL 地址)
factory.setAddress("http://www.webxml.com.cn/WebServices/WeatherWebService.asmx");
// 4. 可以设置超时时间等属性
// factory.getOutInterceptors().add(new LoggingInInterceptor());
// factory.getOutInterceptors().add(new LoggingOutInterceptor());
// 5. 创建并返回代理对象
return (WeatherWebServiceSoap) factory.create();
}
}
第4步:在 Service 或 Controller 中注入并使用
现在你可以在任何需要的地方通过 @Autowired 注入这个客户端,然后直接调用方法。
import com.example.weather.ArrayOfString;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class WeatherService {
@Autowired
private WeatherWebServiceSoap weatherWebServiceSoap; // 注入客户端
public void getWeatherInfo(String cityCode) {
System.out.println("正在查询 " + cityCode + " 的天气...");
ArrayOfString result = weatherWebServiceSoap.getWeather(cityCode, "");
System.out.println("查询结果:");
result.getString().forEach(System.out::println);
}
}
然后在你的 WeatherController 中调用 WeatherService 即可。
总结与对比
| 特性 | JDK javax.xml.ws (JAX-WS) |
Apache CXF | Spring Boot + CXF |
|---|---|---|---|
| 依赖 | 无需额外依赖 | 需要 CXF 库 | 需要 Spring Boot + CXF |
| 易用性 | 简单,适合快速上手 | 简单,功能更丰富 | 需要理解 Spring,但集成后最优雅 |
| 灵活性 | 较低,配置选项少 | 高,支持拦截器、数据绑定等 | 非常高,可与 Spring 生态无缝集成 |
| 适用场景 | 简单的、一次性的调用 | 复杂项目、需要高级功能 | 现代 Spring Boot 企业级应用 |
| 代码生成 | wsimport |
wsdl2java (功能更强) |
wsdl2java |
| 推荐度 | ⭐⭐⭐ | ⭐⭐⭐⭐ | ⭐⭐⭐⭐⭐ |
如何选择?
- 如果你只是写一个小的测试程序,或者临时调用一个 WebService,使用 方法一 (JAX-WS) 最快,不用配置任何东西。
- 如果你的项目已经是一个复杂的 Java Web 应用,并且对性能和灵活性有要求,使用 方法二 (Apache CXF) 是一个稳健的选择。
- 如果你的项目是基于 Spring Boot 的,或者你希望遵循 Spring 的开发规范,追求可维护性和可扩展性,方法三 (Spring Boot + CXF) 是最佳实践,也是目前业界的主流方案。
