- JAX-WS (Java API for XML Web Services):这是 Java 官方推出的、较早且非常成熟的 WebService 规范,它通常基于 SOAP (Simple Object Access Protocol) 协议,使用 XML 格式进行数据交换。
- JAX-RS (Java API for RESTful Web Services):这是用于开发 RESTful 风格 Web 服务的 Java API,它更轻量级,通常基于 HTTP 协议,使用 JSON 或 XML 等格式进行数据交换,是目前 Web 开发的主流。
下面我将分别详细介绍这两种技术的开发流程,并提供完整的代码示例。

使用 JAX-WS 开发 SOAP WebService
JAX-WS 的开发相对“传统”,但依然在很多企业级应用(如银行、政府、大型ERP系统)中广泛使用。
核心概念
- SEI (Service Endpoint Interface):服务端点接口,一个普通的 Java 接口,定义了 WebService 提供的方法。
- SIB (Service Implementation Bean):服务实现Bean,一个具体的 Java 类,实现了 SEI 接口,包含了业务逻辑。
- WSDL (Web Services Description Language):一个 XML 文件,用于描述 WebService 的功能、地址、协议等信息,客户端通过 WSDL 文件来调用服务。
开发步骤
创建 Maven 项目
在 pom.xml 中添加 JAX-WS 的依赖,如果你使用 JDK 6+,JAX-WS API 和工具已经包含在内,但显式声明是个好习惯。
<dependencies>
<!-- JAX-WS API -->
<dependency>
<groupId>javax.xml.ws</groupId>
<artifactId>jaxws-api</artifactId>
<version>2.3.1</version>
</dependency>
<!-- 为了方便测试,可以嵌入一个简单的 HTTP 服务器,如 Jetty -->
<dependency>
<groupId>com.sun.xml.ws</groupId>
<artifactId>jaxws-rt</artifactId>
<version>2.3.3</version>
</dependency>
</dependencies>
定义服务端接口 (SEI)

