Java Web Service 完整教程
目录
- 第一部分:基础概念
- 什么是 Web Service?
- 为什么使用 Web Service?
- Web Service 的核心特点(SOAP vs. REST)
- 第二部分:SOAP Web Service
- 核心概念:SOAP, WSDL, UDDI
- 使用 JAX-WS (Java API for XML Web Services) 开发 SOAP Service
- 自上而下 (Top-Down)
- 自下而上 (Bottom-Up) - 推荐
- 使用 CXF 框架发布和调用 SOAP Service
- 第三部分:RESTful Web Service
- 什么是 REST?
- RESTful API 的核心原则
- 使用 JAX-RS (Java API for RESTful Web Services) 开发 RESTful Service
- 入门示例:使用 Jersey 框架
- 常用注解详解
- 处理不同数据格式(JSON, XML)
- 第四部分:实战项目
- 项目概述:用户管理 RESTful API
- 环境搭建
- 实现步骤
- 第五部分:进阶与总结
- 选择 SOAP 还是 REST?
- 常用框架对比
- 安全性、性能与监控
- 总结与学习资源
第一部分:基础概念
什么是 Web Service?
Web Service 是一种基于 Web 的、跨平台的、跨语言的应用程序交互技术,它允许不同的应用程序在不同的操作系统上,使用不同的编程语言进行通信和交换数据。

你可以把它想象成一个“网络上的函数调用”,你的本地应用(比如一个网站或手机 App)可以通过网络调用一个远程服务器上的服务,获取数据或执行某个操作,就像调用本地方法一样简单。
为什么使用 Web Service?
- 跨平台和跨语言:服务端可以用 Java 写,客户端可以用 Python、C#、JavaScript 写,只要它们都遵循相同的通信协议。
- 松耦合:客户端和服务端是独立的,可以独立开发和部署,一方升级或改变,只要接口不变,另一方通常不受影响。
- 可复用性:一个通用的服务(如天气预报、用户认证)可以被多个不同的应用调用。
- 基于标准:依赖于 HTTP、XML、JSON 等开放标准,易于理解和实现。
Web Service 的核心特点:SOAP vs. REST
这是 Web Service 两种最主流的实现风格。
| 特性 | SOAP (Simple Object Access Protocol) | REST (Representational State Transfer) |
|---|---|---|
| 协议 | 严格的协议,基于 XML,有自己的规范(信封、头、体)。 | 不是协议,而是一种架构风格,基于 HTTP 协议。 |
| 数据格式 | 强制使用 XML。 | 灵活,常用 JSON、XML、Text 等,JSON 更常见。 |
| 标准 | 有自己的标准,如 WS-Security, WS-Addressing。 | 遵循 HTTP 标准(GET, POST, PUT, DELETE 等)。 |
| 接口定义 | 使用 WSDL (Web Services Description Language) 文件描述接口。 | 通常没有明确的接口定义文件,通过 URL 和 HTTP 动词来定义。 |
| 重量级 | 较为重量级,消息头和结构复杂,开销大。 | 轻量级,简单直接,开销小。 |
| 适用场景 | 企业级应用、需要高安全性、事务性、可靠性的场景(如银行、金融)。 | 公开 API、移动应用、Web 前后端分离、微服务。 |
第二部分:SOAP Web Service (使用 JAX-WS)
JAX-WS 是 Java 官方定义的用于创建 SOAP Web Service 的 API。
核心概念
- SOAP (Simple Object Access Protocol):一种基于 XML 的协议,用于在 Web 上交换结构化信息,它定义了一个消息框架,包括一个信封、一组编码规则、表示数据类型约定以及表示过程调用和响应的约定。
- WSDL (Web Services Description Language):一个 XML 文件,用于描述 Web Service 的功能,它告诉客户端:服务在哪里(URL)、叫什么名字、可以调用哪些方法、每个方法需要什么参数、返回什么类型的数据。
- UDDI (Universal Description, Discovery, and Integration):一个目录服务,用于发布和发现 Web Service,现在使用较少,我们通常直接提供 WSDL 文档。
实现方式:自下而上 - 推荐方式
这是最常见的方式,即先编写 Java 代码,然后由工具自动生成 WSDL。

