目录
- 什么是 WebService?
- 为什么使用 WebService?
- WebService 的两种主流实现方式
- 1. SOAP (JAX-WS)
- 2. REST (Spring Web)
- 实战教程:使用 JAX-WS 创建 SOAP WebService
- 1. 环境准备
- 2. 创建服务端
- 3. 创建客户端
- 4. 运行和测试
- 实战教程:使用 Spring Boot 创建 RESTful WebService
- 1. 环境准备
- 2. 创建项目
- 3. 编写 Controller
- 4. 启动和测试
- JAX-WS vs REST (Spring Web) 如何选择?
- 总结与进阶
什么是 WebService?
WebService 是一种跨编程语言和跨操作系统平台的远程调用技术,它允许你通过 网络 使用 HTTP 协议 调用另一个系统的服务,就像调用本地方法一样。

WebService 就是一个“网络上的服务”,它暴露了一个或多个可以远程调用的方法。
为什么使用 WebService?
- 系统解耦:不同系统(如 Java 和 .NET)可以通过 WebService 进行通信,而不需要关心对方内部的技术实现。
- 跨平台/跨语言:WebService 基于 XML (SOAP) 或 JSON (REST) 作为数据交换格式,任何支持这些格式的语言都可以成为客户端或服务端。
- 可复用性:可以将通用的业务逻辑封装成 WebService,供多个应用调用,避免重复开发。
WebService 的两种主流实现方式
WebService 主要有两种风格:SOAP 和 REST,它们在理念、格式和使用场景上都有很大不同。
1. SOAP (JAX-WS)
- 概念:SOAP (Simple Object Access Protocol) 是一个协议,它定义了一套非常严格的、基于 XML 的消息格式,它有自己的规范,不仅仅是 RPC(远程过程调用)。
- 特点:
- 格式严格:消息必须是格式良好的 XML。
- 重量级:由于 XML 标签多,消息体积较大,解析速度相对较慢。
- 标准化:拥有完善的标准(如 WS-Security, WS-Addressing 等),支持事务、安全等企业级特性。
- 平台无关:通过 WSDL (Web Services Description Language) 文件描述服务接口,客户端可以根据 WSDL 生成调用代码。
- Java 实现:JAX-WS (Java API for XML Web Services) 是 Java 官方提供的一套用于开发 SOAP WebService 的 API,它简化了开发过程,你只需要用注解来标注你的 Java 类和方法,JAX-WS 运行时会帮你处理底层的 XML 转换和网络通信。
- 适用场景:企业级应用、银行、金融、电信等对安全性、事务性要求高的场景。
2. REST (Spring Web)
- 概念:REST (Representational State Transfer) 不是一种标准,而是一种软件架构风格,它更轻量级,更符合 Web 的原生理念。
- 特点:
- 格式灵活:通常使用 JSON 作为数据交换格式,XML 也可以,JSON 更轻便,解析更快。
- 轻量级:没有复杂的 XML 包裹,数据直接,网络开销小。
- 无状态:服务器不保存客户端的状态,每次请求都包含所有必要信息。
- 资源导向:将一切视为资源,通过 URL 来定位资源,使用 HTTP 动词(GET, POST, PUT, DELETE)来操作资源。
- Java 实现:在 Java 生态中,Spring Web (Spring MVC / Spring Boot) 是实现 RESTful 风格 WebService 的绝对主流,它通过
@RestController、@GetMapping、@PostMapping等注解,让你能非常方便地创建 REST API。 - 适用场景:Web 应用的前后端分离、移动 App 后端、微服务之间的通信等绝大多数现代 Web 开发场景。
实战教程:使用 JAX-WS 创建 SOAP WebService
我们将创建一个简单的计算器服务,提供 add 和 subtract 方法。
1. 环境准备
- JDK 8 或更高版本
- Maven (用于项目管理)
- IDE (如 IntelliJ IDEA 或 Eclipse)
2. 创建服务端
步骤 1:创建 Maven 项目

创建一个普通的 Maven Java 项目。
步骤 2:添加依赖
在 pom.xml 中添加 JAX-WS 运行时依赖,我们使用 com.sun.xml.ws:jaxws-rt,这是 JAX-WS 的参考实现。
<dependencies>
<!-- JAX-WS Runtime -->
<dependency>
<groupId>com.sun.xml.ws</groupId>
<artifactId>jaxws-rt</artifactId>
<version>4.0.1</version>
</dependency>
</dependencies>
步骤 3:创建服务接口和实现

