- JAX-WS (Java API for XML Web Services):Java 官方标准,是目前最主流、最推荐的方式,它简化了 WebService 的创建和调用过程。
- Axis2 / Apache CXF:功能强大的第三方框架,提供了比 JAX-WS 更多的企业级特性,如 REST 支持、WS-Security 等。
- 手动调用 (HttpClient + XML/JSON 解析):不依赖 WebService 框架,通过通用的 HTTP 客户端发送 SOAP 请求或 RESTful API 请求,这种方式最灵活,但代码量也最大。
JAX-WS (推荐)
JAX-WS 是 Java EE 的标准部分,现在也包含在 Java SE 中,它允许你通过注解来描述 WebService,并提供了工具来自动生成客户端代码。

通过 WSDL 文件生成客户端并调用
这是最常见的情况,你拥有一个服务的 WSDL (Web Services Description Language) 文件。
步骤 1:生成客户端代码
JDK 自带了 wsimport 工具,可以根据 WSDL 文件生成 Java 客户端代码。
-
打开命令行(CMD 或 PowerShell)。
(图片来源网络,侵删) -
执行以下命令:
# 格式:wsimport -keep -d <输出目录> -p <生成的包名> <WSDL文件URL或路径> wsimport -keep -d .\src\main\java -p com.example.client http://www.webxml.com.cn/webservices/weatherwebservice.asmx?wsdl
-keep: 生成源代码文件。-d: 指定编译后的.class文件存放目录。-p: 指定生成的 Java 包名。WSDL URL: WebService 的 WSDL 地址。
执行成功后,会在你指定的目录下生成一堆 Java 文件,包括一个
Service类和一个(或多个)Port接口。
步骤 2:调用生成的客户端
在你的 Java 项目中,引入生成的代码,然后像调用普通 Java 接口一样调用服务。

