- JAX-WS (Java API for XML Web Services):这是 Java 官方标准,用于构建 SOAP (Simple Object Access Protocol) 风格的 WebService,它非常成熟、稳定,在企业级应用中广泛使用,尤其适合需要高安全性、事务处理和标准化的场景。
- JAX-RS (Java API for RESTful Web Services):这是用于构建 REST (Representational State Transfer) 风格 Web 服务的标准,REST 更轻量级、更简单,通常与 JSON 数据格式配合使用,是目前 Web 开发(特别是移动端和前后端分离项目)中最流行的方式。
下面我将分别详细介绍如何使用这两种方式来编写 WebService。

使用 JAX-WS (SOAP 风格)
JAX-WS 是 Java EE 的一部分,在标准 JDK 中也包含了其核心实现(javax.xml.ws 包),我们不需要额外引入复杂的框架,只需要使用 JDK 自带的工具即可。
步骤 1:创建一个服务接口
这个接口定义了客户端可以调用的方法,使用 @WebService 注解来标记它。
// src/main/java/com/example/HelloService.java
package com.example;
import javax.jws.WebMethod;
import javax.jws.WebParam;
import javax.jws.WebService;
import javax.jws.soap.SOAPBinding;
// @WebService 表示这是一个 WebService 接口
@WebService
// @SOAPBinding(style = SOAPBinding.Style.RPC) 表示使用 RPC 风格,这是默认的
public interface HelloService {
// @WebMethod 表示这是一个对外暴露的 Web 方法
// @WebParam 指定参数名,用于 WSDL 文档
@WebMethod
String sayHello(@WebParam(name = "name") String name);
}
步骤 2:创建一个服务实现类
这个类实现了上面定义的接口,是 WebService 的具体逻辑。
// src/main/java/com/example/HelloServiceImpl.java
package com.example;
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) {
System.out.println("WebService 被调用了,参数是: " + name);
return "你好, " + name + "! 欢迎使用 JAX-WS WebService.";
}
}
步骤 3:发布 WebService
你可以编写一个主类来发布这个服务,最简单的方式是使用 Endpoint 类。

