- 什么是 WebService? (概念与核心思想)
- Java WebService 的演进史 (从 SOAP 到 REST)
- 主流的 Java WebService 技术栈
- JAX-WS (Java API for XML Web Services) - 用于 SOAP 服务
- JAX-RS (Java API for RESTful Web Services) - 用于 REST 服务
- 实战示例
- JAX-WS (使用 JDK 内置的
wsimport和Endpoint) - JAX-RS (使用流行的 Jersey 框架)
- JAX-WS (使用 JDK 内置的
- 如何选择? (SOAP vs REST)
- 现代趋势与替代方案
什么是 WebService?
WebService 是一种跨编程语言、跨操作系统的远程调用技术,它的核心思想是:

让不同平台、不同语言开发的应用程序,能够通过网络进行交互和数据交换。
WebService 的主要特点:
- 跨平台性:只要能通过网络发送和接收 XML 或 JSON 格式的数据,任何平台都可以调用 WebService。
- 基于标准:通常基于一些广泛接受的标准,如 HTTP、XML、SOAP、WSDL、UDDI(早期)等。
- 松耦合:服务提供方和服务调用方之间不需要知道对方的内部实现细节,只需约定好接口(通过 WSDL 或 API 文档)即可。
Java WebService 的演进史
Java WebService 技术主要经历了两个主要阶段:
SOAP 时代 (The Old Way)
- 协议:SOAP (Simple Object Access Protocol),它是一个基于 XML 的协议,非常“重量级”和“严谨”。
- 核心:服务端和客户端之间通过 XML 格式的 SOAP 消息进行通信。
- 优点:
- 标准化:有严格的规范(WSDL - Web Services Description Language),可以自动生成客户端和服务端代码。
- 安全性:内置了安全、事务等扩展标准。
- 协议无关:虽然通常用 HTTP,但也可以通过 SMTP、TCP 等协议传输。
- 缺点:
- 性能差:XML 格式冗长,解析开销大。
- 开发复杂:配置繁琐,学习曲线陡峭。
- 可读性差:生成的 SOAP 消息在浏览器中难以直接阅读和调试。
- 代表技术:JAX-WS
REST 时代 (The Modern Way)
- 协议:REST (Representational State Transfer),它不是一种标准,而是一种软件架构风格。
- 核心:将一切数据视为“资源”,通过标准的 HTTP 方法(GET, POST, PUT, DELETE)来操作这些资源。
- 优点:
- 轻量级:通常使用 JSON 或 HTML 作为数据格式,数据量小,解析快。
- 开发简单:完全利用 HTTP 协议的特性,易于理解和实现。
- 易于缓存:可以直接利用 HTTP 缓存机制。
- 前后端分离:非常适合现代 Web 开发,前端通过 AJAX 调用后端 REST API。
- 缺点:
- 无状态:服务端不保存客户端状态,所有状态需要由客户端自己维护。
- 安全性:没有像 SOAP 那样内置的安全标准,需要自己实现或依赖 OAuth2、JWT 等框架。
- 代表技术:JAX-RS
在企业级应用内部,SOAP 仍有其一席之地(尤其是在需要严格契约和安全性的场景),但在互联网应用和前后端分离的架构中,REST 已成为绝对的主流。

主流的 Java WebService 技术栈
JAX-WS (SOAP)
JAX-WS 是 Java 官方定义的一套用于创建 SOAP Web 服务的 API,它极大地简化了 SOAP 服务的开发。
核心概念:
- SEI (Service Endpoint Interface):服务端接口,定义了服务提供的方法。
- SIB (Service Implementation Bean):服务端实现类,实现了 SEI 接口。
- WSDL (Web Services Description Language):XML 文件,描述了服务的地址、可用的方法、参数和返回值格式,客户端通过 WSDL 文件生成调用代码。
常用工具:
wsimport:JDK 自带的命令行工具,根据 WSDL 文件生成客户端的 Java 代码(SEI 和 SIB 的客户端存根)。Endpoint:JDK 自带的类,用于在内存中发布一个简单的 SOAP 服务,无需 Web 容器(如 Tomcat)。
JAX-RS (REST)
JAX-RS 是 Java 官方定义的一套用于创建 RESTful Web 服务的 API,它只定义了一套规范,具体实现由第三方厂商提供。

核心概念:
@Path:标注在类或方法上,定义资源的 URI 路径。@GET,@POST,@PUT,@DELETE:标注在方法上,定义对应的 HTTP 方法。@Produces:标注在方法上,定义该方法返回的媒体类型,如application/json,text/xml。@Consumes:标注在方法上,定义该方法可以接受的请求体媒体类型。@PathParam,@QueryParam,@FormParam:用于从 URL 路径、查询参数或表单数据中获取值。
主流实现框架:
- Jersey:参考实现,由 Oracle 赞助,功能强大,社区活跃。(推荐初学者使用)
- RESTEasy:JBoss(Red Hat)出品,与 JBoss/WildFly 应用服务器集成得非常好。
- Apache CXF:功能全面,除了支持 JAX-RS,还支持 JAX-WS 和许多其他协议。
实战示例
示例 1:JAX-WS (SOAP)
目标:创建一个简单的 SOAP 服务,根据用户名返回问候语。
服务端实现
// SEI (服务端接口)
import javax.jws.WebService;
import javax.jws.WebMethod;
@WebService
public interface GreetingService {
@WebMethod
String sayHello(String name);
}
// SIB (服务端实现)
import javax.jws.WebService;
@WebService(endpointInterface = "com.example.GreetingService")
public class GreetingServiceImpl implements GreetingService {
@Override
public String sayHello(String name) {
return "Hello, " + name + "!";
}
}
// 发布服务 (可以使用 Main 方法发布)
import javax.xml.ws.Endpoint;
public class GServicePublisher {
public static void main(String[] args) {
String address = "http://localhost:8888/ws/greeting";
Endpoint.publish(address, new GreetingServiceImpl());
System.out.println("SOAP Service is published at: " + address);
}
}
运行 GServicePublisher,服务就启动了,访问 http://localhost:8888/ws/greeting?wsdl,可以看到 WSDL 文件。
客户端调用
方法A:使用 wsimport 生成客户端代码
-
打开命令行,执行:
wsimport -p com.example.client -keep http://localhost:8888/ws/greeting?wsdl
这会在
com.example.client包下生成一堆 Java 文件。 -
编写客户端代码:
import com.example.client.GreetingService; import com.example.client.GreetingService_Service; public class GServiceClient { public static void main(String[] args) { // 创建服务视图 GreetingService_Service service = new GreetingService_Service(); // 获取服务端点 GreetingService port = service.getGreetingServicePort(); // 调用方法 String response = port.sayHello("WebService User"); System.out.println(response); // 输出: Hello, WebService User! } }
示例 2:JAX-RS (REST with Jersey)
目标:创建一个 REST 服务,提供用户信息。
环境准备
- 创建一个 Maven 项目。
- 在
pom.xml中添加 Jersey 依赖:
<dependencies>
<!-- Jersey 核心依赖 -->
<dependency>
<groupId>org.glassfish.jersey.containers</groupId>
<artifactId>jersey-container-servlet</artifactId>
<version>2.39</version>
</dependency>
<!-- JSON 支持 -->
<dependency>
<groupId>org.glassfish.jersey.media</groupId>
<artifactId>jersey-media-json-binding</artifactId>
<version>2.39</version>
</dependency>
</dependencies>
服务端实现
// 资源类
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import java.util.HashMap;
import java.util.Map;
@Path("/users") // 定义基础路径
public class UserResource {
// 模拟一个数据库
private static final Map<Integer, String> userDB = new HashMap<>();
static {
userDB.put(1, "Alice");
userDB.put(2, "Bob");
}
@GET
@Path("/{userId}") // 定义路径参数
@Produces(MediaType.APPLICATION_JSON) // 指定返回 JSON 格式
public String getUser(@PathParam("userId") int userId) {
String userName = userDB.get(userId);
if (userName == null) {
// 返回 404 Not Found
throw new javax.ws.rs.NotFoundException("User with id " + userId + " not found.");
}
// 返回简单的 JSON 字符串
return String.format("{\"id\": %d, \"name\": \"%s\"}", userId, userName);
}
}
配置 Web 容器 (web.xml)
在 src/main/webapp/WEB-INF/web.xml 中配置 Jersey Servlet:
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
version="4.0">
<servlet>
<servlet-name>Jersey Web Application</servlet-name>
<servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
<init-param>
<param-name>jersey.config.server.provider.packages</param-name>
<param-value>com.example</param-value> <!-- 指定你的资源类所在的包 -->
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>Jersey Web Application</servlet-name>
<url-pattern>/api/*</url-pattern>
</servlet-mapping>
</web-app>
部署和测试
- 将项目打包成 WAR 文件,部署到 Tomcat 或其他 Servlet 容器中。
- 启动服务器,访问:
http://localhost:8080/your-app-name/api/users/1(应返回{"id": 1, "name": "Alice"})http://localhost:8080/your-app-name/api/users/2(应返回{"id": 2, "name": "Bob"})http://localhost:8080/your-app-name/api/users/3(应返回 404 Not Found)
你可以使用 Postman 或浏览器插件(如 REST Client)来更方便地测试。
如何选择?(SOAP vs REST)
| 特性 | SOAP | REST |
|---|---|---|
| 协议 | 严格的协议(基于 XML) | 架构风格(基于 HTTP) |
| 数据格式 | 主要是 XML | 主要是 JSON, XML, HTML |
| 消息格式 | 标准化的 SOAP Envelope | 灵活的,通常是纯文本 JSON |
| 性能 | 较慢,XML 解析开销大 | 较快,JSON 轻量级 |
| 标准化 | 高度标准化(WSDL, WS-Security) | 无统一标准,依赖 API 文档 |
| 安全性 | 内置安全标准和事务支持 | 需要自行实现或集成 OAuth2, JWT 等 |
| 缓存 | 不支持 | 利用 HTTP 缓存机制 |
| 学习曲线 | 陡峭 | 平缓 |
| 适用场景 | 企业应用集成(B2B)、金融、电信等需要高安全性和严格契约的场景。 | 互联网应用、移动后端、微服务、前后端分离项目。 |
简单来说:
- 如果你的服务需要被不同语言、不同平台的遗留系统调用,并且对安全性和事务有极高要求,可以考虑 SOAP。
- 如果你在开发新的、现代化的 Web 或移动应用,追求开发效率、性能和灵活性,REST 是不二之选。
现代趋势与替代方案
随着技术的发展,传统的 WebService 概念也在演变:
- Spring Boot + Spring WebFlux:在 Java 世界,Spring Boot 已经成为事实标准,它内置了对 REST 的完美支持(使用
@RestController),并以其简洁的配置、强大的生态系统(如 Spring Security, Spring Data)极大地简化了 Web 服务的开发,对于新的项目,Spring Boot 是首选。 - gRPC:由 Google 推出,使用 HTTP/2 和 Protocol Buffers (Protobuf) 作为数据格式,它性能极高、支持双向流、强类型定义,非常适合微服务架构内部的服务间通信。
- GraphQL:由 Facebook 推出,是一种 API 查询语言,它允许客户端精确地请求所需的数据,避免了 REST 中常见的“过度获取”或“获取不足”的问题,适用于需要高度灵活性的前端应用。
- 对于 SOAP,JAX-WS 依然是标准,但使用场景越来越少。
- 对于 REST,JAX-RS (Jersey/RESTEasy) 是一个很好的选择,但 Spring Boot 凭借其易用性和生态优势,在当前市场中占据了主导地位。
- 在特定高性能或微服务场景下,可以关注 gRPC 和 GraphQL。
希望这份详细的指南能帮助你全面了解 Java WebService!