import com.example.client.WeatherWS;
import com.example.client.WeatherWSLocator;
import com.example.client.WeatherWSSoap;
public class JaxwsClientExample {
public static void main(String[] args) {
try {
// 1. 创建服务定位器 (Service Locator)
// WSDL 中的 <service name="..."> 对应这个类
WeatherWS service = new WeatherWSLocator();
// 2. 获取服务端点 (Port)
// WSDL 中的 <port name="..."> 对应这个接口
// 注意:这里我们使用 getWeatherWSSoap(),因为 WSDL 中定义了 soap 绑定
WeatherWSSoap port = service.getWeatherWSSoap();
// 3. 调用 WebService 方法
// 直接调用接口中定义的方法
String result = port.getWeatherbyCityName("北京");
// 4. 处理结果
System.out.println("WebService 返回结果:");
System.out.println(result);
} catch (Exception e) {
e.printStackTrace();
}
}
}
动态调用 (无需生成代码)
如果你不想生成客户端代码,可以使用 JAX-WS 的 Dispatch API 进行动态调用。
import javax.xml.namespace.QName;
import javax.xml.soap.MessageFactory;
import javax.xml.soap.SOAPBody;
import javax.xml.soap.SOAPEnvelope;
import javax.xml.soap.SOAPMessage;
import javax.xml.ws.Dispatch;
import javax.xml.ws.Service;
import java.net.URL;
public class DynamicJaxwsClientExample {
public static void main(String[] args) {
try {
// 1. 创建服务
URL wsdlUrl = new URL("http://www.webxml.com.cn/webservices/weatherwebservice.asmx?wsdl");
QName serviceName = new QName("http://WebXml.com.cn/", "WeatherWS");
Service service = Service.create(wsdlUrl, serviceName);
// 2. 创建 Dispatch 实例 (使用 SOAPMessage 模式)
// QName portName = new QName("http://WebXml.com.cn/", "WeatherWSSoap");
// Dispatch<SOAPMessage> dispatch = service.createDispatch(portName, SOAPMessage.class, Service.Mode.MESSAGE);
// 或者使用 PAYLOAD 模式 (只处理 SOAP Body)
QName portName = new QName("http://WebXml.com.cn/", "WeatherWSSoap");
Dispatch<SOAPMessage> dispatch = service.createDispatch(portName, SOAPMessage.class, Service.Mode.PAYLOAD);
// 3. 创建 SOAP 请求消息
MessageFactory messageFactory = MessageFactory.newInstance();
SOAPMessage soapRequest = messageFactory.createMessage();
SOAPEnvelope envelope = soapRequest.getSOAPPart().getEnvelope();
SOAPBody body = envelope.getBody();
// 添加请求元素
// <soap:Body>
// <getWeatherbyCityName xmlns="http://WebXml.com.cn/">
// <theCityName>北京</theCityName>
// </getWeatherbyCityName>
// </soap:Body>
QName bodyName = new QName("http://WebXml.com.cn/", "getWeatherbyCityName");
body.addBodyElement(bodyName).addTextNode("北京");
// 4. 发送请求并获取响应
System.out.println("发送 SOAP 请求...");
SOAPMessage soapResponse = dispatch.invoke(soapRequest);
// 5. 处理响应
System.out.println("收到 SOAP 响应:");
soapResponse.writeTo(System.out);
} catch (Exception e) {
e.printStackTrace();
}
}
}
使用 Apache CXF
CXF 是一个功能非常全面的开源 WebService 框架,它同时支持 JAX-WS 和 JAX-RS (REST) 标准。
步骤 1:添加 Maven 依赖
在你的 pom.xml 文件中添加 CXF 的依赖。
<dependencies>
<!-- CXF 核心依赖 -->
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-core</artifactId>
<version>3.5.5</version> <!-- 使用最新稳定版 -->
</dependency>
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-frontend-jaxws</artifactId>
<version>3.5.5</version>
</dependency>
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-transports-http</artifactId>
<version>3.5.5</version>
</dependency>
<!-- CXF 内置了 Jetty,可以方便地测试服务端 -->
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-transports-http-jetty</artifactId>
<version>3.5.5</version>
</dependency>
</dependencies>
步骤 2:生成客户端并调用
CXF 提供了 cxf-codegen-plugin Maven 插件来生成客户端,与 wsimport 类似。
- 生成代码 (在
pom.xml中配置插件,或在命令行使用cxf-codegen-frontend-maven-plugin)。 - 调用代码:CXF 生成的客户端代码与 JAX-WS 生成的在调用方式上几乎完全相同。
import org.apache.cxf.jaxws.JaxWsProxyFactoryBean;
import com.example.client.WeatherWSSoap; // 假设这是 CXF 生成的接口
public class CxfClientExample {
public static void main(String[] args) {
// 1. 使用 JaxWsProxyFactoryBean 创建客户端代理
// 无需 WSDL 文件生成代码,直接通过接口和地址创建
JaxWsProxyFactoryBean factory = new JaxWsProxyFactoryBean();
factory.setServiceClass(WeatherWSSoap.class);
factory.setAddress("http://www.webxml.com.cn/webservices/weatherwebservice.asmx");
// 2. 获取客户端代理对象
WeatherWSSoap weatherWS = (WeatherWSSoap) factory.create();
// 3. 直接调用方法
String result = weatherWS.getWeatherbyCityName("上海");
// 4. 处理结果
System.out.println("CXF 调用结果:");
System.out.println(result);
}
}
CXF 的优势:配置更灵活,支持更多的 WS-* 标准(如安全、事务),并且可以非常方便地与 Spring 集成。
手动调用 (HttpClient + XML/JSON)
这种方式不依赖于任何 WebService 特定框架,适用于调用 RESTful API 或者需要手动构造 SOAP 请求的场景。
场景:调用一个简单的 RESTful WebService (返回 JSON)
步骤 1:添加 HttpClient 依赖
<dependencies>
<!-- Apache HttpClient -->
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.5.14</version>
</dependency>
<!-- JSON 解析库,Jackson -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.15.2</version>
</dependency>
</dependencies>
步骤 2:编写调用代码
假设有一个 RESTful API:http://api.example.com/users/1,返回一个 JSON 对象 {"id":1, "name":"John", "email":"john@example.com"}。
import org.apache.http.HttpEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import com.fasterxml.jackson.databind.ObjectMapper;
import java.io.IOException;
public class ManualRestClientExample {
public static void main(String[] args) {
// 1. 创建 HttpClient 实例
try (CloseableHttpClient httpClient = HttpClients.createDefault()) {
// 2. 创建 HTTP GET 请求
String apiUrl = "http://api.example.com/users/1";
HttpGet request = new HttpGet(apiUrl);
// 3. 发送请求并获取响应
try (CloseableHttpResponse response = httpClient.execute(request)) {
// 4. 检查响应状态码
System.out.println("Response Code: " + response.getStatusLine().getStatusCode());
// 5. 获取响应实体 (JSON 字符串)
HttpEntity entity = response.getEntity();
if (entity != null) {
String jsonString = EntityUtils.toString(entity);
System.out.println("JSON Response: " + jsonString);
// 6. 使用 Jackson 解析 JSON
ObjectMapper mapper = new ObjectMapper();
User user = mapper.readValue(jsonString, User.class);
System.out.println("\nParsed User Object:");
System.out.println("ID: " + user.getId());
System.out.println("Name: " + user.getName());
System.out.println("Email: " + user.getEmail());
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
// 定义一个与 JSON 结构对应的 Java 类
static class User {
private int id;
private String name;
private String email;
// Getters and Setters (必须有)
public int getId() { return id; }
public void setId(int id) { this.id = id; }
public String getName() { return name; }
public void setName(String name) { this.name = name; }
public String getEmail() { return email; }
public void setEmail(String email) { this.email = email; }
}
}
总结与对比
| 特性 | JAX-WS (wsimport) | Apache CXF | 手动调用 |
|---|---|---|---|
| 易用性 | 高,标准流程,生成代码后调用简单 | 高,JaxWsProxyFactoryBean 无需生成代码 |
低,需要手动处理 HTTP 和 XML/JSON |
| 依赖 | 仅 JDK | 需要 CXF 库 | 需要 HttpClient 和 JSON/XML 解析库 |
| 灵活性 | 低,严格遵循 WSDL | 高,支持多种标准和协议 | 极高,可控制所有细节 |
| 适用场景 | 调用基于 SOAP 协议的传统 WebService | 企业级应用,需要 WS-* 安全、事务等特性 | 调用 RESTful API,或 SOAP 协议非常特殊/复杂 |
| 性能 | 好 | 好 | 取决于 HTTP 客户端和解析库的性能 |
如何选择?
- 如果你调用的是一个标准的、有 WSDL 文件的 SOAP WebService,并且希望快速实现,请选择 JAX-WS。 这是业界最标准的做法。
- 如果你的项目已经使用了 Spring,或者你需要用到 JAX-RS (REST) 以及 WS-Security 等高级特性,请选择 Apache CXF。 它的生态更强大,集成更方便。
- 如果你调用的是 RESTful API,或者 SOAP 请求非常特殊,无法通过标准工具生成客户端,请选择手动调用。 这虽然麻烦,但最可控。
