核心概念
在开始之前,我们先理解几个关键概念:

- WebService: 一种跨编程语言、跨操作系统平台的远程调用技术,它使用 XML 进行数据交换,并通过 SOAP (Simple Object Access Protocol) 协议在网络上传输。
- SOAP (Simple Object Access Protocol): 用于交换结构化信息的协议,它基于 XML,独立于平台和语言。
- WSDL (Web Services Description Language): 一个 XML 文件,用于描述 WebService 的功能、接口、参数、返回值以及如何访问它,你可以把它理解成 WebService 的“说明书”。
- Endpoint (端点): WebService 的访问地址,通常是一个 URL。
JAX-WS (Java API for XML Web Services) - 现代、主流
这是目前 Java 官方推荐的标准,用于构建和消费 SOAP WebService,它极大地简化了开发过程,你只需要关注业务逻辑,而不用关心底层的 XML 和 SOAP 消息。
JAX-WS 是 Java EE 的一部分,现在也包含在 Jakarta EE 中,主流的实现有 Metro (GlassFish) 和 Apache CXF。
这里我们使用 JDK 自带的 wsimport 工具 和 Metro 来演示,因为它最简单,无需额外引入复杂的框架。
服务端实现
目标: 创建一个提供查询用户信息的 WebService。

步骤:
第一步:创建一个标准的 Java 项目
使用你喜欢的 IDE (如 IntelliJ IDEA, Eclipse) 创建一个 Maven 或 Gradle 项目。
第二步:定义服务接口和实现类