定义一个服务接口,并用 JAX-WS 的注解来标记它。
src/main/java/com/example/webservice/Calculator.java
import javax.jws.WebMethod;
import javax.jws.WebService;
import javax.jws.soap.SOAPBinding;
// @WebService: 将这个类标记为一个 WebService
@WebService
// @SOAPBinding: 定义 SOAP 消息的风格,默认是 DOCUMENT,这里明确为 RPC 风格
@SOAPBinding(style = SOAPBinding.Style.RPC)
public interface Calculator {
// @WebMethod: 将这个公共方法暴露为 WebService 的一个操作
@WebMethod
int add(int a, int b);
@WebMethod
int subtract(int a, int b);
}
创建这个接口的实现类。
src/main/java/com/example/webservice/CalculatorImpl.java
import javax.jws.WebService;
// 注意:实现类不需要添加 @WebService 注解
@WebService(endpointInterface = "com.example.webservice.Calculator")
public class CalculatorImpl implements Calculator {
@Override
public int add(int a, int b) {
System.out.println("WebService is adding " + a + " and " + b);
return a + b;
}
@Override
public int subtract(int a, int b) {
System.out.println("WebService is subtracting " + b + " from " + a);
return a - b;
}
}
步骤 4:发布 WebService
创建一个主类来启动和发布我们的服务。
src/main/java/com/example/webservice/CalculatorPublisher.java
import javax.xml.ws.Endpoint;
public class CalculatorPublisher {
public static void main(String[] args) {
// 定义服务的发布地址
String address = "http://localhost:8888/calculator";
// 创建服务实现实例
CalculatorImpl calculator = new CalculatorImpl();
// 发布服务
Endpoint.publish(address, calculator);
System.out.println("Calculator WebService is published at: " + address);
}
}
步骤 5:运行服务端
运行 CalculatorPublisher 的 main 方法,如果一切顺利,你会在控制台看到:
Calculator WebService is published at: http://localhost:8888/calculator
你的 SOAP WebService 已经成功启动了!你可以访问 http://localhost:8888/calculator?wsdl 来查看服务的 WSDL 描述文件。
3. 创建客户端
创建一个新的 Maven 项目(或同一个项目的另一个模块)。
步骤 1:添加依赖
与服务端相同的依赖。
步骤 2:使用 WSDL 生成客户端代码
最简单的方式是使用 JDK 自带的 wsimport 工具,打开命令行,进入客户端项目的 src/main/java 目录,执行以下命令:
wsimport -keep -p com.example.webservice.client http://localhost:8888/calculator?wsdl
-keep: 生成源代码。-p com.example.webservice.client: 指定生成代码的包名。http://...: WSDL 文件的地址。
执行后,会生成一堆 Java 文件(.class 和 .java),这些就是客户端代理代码。
步骤 3:编写客户端调用代码
src/main/java/com/example/webservice/client/CalculatorClient.java
public class CalculatorClient {
public static void main(String[] args) {
// 通过生成的 Service 类来获取 Port(即服务的代理对象)
CalculatorService service = new CalculatorService();
Calculator calculatorProxy = service.getCalculatorPort();
// 像调用本地方法一样调用远程服务
int sum = calculatorProxy.add(10, 25);
System.out.println("10 + 25 = " + sum);
int difference = calculatorProxy.subtract(100, 50);
System.out.println("100 - 50 = " + difference);
}
}
步骤 4:运行客户端
运行 CalculatorClient 的 main 方法,你会看到输出:
10 + 25 = 35
100 - 50 = 50
服务端控制台也会打印出相应的日志。
实战教程:使用 Spring Boot 创建 RESTful WebService
这是目前更流行、更简单的方式。
1. 环境准备
- JDK 8 或更高版本
- Maven 或 Gradle
- IDE
2. 创建项目
最简单的方式是使用 Spring Initializr (https://start.spring.io)。
- Project: Maven Project
- Language: Java
- Spring Boot: 选择一个稳定版本 (如 3.x.x)
- Project Metadata:
- Group:
com.example - Artifact:
rest-webservice - Name:
rest-webservice - Packaging: Jar
- Java: 17 (或你的版本)
- Group:
- Dependencies: 添加
Spring Web依赖。
点击 "GENERATE" 下载项目,并用你的 IDE 打开。
3. 编写 Controller**
创建一个 Controller 类来处理 HTTP 请求。
src/main/java/com/example/restwebservice/StudentController.java
import org.springframework.web.bind.annotation.*;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
// @RestController: 组合了 @Controller 和 @ResponseBody,表示这个类中的所有方法返回的数据都直接写入 HTTP 响应体中
@RestController
// @RequestMapping: 为这个控制器下的所有请求提供一个基础路径
@RequestMapping("/api/students")
public class StudentController {
// 模拟一个数据源
private List<Student> studentList = new ArrayList<>(List.of(
new Student(1, "张三"),
new Student(2, "李四")
));
// @GetMapping: 处理 HTTP GET 请求
@GetMapping
public List<Student> getAllStudents() {
System.out.println("Getting all students...");
return studentList;
}
// @GetMapping("/{id}": 处理带路径变量的 GET 请求,/api/students/1
@GetMapping("/{id}")
public Student getStudentById(@PathVariable int id) {
System.out.println("Getting student with id: " + id);
// 使用 Java 8 的 Stream API 查找学生
return studentList.stream()
.filter(s -> s.getId() == id)
.findFirst()
.orElseThrow(() -> new RuntimeException("Student not found with id: " + id));
}
// @PostMapping: 处理 HTTP POST 请求,用于创建新资源
@PostMapping
public Student createStudent(@RequestBody Student student) {
System.out.println("Creating student: " + student.getName());
// 在实际应用中,这里应该生成新的 ID 并保存到数据库
student.setId(studentList.size() + 1);
studentList.add(student);
return student;
}
// @PutMapping: 处理 HTTP PUT 请求,用于更新资源
@PutMapping("/{id}")
public Student updateStudent(@PathVariable int id, @RequestBody Student studentDetails) {
System.out.println("Updating student with id: " + id);
Student student = studentList.stream()
.filter(s -> s.getId() == id)
.findFirst()
.orElseThrow(() -> new RuntimeException("Student not found with id: " + id));
student.setName(studentDetails.getName());
return student;
}
// @DeleteMapping: 处理 HTTP DELETE 请求,用于删除资源
@DeleteMapping("/{id}")
public String deleteStudent(@PathVariable int id) {
System.out.println("Deleting student with id: " + id);
boolean removed = studentList.removeIf(s -> s.getId() == id);
if (!removed) {
throw new RuntimeException("Student not found with id: " + id);
}
return "Student with id " + id + " has been deleted.";
}
}
// 一个简单的 POJO (Plain Old Java Object)
class Student {
private int id;
private String name;
public Student() {}
public Student(int id, String name) {
this.id = id;
this.name = name;
}
// 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; }
}
4. 启动和测试
步骤 1:启动应用
找到主启动类(RestWebserviceApplication.java),右键运行 main 方法,Spring Boot 会启动一个内嵌的 Tomcat 服务器,默认监听 8080 端口。
步骤 2:使用 API 工具测试
强烈推荐使用 Postman 或 curl 来测试你的 API。
-
获取所有学生
- Method:
GET - URL:
http://localhost:8080/api/students - Response (JSON):
[ {"id":1,"name":"张三"}, {"id":2,"name":"李四"} ]
- Method:
-
根据 ID 获取学生
- Method:
GET - URL:
http://localhost:8080/api/students/1 - Response (JSON):
{"id":1,"name":"张三"}
- Method:
-
创建新学生
- Method:
POST - URL:
http://localhost:8080/api/students - Body (raw, JSON):
{"name":"王五"} - Response (JSON):
{"id":3,"name":"王五"}
- Method:
-
更新学生
- Method:
PUT - URL:
http://localhost:8080/api/students/1 - Body (raw, JSON):
{"name":"张三丰"} - Response (JSON):
{"id":1,"name":"张三丰"}
- Method:
-
删除学生
- Method:
DELETE - URL:
http://localhost:8080/api/students/2 - Response:
Student with id 2 has been deleted.
- Method:
JAX-WS vs REST (Spring Web) 如何选择?
| 特性 | JAX-WS (SOAP) | REST (Spring Web) |
|---|---|---|
| 本质 | 协议 | 架构风格 |
| 数据格式 | XML (严格) | JSON (主流), XML (可选) |
| 重量级 | 重 (XML标签多) | 轻 (JSON简洁) |
| 标准化 | 高 (WSDL, WS-*) | 低 (遵循HTTP标准,无统一规范) |
| 状态 | 无状态 | 无状态 |
| 安全性 | 内置复杂的安全标准 | 通常通过 HTTPS 和 OAuth2 等实现 |
| 工具支持 | 成熟,有WSDL自动生成客户端代码 | 依赖HTTP客户端库,手动构建请求 |
| 适用场景 | 企业级应用、金融、电信、需要强事务和WS-*标准的场景 | Web应用、移动后端、微服务、前后端分离项目 |
| 学习曲线 | 相对陡峭 | 相对平缓,更符合Web开发者直觉 |
一句话总结:
- 如果你的项目需要遵循严格的行业标准、处理复杂的事务和安全,并且可能需要与老式的 .NET 系统集成,选择 JAX-WS。
- 如果你正在开发现代 Web 应用,追求开发效率、轻量级通信,并且你的客户端是浏览器或移动 App,毫无疑问选择 REST (Spring Web)。
总结与进阶
-
本教程带你从零开始,分别用 Java 的原生 JAX-WS 技术和现代的 Spring Boot 框架实现了 WebService,理解 SOAP 和 REST 的区别以及它们各自的适用场景是成为一名合格 Java 后端开发者的关键技能。
-
进阶学习:
- JAX-WS 进阶:学习
@HandlerChain处理 SOAP 消息头、WS-Security 安全配置、异步调用等。 - REST 进阶:
- API 文档:学习使用 Swagger (OpenAPI) 自动生成和测试 API 文档。
- 数据验证:使用 Hibernate Validator 对请求数据进行校验。
- 全局异常处理:使用
@ControllerAdvice统一处理异常。 - API 版本控制:学习如何管理 API 的不同版本。
- 性能优化:了解 JSON 序列化库(如 Jackson)的配置和性能调优。
- JAX-WS 进阶:学习
希望这份详细的教程能帮助你顺利掌握 Java WebService 开发!
