- WebService 的核心概念:SOAP vs. REST
- Java WebService 开发的三种主流方式:
- JAX-WS (Java API for XML Web Services):用于开发 SOAP WebService 的标准。
- JAX-RS (Java API for RESTful Web Services):用于开发 RESTful WebService 的标准。
- Spring Boot:目前最流行、最简便的开发方式。
- 完整的代码示例:分别用 JAX-WS 和 Spring Boot 开发一个简单的 WebService。
- 选择建议:在什么场景下选择哪种技术。
WebService 核心概念:SOAP vs. REST
在开始编码前,理解这两种风格的区别至关重要。

| 特性 | SOAP (Simple Object Access Protocol) | REST (Representational State Transfer) |
|---|---|---|
| 协议 | 严格的协议,基于 XML。 | 架构风格,没有官方标准。 |
| 数据格式 | 强制使用 XML。 | 灵活,常用 JSON, XML, HTML, Text 等,JSON 是主流。 |
| 接口定义 | 使用 WSDL (Web Services Description Language) 文件定义服务接口、方法、参数等。 | 无需额外文件,接口通过 URL 和 HTTP 方法(GET, POST, PUT, DELETE)来定义。 |
| 消息格式 | XML 格式的消息 envelope,包含 Header 和 Body。 | 消息格式简单,通常是键值对或 JSON 对象。 |
| 安全性 | 内置安全性标准和 WS-Security 等扩展,安全性高且成熟。 | 依赖 HTTPS 和 OAuth 等标准,安全性实现相对灵活。 |
| 性能 | XML 解析开销大,消息冗长,性能相对较低。 | 数据量小(尤其是 JSON),解析快,性能高。 |
| 使用场景 | 企业级应用、金融、电信等对安全性、事务性要求高的场景。 | 公开 API、移动应用后端、微服务架构等对性能和灵活性要求高的场景。 |
简单总结:
- SOAP 像一个“重型卡车”,规矩多、载重能力强(安全性高),但速度慢、灵活性差。
- REST 像一辆“跑车”,速度快、灵活,但在极端路况下(如高安全性要求)可能需要自己加装额外的设备(HTTPS, OAuth)。
Java WebService 开发方式
JAX-WS (开发 SOAP WebService)
JAX-WS 是 Java 标准的一部分,是开发 SOAP WebService 的官方 API,它不需要引入任何第三方框架,因为其实现(如 Metro, Apache Axis2)通常已经包含在 JDK 或 Java EE 应用服务器中。
开发步骤 (以 JDK 自带的 wsimport 工具为例)
服务端 开发
假设我们想发布一个计算器服务。

a. 创建服务接口和实现
// src/main/java/com/example/Calculator.java
package com.example;
import javax.jws.WebService;
import javax.jws.WebMethod;
// @WebService 注解将这个类标记为一个 WebService
@WebService
public interface Calculator {
@WebMethod // 标记为公开的 Web 方法
public int add(int a, int b);
public int subtract(int a, int b);
}
// src/main/java/com/example/CalculatorImpl.java
package com.example;
import javax.jws.WebService;
// endpointInterface 指向接口
@WebService(endpointInterface = "com.example.Calculator")
public class CalculatorImpl implements Calculator {
@Override
public int add(int a, int b) {
return a + b;
}
@Override
public int subtract(int a, int b) {
return a - b;
}
}
b. 发布服务
可以使用一个独立的 Java 类来发布服务。
// src/main/java/com/example/Publisher.java
package com.example;
import javax.xml.ws.Endpoint;
public class Publisher {
public static void main(String[] args) {
// 定义服务的访问地址
String address = "http://localhost:8080/calculator";
// 创建服务实现类实例
CalculatorImpl calculator = new CalculatorImpl();
// 发布服务
Endpoint.publish(address, calculator);
System.out.println("Calculator Service is published at: " + address);
}
}
运行 Publisher 的 main 方法,你的 SOAP WebService 就启动了,监听在 8080 端口。