步骤 1:创建 Maven 项目并添加依赖
pom.xml:
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.example</groupId>
<artifactId>soap-service</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<maven.compiler.source>11</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<!-- JAX-WS API -->
<dependency>
<groupId>javax.xml.ws</groupId>
<artifactId>jaxws-api</artifactId>
<version>2.3.1</version>
</dependency>
<!-- JAX-WS RI (Reference Implementation) -->
<dependency>
<groupId>com.sun.xml.ws</groupId>
<artifactId>jaxws-rt</artifactId>
<version>2.3.3</version>
</dependency>
</dependencies>
<build>
<plugins>
<!-- Maven 插件,用于将类编译成 Service -->
<plugin>
<groupId>org.jvnet.jax-ws-commons</groupId>
<artifactId>jaxws-maven-plugin</artifactId>
<version>2.3</version>
<executions>
<execution>
<goals>
<goal>wsimport</goal>
</goals>
</execution>
</executions>
<configuration>
<sourceSourceDir>src/main/java</sourceSourceDir>
<keep>true</keep>
</configuration>
</plugin>
</plugins>
</build>
</project>
步骤 2:创建 Service Endpoint Interface (SEI)
这是一个 Java 接口,定义了 Web Service 将要暴露的方法。
src/main/java/com/example/HelloService.java:
import javax.jws.WebMethod;
import javax.jws.WebParam;
import javax.jws.WebService;
import javax.jws.soap.SOAPBinding;
// @WebService 注解表明这是一个 Web Service
@WebService
// @SOAPBinding(style = SOAPBinding.Style.RPC) 表示 RPC 风格,默认是 DOCUMENT
public interface HelloService {
// @WebMethod 注解将此方法暴露为 Web Service 的一个操作
@WebMethod
String sayHello(@WebParam(name = "name") String name);
}
步骤 3:创建 Service Implementation Bean (SIB)
这是实现 SEI 接口的类。

