Java WebService 完整教程
本教程将带你从零开始,学习如何使用 Java 创建和消费 WebService,我们将使用两种主流的技术栈:

- JAX-WS (Java API for XML Web Services):Java 官方标准,历史悠久,广泛支持,适合创建基于 SOAP 协议的 WebService。
- JAX-RS (Java API for RESTful Web Services):Java 官方标准,用于创建基于 REST 架构风格的 WebService(通常返回 JSON 或 XML),是目前的主流。
第一部分:核心概念
在开始编码之前,我们先理解几个关键概念。
什么是 WebService?
WebService 是一种跨编程语言、跨操作系统平台的远程调用技术,它允许不同应用通过网络进行交互,就像调用本地方法一样简单。
主要协议:SOAP vs. REST
| 特性 | SOAP (Simple Object Access Protocol) | REST (Representational State Transfer) |
|---|---|---|
| 架构风格 | 一套严格的协议(Protocol) | 一种软件架构风格(Style) |
| 数据格式 | 强制使用 XML | 通常使用 JSON,也支持 XML、HTML 等 |
| 通信方式 | 基于 HTTP/HTTPS,但也可通过 SMTP 等 | 基于 HTTP/HTTPS |
| 标准性 | 高度标准化,有 WSDL 描述服务 | 灵活,没有统一标准,依赖约定 |
| 性能 | XML 格式冗余,解析较慢,性能较低 | JSON 格式轻量,解析快,性能高 |
| 安全性 | 内置安全标准和 WS-* 协议(如 WS-Security) | 通常依赖 HTTPS 和 OAuth 等标准 |
| 适用场景 | 企业级应用、金融、电信等对安全性、事务性要求高的场景 | 移动 App、前后端分离的 Web 应用、公开 API |
第二部分:使用 JAX-WS 创建和调用 SOAP WebService
JAX-WS 是 Java EE 的一部分,现在通常包含在 JDK 中,我们将使用 JDK 自带的 wsimport 工具。
步骤 1:创建 WebService 服务端
我们将创建一个简单的 HelloService,它可以根据输入的名字返回问候语。

1 创建一个 Java 项目
- 创建一个普通的 Java 项目(
JaxWsServer)。 - 创建一个服务接口
HelloService.java。
// src/com/example/HelloService.java
package com.example;
import javax.jws.WebService;
import javax.jws.WebMethod;
// @WebService 注解将这个类标记为一个 WebService
@WebService
public interface HelloService {
// @WebMethod 注解将这个方法暴露为 WebService 的一个操作
@WebMethod
String sayHello(String name);
}
2 创建服务实现类
// src/com/example/HelloServiceImpl.java
package com.example;
import javax.jws.WebService;
// 实现接口,并指定 serviceName
@WebService(endpointInterface = "com.example.HelloService")
public class HelloServiceImpl implements HelloService {
@Override
public String sayHello(String name) {
return "Hello, " + name + "!";
}
}
3 发布服务
我们需要一个主类来发布这个服务,我们将它发布在 http://localhost:8080/hello 这个地址上。