客户端 开发
客户端通常不需要自己写调用代码,而是通过 wsimport 工具根据服务端生成的 WSDL 文件自动生成客户端代码。
a. 使用 wsimport 生成客户端代码
打开命令行,运行以下命令:
wsimport -keep -p com.example.client http://localhost:8080/calculator?wsdl
-keep: 生成源代码。-p com.example.client: 指定生成代码的包名。http://.../calculator?wsdl: 服务的 WSDL 地址。
执行后,会在 com.example.client 包下生成一堆 Java 文件(如 Calculator.java, CalculatorService.java, Add.java 等)。
b. 调用服务
// src/main/java/com/example/client/CalculatorClient.java
package com.example.client;
public class CalculatorClient {
public static void main(String[] args) {
// 通过 WSDL 生成的 Service 类获取 Port (服务代理)
CalculatorService service = new CalculatorService();
Calculator calculator = service.getCalculatorPort();
// 像调用本地方法一样调用远程服务
int result = calculator.add(10, 25);
System.out.println("10 + 25 = " + result);
result = calculator.subtract(50, 20);
System.out.println("50 - 20 = " + result);
}
}
JAX-RS (开发 RESTful WebService)
JAX-RS 是 Java 中用于开发 RESTful 风格 WebService 的标准 API,其最著名的实现是 Jersey 和 RESTEasy。
开发步骤 (以 Jersey 为例)
服务端 开发
a. 添加依赖
如果你使用 Maven,在 pom.xml 中添加 Jersey 核心依赖:
<dependency>
<groupId>org.glassfish.jersey.containers</groupId>
<artifactId>jersey-container-simple-http</artifactId>
<version>2.39.1</version> <!-- 使用最新版本 -->
</dependency>
<dependency>
<groupId>org.glassfish.jersey.inject</groupId>
<artifactId>jersey-hk2</artifactId>
<version>2.39.1</version>
</dependency>
b. 创建资源类
JAX-RS 的核心是 资源类,它用 POJO(普通 Java 对象)来表示资源。
// src/main/java/com/example/ResourceConfig.java
package com.example;
import org.glassfish.jersey.server.ResourceConfig;
// 注册资源类
public class ResourceConfig extends org.glassfish.jersey.server.ResourceConfig {
public ResourceConfig() {
// 扫描并注册带有 @Path 注解的类
packages("com.example.resource");
}
}
// src/main/java/com/example/resource/MessageResource.java
package com.example.resource;
import javax.ws.rs.*;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
// @Path 注解定义了资源的 URI 路径
@Path("/messages")
public class MessageResource {
// @GET 表示处理 HTTP GET 请求
// @Produces 定义返回的媒体类型
@GET
@Produces(MediaType.TEXT_PLAIN)
public String getHelloMessage() {
return "Hello, this is a RESTful WebService!";
}
// 路径参数
@GET
@Path("/{id}")
@Produces(MediaType.APPLICATION_JSON)
public Response getMessageById(@PathParam("id") int id) {
if (id <= 0) {
// 返回 400 Bad Request
return Response.status(Response.Status.BAD_REQUEST).entity("Invalid ID").build();
}
// 模拟从数据库获取数据
String message = "Message content for ID: " + id;
// 返回 200 OK 和 JSON 数据
return Response.ok("{\"id\": " + id + ", \"content\": \"" + message + "\"}").build();
}
// 处理 POST 请求
@POST
@Consumes(MediaType.APPLICATION_JSON) // 定义接受的媒体类型
@Produces(MediaType.APPLICATION_JSON)
public Response createMessage(String jsonMessage) {
// 在实际应用中,这里会解析 jsonMessage 并存入数据库
System.out.println("Received message: " + jsonMessage);
String responseJson = "{\"status\": \"success\", \"received\": \"" + jsonMessage + "\"}";
return Response.status(Response.Status.CREATED).entity(responseJson).build();
}
}
c. 启动服务器
// src/main/java/com/example/ServerLauncher.java
package com.example;
import org.glassfish.jersey.grizzly2.httpserver.GrizzlyHttpServerFactory;
import org.glassfish.jersey.server.ResourceConfig;
import java.net.URI;
public class ServerLauncher {
public static final String BASE_URI = "http://localhost:8080/myapi/";
public static void main(String[] args) {
// 创建一个 ResourceConfig 实例,注册我们的资源
final ResourceConfig rc = new ResourceConfig().packages("com.example.resource");
// 启动 Grizzly HTTP 服务器
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();
}
}
}
运行 ServerLauncher,一个 RESTful 服务就启动了。
客户端 调用
你可以使用任何 HTTP 客户端工具(如 Postman, curl)或 Java 代码来调用。
使用 curl:
# GET 请求
curl http://localhost:8080/myapi/messages
# GET 请求带路径参数
curl http://localhost:8080/myapi/messages/123
# POST 请求
curl -X POST -H "Content-Type: application/json" -d '{"user": "test", "text": "hello world"}' http://localhost:8080/myapi/messages
Spring Boot (开发 RESTful WebService)
这是目前最主流、最推荐的方式,Spring Boot 极大地简化了 WebService 的开发,特别是 RESTful 服务。
开发步骤
创建 Spring Boot 项目
最简单的方式是使用 Spring Initializr 网站:
- Project: Maven Project
- Language: Java
- Spring Boot: 选择一个稳定版本 (如 3.x.x)
- Project Metadata: Group, Artifact, Name 等。
- Dependencies: 添加
Spring Web,这个依赖会自动包含我们需要的 Tomcat 服务器和 Jackson (用于 JSON 处理) 库。
编写 Controller
在 Spring Boot 中,RESTful 服务由 @RestController 或 @Controller 来处理。@RestController 是 @Controller + @ResponseBody 的组合,表示所有方法返回的都是数据,而不是视图。
// src/main/java/com/example/demo/HelloController.java
package com.example.demo;
import org.springframework.web.bind.annotation.*;
// @RestController 标记这是一个 REST 控制器
@RestController
public class HelloController {
// @RequestMapping 可以处理多种 HTTP 方法,这里指定为 GET
// @GetMapping 是 @RequestMapping(method = RequestMethod.GET) 的快捷方式
@GetMapping("/hello")
public String sayHello() {
return "Hello from Spring Boot RESTful Service!";
}
// 路径参数,使用 @PathVariable
@GetMapping("/greet/{name}")
public String greet(@PathVariable String name) {
return "Hello, " + name + "!";
}
// 请求参数,使用 @RequestParam
@GetMapping("/search")
public String search(@RequestParam(defaultValue = "default") String keyword) {
return "Searching for: " + keyword;
}
// 处理 POST 请求,接收 JSON 并返回 JSON
// @PostMapping 是 @RequestMapping(method = RequestMethod.POST) 的快捷方式
// @RequestBody 将请求体的 JSON 自动映射到 Java 对象
// @ResponseBody (在 @RestController 中默认添加) 将返回的 Java 对象自动转换为 JSON
@PostMapping("/users")
public User createUser(@RequestBody User user) {
// 在实际应用中,这里会保存 user 到数据库
System.out.println("Received user: " + user.getName());
// 返回创建成功的用户信息,Spring Boot 会自动将其转为 JSON
return user;
}
}
// 一个简单的 POJO,用于 JSON 映射
class User {
private String name;
private int age;
// Getters and Setters (省略...)
public String getName() { return name; }
public void setName(String name) { this.name = name; }
public int getAge() { return age; }
public void setAge(int age) { this.age = age; }
@Override
public String toString() {
return "User{name='" + name + "', age=" + age + "}";
}
}
运行应用
直接运行 DemoApplication.java (Spring Initializr 自动生成的 main 类)。
package com.example.demo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}
测试
服务默认运行在 8080 端口。
# GET 请求
curl http://localhost:8080/hello
# GET 请求带路径参数
curl http://localhost:8080/greet/Alice
# GET 请求带请求参数
curl "http://localhost:8080/search?keyword=java"
# POST 请求
curl -X POST -H "Content-Type: application/json" -d '{"name":"Bob", "age":30}' http://localhost:8080/users
如何选择?
| 场景 | 推荐技术 | 理由 |
|---|---|---|
| 需要与老旧的 Java EE 系统集成,或必须使用 SOAP | JAX-WS | 它是标准,兼容性好,有成熟的 WS-* 标准(如安全、事务)。 |
| 开发新的、公开的 API,或作为微服务的一部分 | Spring Boot + JAX-RS (RESTful) | 首选方案,Spring Boot 简化了配置和部署,性能高,生态极其丰富,是现代 Java 开发的绝对主流。 |
| 学习或理解 WebService 底层原理 | JAX-WS / JAX-RS | 直接使用标准 API,可以更好地理解 WSDL, XML, HTTP 协议等细节。 |
| 快速原型开发 | Spring Boot | 几乎零配置,几分钟就能启动一个可用的 RESTful 服务。 |
除非有特殊的历史遗留或技术约束,否则强烈推荐使用 Spring Boot 来开发 RESTful WebService,它代表了 Java Web 开发的未来方向,效率最高,社区支持最广。