src/main/java/com/example/HelloServiceImpl.java:
import javax.jws.WebService;
// @WebService(endpointInterface = "com.example.HelloService") 指定实现的接口
@WebService(endpointInterface = "com.example.HelloService")
public class HelloServiceImpl implements HelloService {
@Override
public String sayHello(String name) {
return "Hello, " + name + "!";
}
}
步骤 4:发布 Web Service
我们可以编写一个 main 方法来发布服务,也可以部署到 Servlet 容器(如 Tomcat)中。
src/main/java/com/example/Publisher.java:
import javax.xml.ws.Endpoint;
import com.example.HelloServiceImpl;
public class Publisher {
public static void main(String[] args) {
// 创建服务的实现实例
HelloServiceImpl helloService = new HelloServiceImpl();
// 发布服务到指定地址
// 第一个参数是服务的访问地址,第二个参数是服务的实现对象
Endpoint.publish("http://localhost:8888/hello", helloService);
System.out.println("SOAP Web Service is published at http://localhost:8888/hello?wsdl");
}
}
运行 Publisher 类,你的 SOAP 服务就启动了。
步骤 5:测试服务
- 在浏览器中访问
http://localhost:8888/hello?wsdl,你会看到一个 XML 文件,这就是 WSDL,它描述了你的服务。 - 使用工具测试,如 SoapUI 或 Postman。
- 在 SoapUI 中,创建新的 SOAP Project,将 WSDL 的 URL 粘贴进去。
- 工具会自动解析出
sayHello操作。 - 在请求中填入参数(
<name>World</name>),然后发送请求,你会收到<return>Hello, World!</return>的响应。
第三部分:RESTful Web Service (使用 JAX-RS)
REST 架构风格是目前 Web Service 的主流,尤其适用于移动端和前后端分离的项目。
核心概念
- 资源:在 REST 中,一切皆资源,每个资源都有一个唯一的 URI(统一资源标识符),用户资源可以是
/users,特定用户可以是/users/123。 - 统一接口:使用标准的 HTTP 方法来操作资源。
GET:获取资源POST:创建新资源PUT:更新资源(全量更新)DELETE:删除资源PATCH:部分更新资源
- 无状态:服务器不保存客户端的状态,每个请求都必须包含处理该请求所需的所有信息。
- 表现层:资源可以有多种表现形式,如 JSON、XML、HTML 等,客户端通过
Accept请求头告诉服务器它希望接收哪种格式,服务器通过Content-Type响应头告诉客户端它返回的是什么格式。
实现方式:使用 Jersey 框架
Jersey 是 JAX-RS 规范最流行的参考实现之一。
步骤 1:创建 Maven 项目并添加依赖
pom.xml:
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.example</groupId>
<artifactId>rest-service</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<maven.compiler.source>11</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<!-- Jersey 核心依赖 -->
<dependency>
<groupId>org.glassfish.jersey.containers</groupId>
<artifactId>jersey-container-grizzly2-http</artifactId>
<version>2.35</version>
</dependency>
<!-- 支持 JSON -->
<dependency>
<groupId>org.glassfish.jersey.media</groupId>
<artifactId>jersey-media-json-binding</artifactId>
<version>2.35</version>
</dependency>
</dependencies>
</project>
步骤 2:创建资源类
这是一个普通的 Java 类,用 JAX-RS 注解来映射到 URI 和 HTTP 方法。
src/main/java/com/example/Resource.java:
import javax.ws.rs.*;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
// @Path 注解定义了这个类的 URI 基础路径
@Path("/hello")
public class Resource {
// @GET 注解表示这个方法处理 HTTP GET 请求
// @Produces 注解指定该方法返回的媒体类型
@GET
@Produces(MediaType.TEXT_PLAIN)
public String getPlainText() {
return "Hello, World in Plain Text!";
}
@GET
@Produces(MediaType.APPLICATION_JSON)
public String getJson() {
// 在实际应用中,这里会返回一个对象,Jersey 会自动将其转换为 JSON
return "{\"message\": \"Hello, World in JSON!\"}";
}
// 路径参数
@GET
@Path("/{name}")
@Produces(MediaType.TEXT_PLAIN)
public sayHelloToName(@PathParam("name") String name) {
return "Hello, " + name + "!";
}
// 处理 POST 请求
@POST
@Path("/echo")
@Consumes(MediaType.APPLICATION_JSON) // 指定该方法能接受的媒体类型
@Produces(MediaType.APPLICATION_JSON)
public Response echoJson(String jsonInput) {
// 在实际应用中,这里会解析 jsonInput,处理业务逻辑,然后返回结果
System.out.println("Received JSON: " + jsonInput);
String responseJson = "{\"status\": \"success\", \"received\": " + jsonInput + "}";
// 返回一个 Response 对象,可以设置状态码等
return Response.status(200).entity(responseJson).build();
}
}
步骤 3:启动服务
src/main/java/com/example/Main.java:
import org.glassfish.grizzly.http.server.HttpServer;
import org.glassfish.jersey.grizzly2.httpserver.GrizzlyHttpServerFactory;
import org.glassfish.jersey.server.ResourceConfig;
import java.net.URI;
public class Main {
// 定义服务的基地 URI
public static final String BASE_URI = "http://localhost:8080/myapp/";
public static void main(String[] args) {
// 创建一个 ResourceConfig 实例,并注册我们的资源类
ResourceConfig config = new ResourceConfig().packages("com.example");
// 创建并启动 Grizzly HTTP 服务器
HttpServer server = GrizzlyHttpServerFactory.createHttpServer(URI.create(BASE_URI), config);
System.out.println("Jersey app started with WADL available at "
+ BASE_URI + "application.wadl\nHit enter to stop it...");
try {
System.in.read();
} catch (Exception e) {
e.printStackTrace();
} finally {
server.shutdownNow();
}
}
}
步骤 4:测试服务
运行 Main 类,然后使用 Postman 或浏览器进行测试。
GET http://localhost:8080/myapp/hello-> 返回纯文本GET http://localhost:8080/myapp/hello(在 Postman 中设置 Accept 为application/json) -> 返回 JSONGET http://localhost:8080/myapp/hello/Alice-> 返回 "Hello, Alice!"POST http://localhost:8080/myapp/hello/echo- 在 Body 中选择 raw -> JSON,输入:
{"user": "Bob"} - 设置 Content-Type 为
application/json - 发送请求,服务器会返回:
{"status": "success", "received": {"user": "Bob"}}
- 在 Body 中选择 raw -> JSON,输入:
第四部分:实战项目 - 用户管理 RESTful API
我们将创建一个简单的内存版用户管理 API。
- 环境:继续使用 Jersey + Maven 项目。
- 依赖:
pom.xml与上面 REST 示例相同。 - 模型:
User.javapublic class User { private int id; private String name; private String email; // 构造器、Getters、Setters、toString() // 为了简化,省略了 Lombok public User(int id, String name, String email) { this.id = id; this.name = name; this.email = email; } // ... getters and setters } - 资源:
UserResource.javaimport javax.ws.rs.*; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; import java.util.ArrayList; import java.util.List; import java.util.stream.Collectors;
@Path("/users") public class UserResource {
private static List<User> users = new ArrayList<>();
static {
users.add(new User(1, "Alice", "alice@example.com"));
users.add(new User(2, "Bob", "bob@example.com"));
}
@GET
@Produces(MediaType.APPLICATION_JSON)
public List<User> getAllUsers() {
return users;
}
@GET
@Path("/{id}")
@Produces(MediaType.APPLICATION_JSON)
public Response getUserById(@PathParam("id") int id) {
User user = users.stream()
.filter(u -> u.getId() == id)
.findFirst()
.orElse(null);
if (user == null) {
// 返回 404 Not Found
return Response.status(Response.Status.NOT_FOUND).build();
}
return Response.ok(user).build();
}
@POST
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
public Response createUser(User newUser) {
// 简单起见,假设新用户没有 ID
int newId = users.stream().mapToInt(User::getId).max().orElse(0) + 1;
newUser.setId(newId);
users.add(newUser);
// 返回 201 Created,并包含新创建的用户
return Response.status(Response.Status.CREATED).entity(newUser).build();
}
@DELETE
@Path("/{id}")
public Response deleteUser(@PathParam("id") int id) {
boolean removed = users.removeIf(u -> u.getId() == id);
if (removed) {
return Response.noContent().build(); // 204 No Content
} else {
return Response.status(Response.Status.NOT_FOUND).build();
}
}
```
- 启动:使用与
Main.java相同的代码启动服务。 - 测试:
GET http://localhost:8080/myapp/users-> 获取所有用户列表。POST http://localhost:8080/myapp/users-> Body:{"name": "Charlie", "email": "charlie@example.com"},返回新创建的用户(包含 ID)。GET http://localhost:8080/myapp/users/3-> 获取 ID 为 3 的用户。DELETE http://localhost:8080/myapp/users/1-> 删除 ID 为 1 的用户。
第五部分:进阶与总结
选择 SOAP 还是 REST?
-
选择 SOAP:
- 你需要处理复杂的交易(如银行转账)。
- 需要高级的 WS-* 标准(如 WS-Security, WS-ReliableMessaging)。
- 你的公司或合作伙伴已经广泛使用 SOAP。
- 你需要一个强契约(WSDL)来严格定义接口。
-
选择 REST:
- 你正在开发公开 API 供移动端或前端使用。
- 你追求简单、轻量和性能。
- 你需要利用 HTTP 的特性(如缓存、重定向)。
- 你的应用是微服务架构的一部分。
目前超过 90% 的新 Web Service 项目会选择 RESTful 风格。
常用框架对比
| 类型 | SOAP | REST |
|---|---|---|
| 核心 API | JAX-WS | JAX-RS |
| SOAP 实现 | Apache CXF, Metro (GlassFish) | - |
| REST 实现 | - | Jersey (Reference), RESTEasy (JBoss/WildFly), Apache CXF (也支持 REST) |
对于 REST,Jersey 和 RESTEasy 是最主流的选择,Spring Boot 也内置了对 JAX-RS 的支持,并提供了更强大的 Spring MVC RESTful 开发方式,这也是一个非常流行的选择。
安全性、性能与监控
- 安全性:
- SOAP: 内置 WS-Security 标准,支持 XML 签名、加密等,非常强大。
- REST: 通常使用标准的 Web 安全机制,如 HTTPS、OAuth 2.0、JWT (JSON Web Tokens)、API Key 等。
- 性能:
REST 通常比 SOAP 性能更好,因为消息体更小(JSON vs XML),没有额外的 SOAP 信封开销。
- 监控:
无论哪种风格,都需要对 API 进行监控,可以使用工具如 Prometheus + Grafana, ELK Stack, 或商业 API 网关(如 Kong, Apigee)来跟踪请求量、响应时间、错误率等。
总结与学习资源
Java Web Service 技术已经非常成熟,从最初的 SOAP 到如今主导的 RESTful,核心思想都是让应用之间能够通过网络进行高效、标准化的通信。
-
学习建议:
- 打好基础:深入理解 HTTP 协议、XML 和 JSON。
- 从 REST 开始:对于大多数现代开发者,掌握 JAX-RS (如 Jersey) 和 RESTful 设计原则是首要任务。
- 了解 SOAP:不要完全抛弃 SOAP,了解其原理和适用场景,在企业级项目中你可能会遇到。
- 学习框架:深入一个主流框架(如 Jersey 或 Spring Boot),并学习其高级特性(如依赖注入、AOP、过滤器等)。
- 实践项目:通过动手实践来巩固知识,比如构建一个完整的 CRUD API。
-
学习资源:
- 官方文档:JAX-WS (Oracle), JAX-RS (Oracle), Jersey Documentation
- 优秀教程:Baeldung (有大量关于 JAX-RS, Spring REST 的教程)
- 书籍:《RESTful Web Services》, 《Java Web Services: Up and Running》
- 社区:Stack Overflow, GitHub
希望这份详尽的教程能帮助你顺利入门并掌握 Java Web Service 开发!