// src/com/example/HelloPublisher.java
package com.example;
import javax.xml.ws.Endpoint;
public class HelloPublisher {
public static void main(String[] args) {
// 定义服务的发布地址
String address = "http://localhost:8080/hello";
// 发布服务
Endpoint.publish(address, new HelloServiceImpl());
System.out.println("WebService is published at: " + address);
}
}
4 运行服务端
运行 HelloPublisher 的 main 方法,你的 SOAP WebService 已经启动并运行在 http://localhost:8080/hello。
你可以在浏览器中访问这个地址,通常会看到一个页面,提示你这是一个 WSDL 文件,WSDL (Web Services Description Language) 是用来描述 WebService 的 XML 文件。
步骤 2:创建 WebService 客户端
我们创建另一个项目来调用刚刚发布的服务,我们将使用 JDK 自带的 wsimport 工具来生成客户端代码。
1 使用 wsimport 生成客户端代码
打开命令行(CMD 或 PowerShell),切换到你的客户端项目目录(JaxWsClient),然后执行以下命令:
wsimport -p com.example.client -keep http://localhost:8080/hello?wsdl
命令解释:
wsimport: JDK 自带的工具。-p com.example.client: 指定生成的客户端代码的包名。-keep: 保留生成的源文件,方便查看。http://localhost:8080/hello?wsdl: 服务端的 WSDL 地址。
执行后,会在 com.example.client 包下生成一堆 Java 文件(包括接口、服务、模型类等)。
2 编写客户端调用代码
在客户端项目中创建一个 HelloClient.java。
// src/com/example/client/HelloClient.java
package com.example.client;
public class HelloClient {
public static void main(String[] args) {
// 1. 创建服务视图 (Service)
HelloService_Service service = new HelloService_Service();
// 2. 获取服务端点 (Port),即服务的实现类
HelloService helloPort = service.getHelloServicePort();
// 3. 像调用本地方法一样调用远程方法
String response = helloPort.sayHello("WebService World");
// 4. 打印结果
System.out.println("Response from server: " + response);
}
}
3 运行客户端
运行 HelloClient 的 main 方法,如果一切正常,你将看到输出:
Response from server: Hello, WebService World!
至此,一个完整的 JAX-WS 开发流程就完成了。
第三部分:使用 JAX-RS (RESTful WebService)
RESTful WebService 是目前的主流,我们使用 Jersey 作为 JAX-RS 的参考实现(这也是许多教程选择它的原因),它更简单、更灵活。
步骤 1:环境准备
你需要添加 Jersey 的核心依赖,如果你使用 Maven,在 pom.xml 中添加:
<dependencies>
<!-- Jersey 核心依赖 -->
<dependency>
<groupId>org.glassfish.jersey.containers</groupId>
<artifactId>jersey-container-grizzly2-http</artifactId>
<version>2.39</version> <!-- 使用最新稳定版本 -->
</dependency>
<!-- 支持 JSON -->
<dependency>
<groupId>org.glassfish.jersey.media</groupId>
<artifactId>jersey-media-json-jackson</artifactId>
<version>2.39</version>
</dependency>
</dependencies>
步骤 2:创建 RESTful 服务端
我们将创建一个管理用户信息的 RESTful API。
1 创建资源类
资源类是 RESTful 服务的核心,每个方法通常对应一个 HTTP 请求。
// src/com/example/UserResource.java
package com.example;
import javax.ws.rs.*;
import javax.ws.rs.core.MediaType;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
// @Path 注解定义了资源的基 URI 路径
@Path("/users")
public class UserResource {
// 模拟一个数据库
private static List<User> users = new ArrayList<>();
static {
users.add(new User(1, "Alice"));
users.add(new User(2, "Bob"));
}
// @GET: 处理 HTTP GET 请求
// @Produces: 指定返回的媒体类型,这里是 JSON
@GET
@Produces(MediaType.APPLICATION_JSON)
public List<User> getAllUsers() {
return users;
}
// @Path: 可以在 @Path 下定义子路径
// @PathParam: 从路径中获取参数
@GET
@Path("/{id}")
@Produces(MediaType.APPLICATION_JSON)
public getUserById(@PathParam("id") int id) {
return users.stream()
.filter(user -> user.getId() == id)
.findFirst()
.orElse(null); // 如果找不到,返回 null
}
// @POST: 处理 HTTP POST 请求
// @Consumes: 指定接收的请求体媒体类型
@POST
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
public User createUser(User user) {
user.setId(users.size() + 1); // 简单生成 ID
users.add(user);
return user;
}
}
// 一个简单的 POJO (Plain Old Java Object)
class User {
private int id;
private String name;
// 构造函数、Getter 和 Setter 是必须的,Jackson 依赖它们
public User() {}
public User(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; }
}
2 创建启动类
// src/com/example/MyApplication.java
package com.example;
import org.glassfish.jersey.server.ResourceConfig;
public class MyApplication extends ResourceConfig {
public MyApplication() {
// 注册资源类
register(UserResource.class);
}
}
3 创建主类来启动服务器
// src/com/example/ServerMain.java
package com.example;
import org.glassfish.grizzly.http.server.HttpServer;
import org.glassfish.jersey.grizzly2.httpserver.GrizzlyHttpServerFactory;
import java.net.URI;
public class ServerMain {
public static final String BASE_URI = "http://localhost:8080/";
public static void main(String[] args) {
// 创建 ResourceConfig 实例
final ResourceConfig rc = new MyApplication();
// 创建并启动 Grizzly HTTP 服务器
HttpServer server = GrizzlyHttpServerFactory.createHttpServer(URI.create(BASE_URI), rc);
System.out.println("Server started at " + BASE_URI);
try {
// 阻塞主线程,保持服务器运行
System.in.read();
} catch (Exception e) {
e.printStackTrace();
} finally {
server.shutdownNow();
}
}
}
4 运行服务端
运行 ServerMain 的 main 方法,服务器启动在 http://localhost:8080/。
你可以使用 Postman 或浏览器(对于 GET 请求)来测试 API:
GET http://localhost:8080/users-> 获取所有用户GET http://localhost:8080/users/1-> 获取 ID 为 1 的用户POST http://localhost:8080/users-> 创建新用户,请求体为{"name": "Charlie"}
步骤 3:创建 RESTful 客户端
Jersey 也提供了强大的客户端 API。
1 创建客户端代码
// src/com/example/client/RestClient.java
package com.example.client;
import com.example.User;
import org.glassfish.jersey.client.ClientConfig;
import org.glassfish.jersey.client.ClientResponse;
import javax.ws.rs.client.Client;
import javax.ws.rs.client.ClientBuilder;
import javax.ws.rs.client.Entity;
import javax.ws.rs.client.WebTarget;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import java.util.List;
public class RestClient {
public static void main(String[] args) {
// 1. 创建客户端
Client client = ClientBuilder.newClient(new ClientConfig());
// 2. 定义服务器的根地址
WebTarget target = client.target("http://localhost:8080");
// --- 测试 GET /users ---
System.out.println("--- Testing GET /users ---");
WebTarget allUsersTarget = target.path("users");
List<User> allUsers = allUsersTarget.request(MediaType.APPLICATION_JSON).get(List.class);
allUsers.forEach(System.out::println);
// --- 测试 GET /users/1 ---
System.out.println("\n--- Testing GET /users/1 ---");
WebTarget userTarget = target.path("users").path("1");
User user = userTarget.request(MediaType.APPLICATION_JSON).get(User.class);
System.out.println("Found user: " + user);
// --- 测试 POST /users ---
System.out.println("\n--- Testing POST /users ---");
WebTarget createUserTarget = target.path("users");
User newUser = new User();
// 注意:ID 通常由服务器生成,客户端可以不设置或设为 0
newUser.setName("David");
// 发送 POST 请求,并接收响应
Response postResponse = createUserTarget.request()
.post(Entity.entity(newUser, MediaType.APPLICATION_JSON));
if (postResponse.getStatus() == Response.Status.CREATED.getStatusCode()) {
User createdUser = postResponse.readEntity(User.class);
System.out.println("Created user: " + createdUser);
} else {
System.out.println("Failed to create user. Status: " + postResponse.getStatus());
}
client.close();
}
}
2 运行客户端
运行 RestClient 的 main 方法,它会依次调用服务端的 API 并打印结果。
总结与建议
| 特性 | JAX-WS (SOAP) | JAX-RS (REST) |
|---|---|---|
| 适用场景 | 企业内部系统、需要严格契约、高安全性要求 | 公开 API、移动后端、前后端分离项目 |
| 学习曲线 | 较陡峭,涉及 WSDL、SOAP 协议细节 | 较平缓,概念简单,易于上手 |
| 开发效率 | 较低,代码生成步骤多 | 较高,注解驱动,开发迅速 |
| 社区与生态 | 成熟,但在新项目中较少使用 | 极其活跃,是当前 Web 开发的主流 |
给你的建议:
- 如果你是初学者:直接学习 JAX-RS (RESTful),这是当前业界的事实标准,应用范围更广,学习成果更有价值。
- 如果你需要与遗留系统集成:某些旧系统可能只提供 SOAP 接口,这时你需要了解 JAX-WS。
- 如果你需要最高级别的安全和事务支持:SOAP 的 WS-* 标准提供了非常完善的企业级解决方案,而 REST 的实现通常需要自己组合多种技术。
希望这份详细的教程能帮助你快速入门 Java WebService 开发!
