目录
- 核心概念区分:SOAP vs RESTful
- 使用 JDK 内置的
javax.xml.ws(JAX-WS) - 最传统- 适用于:标准的 SOAP WebService。
- 优点:无需额外依赖,JDK 自带。
- 缺点:配置相对繁琐,功能有限。
- 使用 Apache Axis2 / CXF - 最强大灵活
- 适用于:复杂的 SOAP WebService,需要更多控制和高级功能。
- 优点:功能强大,生态成熟,支持 WS-Security 等标准。
- 缺点:需要引入第三方库,学习曲线稍陡。
- 使用 Spring Boot
RestTemplate- 现代 RESTful API- 适用于:现代的 RESTful WebService (本质上不是传统 WebService,但常被混为一谈)。
- 优点:Spring 生态核心,代码简洁,易于集成。
- 缺点:仅适用于 RESTful 风格。
- 使用 Spring Boot
WebClient- 最现代的 RESTful API- 适用于:异步、非阻塞的 RESTful API 调用。
- 优点:响应式编程,性能更高,是
RestTemplate的现代化替代品。 - 缺点:学习曲线比
RestTemplate陡峭。
- 总结与选择建议
核心概念区分:SOAP vs RESTful
在开始之前,必须明确你要调用的服务类型,因为它们的技术栈和调用方式完全不同。

| 特性 | SOAP (Simple Object Access Protocol) | RESTful (Representational State Transfer) |
|---|---|---|
| 协议 | 严格基于 HTTP,但也可用于 SMTP、TCP 等。 | 基于 HTTP/HTTPS 协议。 |
| 数据格式 | 强制使用 XML。 | 灵活,常用 JSON,也支持 XML、HTML、纯文本等。 |
| 标准 | 有严格的国际标准(W3C)。 | 没有官方标准,更像是设计风格和约束。 |
| 接口描述 | 使用 WSDL (Web Services Description Language) 文件来描述服务接口、方法、参数等。 | 使用 OpenAPI (Swagger) 或 API Blueprint 等文档来描述。 |
| 操作 | 通过 <soap:Body> 中的 XML 标签定义操作(如 getWeather)。 |
通过 HTTP 动词(GET, POST, PUT, DELETE)来操作资源。 |
| 安全性 | 内置了 WS-Security 等标准,安全性更高、更复杂。 | 通常依赖 HTTPS 和 OAuth、JWT 等标准。 |
简单判断:
- 如果拿到一个
.wsdl文件,那几乎可以肯定是 SOAP 服务。 - 如果拿到的是一个 API 文档,里面描述了 URL 和 JSON 数据交互,那很可能是 RESTful 服务。
方法一:使用 JDK 内置的 javax.xml.ws (JAX-WS)
这是最传统、最简单的方式,无需任何外部库,适合快速调用简单的 SOAP 服务。
步骤:
- 获取 WSDL 文件:从服务提供方拿到 WSDL 文件的地址。
- 生成客户端代码:使用 JDK 自带的
wsimport工具,根据 WSDL 文件生成 Java 客户端代码(接口和类)。 - 调用服务:在 Java 代码中创建服务实例,调用接口方法。
示例:
假设我们要调用一个天气预报的 SOAP 服务,其 WSDL 地址为:http://www.webxml.com.cn/WebServices/WeatherWS.asmx?wsdl
生成客户端代码