// src/main/java/com/example/WebServicePublisher.java
package com.example;
import javax.xml.ws.Endpoint;
public class WebServicePublisher {
public static void main(String[] args) {
// 定义服务的访问地址
String address = "http://localhost:8888/ws/hello";
// 创建服务实现类的实例
HelloService helloService = new HelloServiceImpl();
// 发布服务
// 第一个参数是访问地址,第二个参数是服务的实现实例
Endpoint.publish(address, helloService);
System.out.println("WebService 发布成功!");
System.out.println("访问地址: " + address);
System.out.println("WSDL 地址: " + address + "?wsdl");
}
}
步骤 4:运行和测试
-
运行:直接运行
WebServicePublisher的main方法。 -
验证 WSDL:在浏览器中访问
http://localhost:8888/ws/hello?wsdl,如果看到一个 XML 文件(WSDL 描述文件),说明服务发布成功。 -
测试:可以使用专门的 SOAP 客户端工具(如 SoapUI)进行测试,也可以使用 JDK 自带的
wsimport工具生成客户端代码进行调用。使用
wsimport生成客户端: 打开一个新的命令行窗口(不要关闭发布服务的窗口),执行以下命令:# -p: 客户端代码包名 # -keep: 保留生成的源文件 # -d: 指定编译后的 .class 文件存放目录 wsimport -p com.example.client -keep -d ./client http://localhost:8888/ws/hello?wsdl
这会在
com/example/client目录下生成一堆 Java 文件,你可以写一个简单的客户端来调用:// Client.java import com.example.client.HelloService; import com.example.client.HelloService_Service; public class Client { public static void main(String[] args) { // 通过服务名称获取服务实例 HelloService_Service service = new HelloService_Service(); // 获取服务端口(即实现类) HelloService helloPort = service.getHelloServicePort(); // 调用方法 String result = helloPort.sayHello("张三"); System.out.println("客户端收到结果: " + result); } }
使用 JAX-RS (REST 风格)
JAX-RS 是 Java EE 的一部分,但它的参考实现是 Jersey,另一个非常流行的实现是 RESTEasy,在现代 Java 项目中,我们通常使用 Spring Boot 来集成 JAX-RS(或更常见的 Spring MVC 的 @RestController),因为它极大地简化了配置。
这里我们以 Spring Boot + Jersey 为例,因为它最符合“现代Java写WebService”的实践。
步骤 1:创建 Spring Boot 项目
使用 Spring Initializr 创建一个新项目,并添加以下依赖:
- Spring Web (虽然我们用 Jersey,但这个依赖通常会有用)
- Jersey (或 Jersey Spring Web)
- Spring Boot DevTools (可选,用于热部署)
步骤 2:配置 Jersey
在 application.properties 或 application.yml 中配置 Jersey。
# application.properties # 配置 Jersey servlet 的映射路径 jersey.servlet.application=/api
步骤 3:创建资源类 (Resource Class)
这是 REST 服务的核心,使用 @Path、@GET、@POST 等注解来定义资源和方法。
// src/main/java/com/example/GreetingResource.java
package com.example;
import org.springframework.stereotype.Component;
import javax.ws.rs.*;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
// @Component 让 Spring 管理这个 Bean
@Component
// @Path 定义资源的 URI 路径
@Path("/greetings")
public class GreetingResource {
// @GET 表示这是一个 HTTP GET 请求处理方法
// @Path 定义该方法在资源下的子路径
// @Produces 定义该方法返回的媒体类型 (MIME Type)
@GET
@Path("/hello")
@Produces(MediaType.TEXT_PLAIN)
public String sayHello() {
return "Hello, Jersey!";
}
// @QueryParam 用于获取 URL 中的查询参数
@GET
@Path("/greet")
@Produces(MediaType.APPLICATION_JSON)
public Greeting greet(@QueryParam("name") String name) {
// 如果没有提供 name 参数,则使用默认值 "World"
if (name == null || name.isEmpty()) {
name = "World";
}
return new Greeting("你好, " + name + "!");
}
// @POST 表示这是一个 HTTP POST 请求处理方法
// @Consumes 定义该方法能接受的请求体媒体类型
@POST
@Path("/create")
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
public Response createGreeting(Greeting greeting) {
// 模拟创建逻辑,比如将问候语存入数据库
System.out.println("收到一个新的问候语: " + greeting.getMessage());
// 返回一个响应对象,可以设置状态码、头信息和实体
greeting.setMessage("已确认: " + greeting.getMessage());
return Response.status(Response.Status.CREATED).entity(greeting).build();
}
}
// 一个简单的 POJO,用于 JSON 序列化/反序列化
class Greeting {
private String message;
public Greeting() {}
public Greeting(String message) {
this.message = message;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
}
步骤 4:配置 Jersey Servlet
创建一个配置类来注册 Jersey。
// src/main/java/com/example/JerseyConfig.java
package com.example;
import org.glassfish.jersey.server.ResourceConfig;
import org.springframework.stereotype.Component;
@Component
public class JerseyConfig extends ResourceConfig {
public JerseyConfig() {
// 注册这个资源类
register(GreetingResource.class);
// 如果需要,可以注册其他特性,如过滤器、异常映射器等
}
}
步骤 5:运行和测试
-
运行:运行 Spring Boot 的主启动类。
-
测试:服务启动后,你可以使用 Postman、curl 或浏览器来测试这些 API 端点。
- GET /api/greetings/hello
curl http://localhost:8080/api/greetings/hello # 响应: Hello, Jersey!
- GET /api/greetings/greet
curl "http://localhost:8080/api/greetings/greet?name=李四" # 响应 (JSON): {"message":"你好, 李四!"} - POST /api/greetings/create
curl -X POST \ -H "Content-Type: application/json" \ -d '{"message":"这是一个测试"}' \ http://localhost:8080/api/greetings/create # 响应 (JSON): {"message":"已确认: 这是一个测试"}
- GET /api/greetings/hello
总结与对比
| 特性 | JAX-WS (SOAP) | JAX-RS (REST) |
|---|---|---|
| 协议 | SOAP (基于 XML) | HTTP (GET, POST, PUT, DELETE 等) |
| 数据格式 | 主要是 XML,也可以是 JSON | 主要是 JSON,也可以是 XML, Text 等 |
| 风格 | 面向服务,有严格的契约 | 面向资源,轻量级,无状态 |
| 标准 | Java EE 标准 | Java EE 标准 |
| 常用实现 | JDK 内置 | Jersey, RESTEasy |
| 集成框架 | 可与 Spring 集成,但原生发布简单 | 与 Spring Boot 集成是主流 |
| 优点 | - 标准化、强契约 - 内置安全、事务支持 - 自动生成 WSDL 客户端 |
- 简单、轻量 - 无需额外工具,浏览器和客户端友好 - 与 HTTP 协议紧密结合,利用其所有特性 |
| 缺点 | - 配置相对复杂 - SOAP 头和消息体较重 - 不适合浏览器直接调用 |
- 无统一标准,需要自行定义 API 规范 - 缺少内置的标准化安全机制 |
| 适用场景 | - 企业级应用集成 - 需要高安全性和事务保障的系统 - 金融、电信等传统行业 |
- 公开 API - 移动后端服务 - 前后端分离的 Web 应用 |
如何选择?
- 如果你正在开发一个需要与 Java EE 生态深度集成、对安全性和事务有严格要求的企业内部系统,或者需要为不同语言的客户端提供一套标准化的、自动生成的调用方式,JAX-WS 是一个不错的选择。
- 如果你正在开发现代的 Web 应用,特别是需要为移动 App 或前端提供 API 服务,或者你的项目已经基于 Spring Boot,JAX-RS (通过 Jersey 或 Spring MVC 的
@RestController) 是更简单、更高效的选择,在 Spring 生态中,直接使用@RestController是最普遍的做法,其原理和 Jersey 非常相似。