你需要一个接口(或一个类)来定义 WebService 的方法。
UserService.java (接口)
import javax.jws.WebMethod;
import javax.jws.WebParam;
import javax.jws.WebService;
import javax.jws.soap.SOAPBinding;
// @WebService 注解将这个类标记为一个 WebService
@WebService
// @SOAPBinding 指定 SOAP 协议的样式,默认是 DOCUMENT
@SOAPBinding(style = SOAPBinding.Style.DOCUMENT)
public interface UserService {
// @WebMethod 将此方法暴露为 WebService 的一个操作
// @WebParam 指定参数的名称
@WebMethod
String getUserInfo(@WebParam(name = "userId") String userId);
}
UserServiceImpl.java (实现类)
import javax.jws.WebService;
// 注意:实现类需要使用 @WebService 注解,并指定 endpointInterface 属性
// 这表示这个类实现了上面定义的接口
@WebService(endpointInterface = "com.example.webservice.UserService")
public class UserServiceImpl implements UserService {
@Override
public String getUserInfo(String userId) {
// 模拟业务逻辑
if ("001".equals(userId)) {
return "User ID: 001, Name: Alice, Email: alice@example.com";
} else if ("002".equals(userId)) {
return "User ID: 002, Name: Bob, Email: bob@example.com";
} else {
return "User not found with ID: " + userId;
}
}
}
第三步:发布 WebService
你需要一个主类来启动一个内嵌的 HTTP 服务器,并将你的服务发布上去。
Publisher.java
import javax.xml.ws.Endpoint;
public class Publisher {
public static void main(String[] args) {
// 创建服务实现类的实例
UserServiceImpl userServiceImpl = new UserServiceImpl();
// 定义服务的访问地址 (Endpoint URL)
String address = "http://localhost:8888/ws/user";
// 发布服务
Endpoint.publish(address, userServiceImpl);
System.out.println("WebService is published at: " + address);
System.out.println("You can access the WSDL at: " + address + "?wsdl");
}
}
第四步:运行和测试
- 运行
Publisher.java的main方法。 - 打开浏览器,访问
http://localhost:8888/ws/user?wsdl。 - 如果看到一个 XML 文件(即 WSDL 文件),说明你的 WebService 发布成功了!
客户端实现
目标: 创建一个客户端程序来调用上面发布的 WebService。
步骤:
第一步:使用 wsimport 生成客户端代码
wsimport 是 JDK 自带的工具,可以根据 WSDL 文件生成客户端所需的 Java 代码(存根和框架)。
打开你的终端(或命令提示符),进入到客户端项目的 src/main/java 目录下,执行以下命令:
wsimport -keep -p com.example.webservice.client http://localhost:8888/ws/user?wsdl
-keep: 生成源代码。-p com.example.webservice.client: 指定生成代码的包名。http://...?wsdl: WSDL 文件的 URL。
执行后,会在你指定的包下生成一堆 .java 文件(如 UserService.java, UserService_Service.java, UserInfo.java 等)。
第二步:编写客户端调用代码
你可以像调用本地方法一样调用远程的 WebService 了。
WebServiceClient.java
import com.example.webservice.client.UserService;
import com.example.webservice.client.UserService_Service;
public class WebServiceClient {
public static void main(String[] args) {
// 通过 Service 类创建一个服务的代理
UserService_Service service = new UserService_Service();
// 从 Service 中获取 Port(端口),即服务的实现
UserService userService = service.getUserServicePort();
// 调用远程方法
String response1 = userService.getUserInfo("001");
System.out.println("Response for '001': " + response1);
String response2 = userService.getUserInfo("002");
System.out.println("Response for '002': " + response2);
String response3 = userService.getUserInfo("003");
System.out.println("Response for '003': " + response3);
}
}
第三步:运行客户端
运行 WebServiceClient.java,你将看到从服务端返回的结果。
Spring Boot + JAX-WS (更现代的整合方式)
在 Spring Boot 项目中集成 JAX-WS,可以更好地利用 Spring 的生态系统(如依赖注入、事务管理等)。
服务端实现 (Spring Boot):
-
添加依赖 在
pom.xml中添加cxf-spring-boot-starter-jaxws。<dependency> <groupId>org.apache.cxf</groupId> <artifactId>cxf-spring-boot-starter-jaxws</artifactId> <version>3.4.5</version> <!-- 请使用最新版本 --> </dependency> -
配置 Endpoint 创建一个配置类来发布你的服务。
import com.example.webservice.UserService; import com.example.webservice.UserServiceImpl; import org.apache.cxf.jaxws.EndpointImpl; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import javax.xml.ws.Endpoint; @Configuration public class CxfConfig { @Bean public UserService userService() { return new UserServiceImpl(); } @Bean public Endpoint endpoint() { EndpointImpl endpoint = new EndpointImpl(springApplicationContext(), userService()); endpoint.publish("/user"); // 发布路径 return endpoint; } // 获取 Spring 应用上下文,CXF 需要它来注入依赖 @Bean public org.springframework.context.ApplicationContext springApplicationContext() { return new org.springframework.context.annotation.AnnotationConfigApplicationContext(); } } -
访问地址 启动 Spring Boot 应用后,服务会自动发布在
http://<your-host>:<port>/user?wsdl。
JAX-RS (Java API for RESTful Web Services) - 现代、轻量级
虽然你问的是 WebService,但很多时候大家说的其实是 RESTful WebService,它更轻量、更简单,基于 HTTP 协议,使用 JSON 数据格式,是目前 Web API 的主流。
服务端实现 (Spring Boot + JAX-RS - 例如使用 RESTEasy)
-
添加依赖
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <!-- 如果你需要 JAX-RS 的特定实现,RESTEasy --> <dependency> <groupId>org.jboss.resteasy</groupId> <artifactId>resteasy-spring-boot-starter</artifactId> <version>3.15.1.Final</version> </dependency> -
创建资源类
import org.springframework.web.bind.annotation.*; // @RestController = @Controller + @ResponseBody @RestController @RequestMapping("/api/users") // 对应 REST 的路径 public class UserResource { // @GetMapping 对应 HTTP GET 请求 @GetMapping("/{userId}") public String getUserInfo(@PathVariable String userId) { if ("001".equals(userId)) { return "User ID: 001, Name: Alice, Email: alice@example.com (from REST)"; } return "User not found with ID: " + userId; } } -
测试 启动应用,访问
http://localhost:8080/api/users/001,浏览器会直接返回 JSON 格式的字符串。
客户端实现 (Spring Boot + RestTemplate 或 WebClient)
使用 RestTemplate (传统) 或 WebClient (响应式,推荐) 来调用 REST API。
import org.springframework.web.client.RestTemplate;
public class RestApiClient {
public static void main(String[] args) {
RestTemplate restTemplate = new RestTemplate();
String url = "http://localhost:8080/api/users/001";
// 直接发送 GET 请求,并接收响应体 (String)
String response = restTemplate.getForObject(url, String.class);
System.out.println("REST API Response: " + response);
}
}
Apache Axis2 (经典、功能强大)
这是一个非常老牌且功能强大的框架,支持 SOAP 1.1, 1.2 和 RESTful 风格,它的架构比 JAX-WS 更灵活,但配置也更复杂。对于新项目,一般不推荐,除非需要处理非常复杂的遗留系统或特定需求。
服务端实现 (Axis2) 大致步骤:
- 下载并解压 Axis2。
- 创建服务存档:将你的服务类和依赖打包成一个
.aar(Axis2 Archive) 文件。 - 部署服务:将
.aar文件放到 Axis2 的repository/services目录下。 - 启动 Axis2 服务器。
- 访问
http://localhost:8080/axis2/services/listServices查看已部署的服务。
总结与对比
| 特性 | JAX-WS (标准) | Spring Boot + JAX-WS | JAX-RS (RESTful) | Apache Axis2 |
|---|---|---|---|---|
| 协议 | SOAP | SOAP | HTTP (JSON) | SOAP, REST |
| 数据格式 | XML | XML | JSON, XML, Text | XML, JSON 等 |
| 复杂度 | 中等 | 中等 (依赖 Spring) | 低 | 高 |
| 性能 | 较低 (XML 解析开销) | 较低 | 高 | 较低 |
| 适用场景 | 企业级应用、与遗留系统集成、需要强类型契约 | 基于 Spring 生态的 SOAP 服务 | 现代 Web API、移动端后端、微服务 | 遗留系统维护、复杂 SOAP 处理 |
| 推荐度 | 推荐 (如果必须用 SOAP) | 推荐 (如果项目已经是 Spring) | 强烈推荐 (对于新项目) | 不推荐 (除非特殊需求) |
- 如果你的项目 必须使用 SOAP 协议,请选择 JAX-WS,如果是 Spring 项目,优先考虑 Spring Boot + JAX-WS。
- 如果你正在构建一个新的 Web API,并且没有历史包袱,请选择 JAX-RS (RESTful),这是当前业界的事实标准。
- Apache Axis2 可以作为一个备选,用于处理复杂的 SOAP 场景或维护旧系统,但对于新项目来说过于笨重。