打开命令行,执行以下命令:
# -p: 指定生成的包名 # -keep: 生成源代码文件 # -d: 指定 class 文件输出目录 wsimport -p com.example.weather.client -keep -d src/main/java http://www.webxml.com.cn/WebServices/WeatherWS.asmx?wsdl
执行成功后,你的 src/main/java/com/example/weather/client 目录下会生成一堆 Java 文件。
编写调用代码
import com.example.weather.client.WeatherWS;
import com.example.weather.client.WeatherWSImplService;
import com.example.weather.client.ArrayOfString;
public class JaxWsClient {
public static void main(String[] args) {
// 1. 创建服务 Service 实例
// WeatherWSImplService 是 wsimport 生成的类
WeatherWSImplService service = new WeatherWSImplService();
// 2. 从服务中获取 Port(端口),即服务的实现类
// WeatherWS 是 wsimport 生成的接口
WeatherWS weatherWS = service.getWeatherWSImplPort();
try {
// 3. 调用接口方法
// 假设服务有一个 getWeather 方法,接受城市名作为参数
ArrayOfString result = weatherWS.getWeather("北京", "");
// 4. 处理返回结果
// 返回结果是一个字符串数组
System.out.println("天气预报结果:");
for (String info : result.getString()) {
System.out.println(info);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
方法二:使用 Apache CXF (推荐)
CXF 是一个非常流行的开源框架,它对 JAX-WS 和 JAX-RS (REST) 提供了强大的支持,是企业级开发的常用选择。

步骤:
- 添加依赖:在
pom.xml中添加 CXF 依赖。 - 创建接口:手动或通过工具(如
cxf-codegen-plugin)创建一个与 WSDL 匹配的 Java 接口。 - 调用服务:使用 CXF 的
JaxWsProxyFactoryBean来动态创建服务代理并调用。
示例:
添加 Maven 依赖
<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>
创建客户端接口
这个接口需要和 WSDL 中定义的 PortType 完全一致,为了方便,你可以直接从 wsimport 生成的代码中复制 WeatherWS 接口过来。
// 这个接口内容与 wsimport 生成的接口完全一样
import javax.jws.WebMethod;
import javax.jws.WebParam;
import javax.jws.WebService;
import com.example.weather.client.ArrayOfString; // 假设也复制了这个类
@WebService(targetNamespace = "http://WebXml.com.cn/", name = "WeatherWS")
public interface WeatherWS {
@WebMethod
ArrayOfString getWeather(@WebParam(name = "theCityName") String theCityName, @WebParam(name = "theCount") String theCount);
}
编写调用代码
import org.apache.cxf.jaxws.JaxWsProxyFactoryBean;
public class CxfClient {
public static void main(String[] args) {
// 1. 创建工厂
JaxWsProxyFactoryBean factory = new JaxWsProxyFactoryBean();
// 2. 设置服务接口
factory.setServiceClass(WeatherWS.class);
// 3. 设置 WSDL 地址
factory.setAddress("http://www.webxml.com.cn/WebServices/WeatherWS.asmx");
// 4. 创建服务代理
WeatherWS weatherWS = factory.create(WeatherWS.class);
try {
// 5. 调用方法
ArrayOfString result = weatherWS.getWeather("上海", "");
// 6. 处理结果
System.out.println("天气预报结果:");
for (String info : result.getString()) {
System.out.println(info);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
CXF 的优势:配置更灵活,可以轻松添加拦截器、SOAP 头、WS-Security 等复杂功能。
方法三:使用 Spring Boot RestTemplate
大部分新开发的“WebService”其实是 RESTful 风格的,使用 Spring Boot 的 RestTemplate 是最简单直接的方式。
步骤:
- 添加依赖:确保有
spring-boot-starter-web。 - 配置
RestTemplateBean:在 Spring Boot 配置类中声明RestTemplate。 - 发起 HTTP 请求:在 Service 中注入
RestTemplate并调用其方法。
示例:
假设有一个 RESTful API,GET http://api.example.com/users/1,返回 JSON 数据:{"id":1, "name":"John", "email":"john@example.com"}
添加依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
配置 RestTemplate
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestTemplate;
@Configuration
public class RestTemplateConfig {
@Bean
public RestTemplate restTemplate() {
return new RestTemplate();
}
}
编写调用代码
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;
// 假设有一个与返回 JSON 对应的 Java 类 (POJO)
class User {
private int id;
private String name;
private String email;
// Getters and Setters
@Override
public String toString() {
return "User{" + "id=" + id + ", name='" + name + '\'' + ", email='" + email + '\'' + '}';
}
}
@Service
public class UserService {
@Autowired
private RestTemplate restTemplate;
public User getUserById(int id) {
String url = "http://api.example.com/users/" + id;
// 直接调用 getForObject,它会自动将 JSON 响应映射到 User 对象
User user = restTemplate.getForObject(url, User.class);
return user;
}
public static void main(String[] args) {
// 为了方便演示,手动创建上下文
// 在实际 Spring Boot 应用中,由容器自动注入
var context = new SpringApplicationBuilder(UserService.class).run();
UserService userService = context.getBean(UserService.class);
User user = userService.getUserById(1);
System.out.println(user);
}
}
方法四:使用 Spring Boot WebClient (推荐)
WebClient 是 Spring 5 引入的响应式 HTTP 客户端,是 RestTemplate 的现代化替代品,它支持非阻塞 I/O,在性能和资源利用上更具优势。
步骤:
- 添加依赖:需要
spring-boot-starter-webflux。 - 配置
WebClientBean:在配置类中创建WebClient实例。 - 发起异步请求:使用
WebClient的流畅 API 发起请求并处理响应。
示例:
API 同上:GET http://api.example.com/users/1
添加依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId>
</dependency>
配置 WebClient
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.reactive.function.client.WebClient;
@Configuration
public class WebClientConfig {
@Bean
public WebClient webClient() {
return WebClient.create();
}
}
编写调用代码
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.reactive.function.client.WebClient;
import reactor.core.publisher.Mono;
// User POJO 同上
@Service
public class ReactiveUserService {
@Autowired
private WebClient webClient;
public Mono<User> getUserById(int id) {
String url = "http://api.example.com/users/" + id;
return webClient.get()
.uri(url)
.retrieve() // 获取响应
.bodyToMono(User.class); // 将响应体解析为 Mono<User>
}
public static void main(String[] args) {
var context = new SpringApplicationBuilder(ReactiveUserService.class).run();
ReactiveUserService userService = context.getBean(ReactiveUserService.class);
// 调用方法是异步的,返回一个 Mono
Mono<User> userMono = userService.getUserById(1);
// 订阅 Mono 来获取结果
userMono.subscribe(user -> {
System.out.println("获取到用户: " + user);
}, error -> {
System.err.println("发生错误: " + error.getMessage());
});
// 为了让主线程不退出,等待异步操作完成
// 在实际应用中,通常是在一个 Web 环境中,不需要这个
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
总结与选择建议
| 场景 | 推荐技术 | 理由 |
|---|---|---|
| 调用传统 SOAP 服务 | Apache CXF | 功能强大,灵活,是企业级标准,JDK 自带的 javax.xml.ws 可用于简单场景,但扩展性差。 |
| 调用现代 RESTful API | Spring Boot WebClient |
最新、最现代的选择,支持响应式编程,性能更好,是 RestTemplate 的未来方向。 |
| 快速原型/简单 RESTful API | Spring Boot RestTemplate |
代码简单直观,易于上手,对于同步阻塞场景足够好用。 |
| 无框架的旧项目 | JDK javax.xml.ws |
无需引入外部依赖,适合快速集成。 |
最终建议:
- 如果你的项目是 SOAP 服务,直接使用 Apache CXF。
- 如果你的项目是 Spring Boot 并且调用 RESTful 服务,优先使用
WebClient,如果项目是同步的且不想改动,RestTemplate仍然是一个可靠的选择。