创建一个 Java 接口,使用 @WebService 注解来标记它。
// src/main/java/com/example/webservice/HelloService.java
package com.example.webservice;
import javax.jws.WebService;
import javax.jws.WebMethod;
@WebService
public interface HelloService {
@WebMethod
String sayHello(String name);
}
实现服务端接口 (SIB)
创建一个实现类,实现上面的接口。
// src/main/java/com/example/webservice/HelloServiceImpl.java
package com.example.webservice;
import javax.jws.WebService;
@WebService(endpointInterface = "com.example.webservice.HelloService")
public class HelloServiceImpl implements HelloService {
@Override
public String sayHello(String name) {
return "Hello, " + name + "! Welcome to JAX-WS World.";
}
}
发布 WebService
编写一个主程序,将我们的服务发布到一个指定的 URL 地址上。
// src/main/java/com/example/webservice/Publisher.java
package com.example.webservice;
import javax.xml.ws.Endpoint;
public class Publisher {
public static void main(String[] args) {
// 创建服务的实现实例
HelloService serviceImpl = new HelloServiceImpl();
// 定义服务的访问地址
String address = "http://localhost:8888/ws/hello";
// 发布服务
Endpoint.publish(address, serviceImpl);
System.out.println("WebService is published at: " + address);
System.out.println("You can access the WSDL at: " + address + "?wsdl");
}
}
运行和测试
-
运行
Publisher的main方法。 -
打开浏览器,访问
http://localhost:8888/ws/hello?wsdl,如果看到一个 XML 文件,说明服务发布成功。 -
客户端测试:可以使用
wsimport命令(JDK 自带)生成客户端代码进行调用。-
打开一个新的终端,执行:
wsimport -s . http://localhost:8888/ws/hello?wsdl -
这会在当前目录下生成一堆客户端代码。
-
编写一个客户端测试类:
import com.example.webservice.HelloService; import com.example.webservice.HelloServiceImplService; public class JaxWsClient { public static void main(String[] args) { // 通过 WSDL 创建服务实例 HelloServiceImplService service = new HelloServiceImplService(); // 获取服务端口 HelloService helloPort = service.getHelloServiceImplPort(); // 调用方法 String response = helloPort.sayHello("Alice"); System.out.println("Client received: " + response); } } -
运行客户端,会得到输出:
Client received: Hello, Alice! Welcome to JAX-WS World.
-
使用 JAX-RS (RESTful WebService) 开发
这是目前最流行的方式,特别适合移动 App、前后端分离的 Web 应用,我们以最常用的 Jersey 框架为例。
核心概念
- JAX-RS:Java API 规范,定义了一套注解(如
@Path,@GET,@POST等)来开发 REST 服务。 - Jersey:是 JAX-RS 规范的参考实现,提供了完整的运行时环境和工具。
- REST (Representational State Transfer):一种软件架构风格,强调使用标准的 HTTP 方法(GET, POST, PUT, DELETE)来操作资源。
开发步骤
创建 Maven 项目
在 pom.xml 中添加 Jersey 的核心依赖。
<dependencies>
<!-- Jersey 核心依赖 -->
<dependency>
<groupId>org.glassfish.jersey.containers</groupId>
<artifactId>jersey-container-grizzly2-http</artifactId>
<!-- 使用最新稳定版 -->
<version>2.41</version>
</dependency>
<!-- 如果需要支持 JSON,需要添加这个依赖 -->
<dependency>
<groupId>org.glassfish.jersey.inject</groupId>
<artifactId>jersey-hk2</artifactId>
<version>2.41</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.media</groupId>
<artifactId>jersey-media-json-binding</artifactId>
<version>2.41</version>
</dependency>
</dependencies>
定义资源类
使用 @Path 注解标记一个类作为资源类,使用 @GET, @POST 等注解标记方法。
// src/main/java/com/example/rest/ResourceConfig.java
package com.example.rest;
import org.glassfish.jersey.server.ResourceConfig;
// 自定义 ResourceConfig,注册我们的资源
public class ResourceConfig extends org.glassfish.jersey.server.ResourceConfig {
public ResourceConfig() {
// 扫描并注册 com.example.rest 包下的所有资源
packages("com.example.rest");
}
}
// src/main/java/com/example/rest/UserResource.java
package com.example.rest;
import javax.ws.rs.*;
import javax.ws.rs.core.MediaType;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
@Path("/users")
public class UserResource {
// 模拟一个数据库
private static final ConcurrentMap<Integer, User> userDB = new ConcurrentHashMap<>();
private static int idCounter = 1;
// GET /users - 获取所有用户列表
@GET
@Produces(MediaType.APPLICATION_JSON)
public List<User> getAllUsers() {
return new ArrayList<>(userDB.values());
}
// GET /users/{id} - 根据ID获取单个用户
@GET
@Path("/{id}")
@Produces(MediaType.APPLICATION_JSON)
public User getUserById(@PathParam("id") int id) {
return userDB.get(id);
}
// POST /users - 创建一个新用户
@POST
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
public User createUser(User user) {
user.setId(idCounter++);
userDB.put(user.getId(), user);
return user; // 返回创建成功的用户对象(包含ID)
}
}
// 用户实体类
class User {
private int id;
private String name;
private String email;
// 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; }
public String getEmail() { return email; }
public void setEmail(String email) { this.email = email; }
}
启动服务器并发布资源
编写一个主程序来启动 Grizzly 服务器。
// src/main/java/com/example/rest/ServerLauncher.java
package com.example.rest;
import org.glassfish.grizzly.http.server.HttpServer;
import org.glassfish.jersey.grizzly2.httpserver.GrizzlyHttpServerFactory;
import java.net.URI;
public class ServerLauncher {
public static final String BASE_URI = "http://localhost:8080/api/";
public static void main(String[] args) {
// 创建 ResourceConfig 实例
final ResourceConfig rc = new ResourceConfig();
// 或者直接注册资源类: rc.registerClasses(UserResource.class);
// 创建并启动 Grizzly HTTP 服务器
HttpServer server = GrizzlyHttpServerFactory.createHttpServer(URI.create(BASE_URI), rc);
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();
}
}
}
运行和测试
-
运行
ServerLauncher的main方法。 -
服务启动后,你可以使用任何 API 测试工具(如 Postman, Insomnia, curl)来测试接口。
-
获取所有用户:
GET http://localhost:8080/api/users- 预期返回:
[](空列表)
-
创建用户:
POST http://localhost:8080/api/users- 在
Body中选择raw->JSON,输入:{ "name": "Bob", "email": "bob@example.com" } - 预期返回 (状态码 201 Created):
{ "id": 1, "name": "Bob", "email": "bob@example.com" }
-
获取ID为1的用户:
GET http://localhost:8080/api/users/1- 预期返回:
{ "id": 1, "name": "Bob", "email": "bob@example.com" }
-
方案对比与选择
| 特性 | JAX-WS (SOAP) | JAX-RS (REST) |
|---|---|---|
| 协议 | SOAP (基于XML,有严格规范) | HTTP (无状态,灵活) |
| 数据格式 | XML (默认) | JSON (主流), XML, Text 等 |
| 风格 | 面向接口/操作 | 面向资源 |
| 标准/规范 | WSDL, UDDI (发现服务) | 无标准,但有 RESTful 设计原则 |
| 安全性 | 内置 WS-Security 标准 | 通常依赖 OAuth 2.0, JWT, HTTPS |
| 性能 | SOAP 头部等开销较大,性能较低 | 轻量级,性能高 |
| 适用场景 | 企业级应用、金融、政府、需要高安全性和事务保证的场景 | Web API、移动后端、微服务、前后端分离项目 |
| 开发体验 | 相对繁琐,需要工具生成客户端代码 | 简单直观,符合 Web 开发习惯 |
如何选择?
- 选择 JAX-RS (REST):如果你的项目是现代的 Web 应用,需要与移动端或前端交互,或者你正在构建微服务,毫不犹豫地选择 REST,它更简单、更高效、更符合当前的技术潮流。
- 选择 JAX-WS (SOAP):如果你的项目需要与一些老旧的、基于 SOAP 的企业系统(如 SAP, Oracle EBS)集成,或者你的组织对安全性有非常严格且标准化的要求(如 WS-Security),SOAP 仍然是一个可靠的选择。
其他重要概念
- 框架集成:在实际项目中,我们通常不会自己写服务器启动代码,REST 服务可以轻松集成到 Spring Boot 中,SOAP 服务可以集成到 Spring 或 Spring Boot 中,由框架管理生命周期,这会大大简化开发。
- 安全性:无论是 REST 还是 SOAP,安全都是重中之重,REST 常用 JWT (JSON Web Tokens) 或 OAuth 2.0 进行身份认证和授权,SOAP 则使用 WS-Security。
- 文档:REST 服务通常使用 Swagger (OpenAPI) 来自动生成和提供交互式 API 文档,这对于前后端协作至关重要,SOAP 服务则依赖 WSDL 文档。
希望这份详细的指南能帮助你从零开始掌握 Java WebService 接口开发!
