Java Web Service 完整教程
目录
-
第一部分:基础理论
(图片来源网络,侵删)- 什么是 Web Service?
- 为什么需要 Web Service?
- Web Service 的核心特点:SOAP vs. REST
- Java Web Service 的演变史
-
第二部分:传统 SOAP Web Service 开发 (JAX-WS)
- JAX-WS 简介
- 实战 1:创建一个简单的 SOAP Web Service (Server 端)
- 实战 2:创建 SOAP Web Service 客户端
- 使用
wsimport工具
-
第三部分:现代 RESTful Web Service 开发 (JAX-RS)
- REST 架构风格简介
- JAX-RS 简介
- 实战 3:使用 JAX-RS (Jersey) 创建 RESTful Web Service
- 实战 4:使用 JAX-RS (RESTEasy) 创建 RESTful Web Service
-
第四部分:企业级框架 - Spring Boot 与 Web Service
- 为什么选择 Spring Boot?
- 实战 5:使用 Spring Boot 创建 RESTful Web Service
- 实战 6:在 Spring Boot 中集成 SOAP Web Service (CXF)
-
第五部分:总结与最佳实践
(图片来源网络,侵删)
第一部分:基础理论
什么是 Web Service?
Web Service(网络服务)是一种基于 Web 的、可互操作的软件应用程序,它使用标准化的 XML 消息格式在网络上进行通信,它允许不同的应用程序(无论使用何种编程语言或运行在何种平台上)通过 HTTP 协议互相交换数据或调用功能。
为什么需要 Web Service?
- 跨平台和跨语言:Java 应用可以调用 Python 或 C# 应用提供的服务,反之亦然。
- 系统解耦:客户端和服务器端可以独立开发、部署和升级,只要它们之间约定的接口(WSDL 或 API 文档)不变。
- 复用性:通用的业务逻辑(如用户认证、支付处理)可以作为 Web Service 提供给多个系统使用。
- B2B 集成:企业之间可以通过 Web Service 安全地交换数据和流程。
Web Service 的核心特点:SOAP vs. REST
这是选择 Web Service 技术路线时最重要的决策点。
| 特性 | SOAP (Simple Object Access Protocol) | REST (Representational State Transfer) |
|---|---|---|
| 协议 | 严格的协议,基于 XML,定义了消息结构、处理规则等。 | 一种架构风格,没有严格的协议,通常基于 HTTP/HTTPS。 |
| 消息格式 | 强制使用 XML。 | 灵活,可以是 JSON, XML, HTML, 文本等。JSON 是目前主流。 |
| 标准 | 高度标准化,有 WS-Security, WS-Addressing 等扩展,适合企业级安全。 | 没有官方标准,依赖于 HTTP 标准。 |
| 性能 | 由于 XML 解析和复杂的协议头,通常比 REST 慢。 | 消息更轻量(尤其是 JSON),性能更高。 |
| 使用方式 | 通过 POST 请求发送一个完整的 XML 包(Envelope)。 | 主要使用标准的 HTTP 方法:GET (查询), POST (创建), PUT (更新), DELETE (删除)。 |
| 适用场景 | 企业级应用、金融、电信等对安全性、事务性要求极高的场景。 | 公开 API、移动后端、微服务、Web 应用等绝大多数现代应用。 |
Java Web Service 的演变史
- JAX-RPC (Java API for XML-based RPC): 早期的标准,现已废弃。
- JAX-WS (Java API for XML Web Services): 成为了 Java EE 的标准,用于开发 SOAP Web Service,它简化了开发,提供了注解支持。
- JAX-RS (Java API for RESTful Web Services): Java EE 的标准,用于开发 RESTful Web Service,有多种实现,如 Jersey, RESTEasy。
- Spring Framework: Spring 提供了更简洁、更强大的方式来开发 Web Service,尤其是 Spring MVC(用于 REST)和 Spring WS(用于 SOAP)。
- Spring Boot: 目前最主流的框架,它通过自动配置和起步依赖,极大地简化了 Spring Web Service 的创建和部署。
第二部分:传统 SOAP Web Service 开发 (JAX-WS)
JAX-WS 是 Java 官方推荐的 SOAP 开发标准。
实战 1:创建一个简单的 SOAP Web Service (Server 端)
我们将使用 Eclipse IDE 来演示。

步骤 1:创建 Dynamic Web Project
- 在 Eclipse 中,
File->New->Dynamic Web Project。 - 输入项目名,
JaxWsServer,选择 Target runtime(如 Apache Tomcat v9.0)。 - 点击
Finish。
步骤 2:创建 Service Endpoint Interface (SEI) 这是一个普通的 Java 接口,定义了 Web Service 将要暴露的方法。
// src/com/example/HelloWorld.java
package com.example;
import javax.jws.WebMethod;
import javax.jws.WebService;
import javax.jws.WebParam;
// @WebService 注解将此接口标记为 Web Service 的端点
@WebService
public interface HelloWorld {
// @WebMethod 注解将此方法标记为 Web Service 的一个操作
// @WebParam 注解用于指定参数名
@WebMethod
String sayHello(@WebParam(name = "name") String name);
}
步骤 3:创建 Service Implementation Bean (SIB) 这是实现 SEI 接口的类。
// src/com/example/HelloWorldImpl.java
package com.example;
import javax.jws.WebService;
// @WebService 注解的 endpointInterface 属性指向 SEI
@WebService(endpointInterface = "com.example.HelloWorld")
public class HelloWorldImpl implements HelloWorld {
@Override
public String sayHello(String name) {
return "Hello, " + name + "!";
}
}
步骤 4:发布 Web Service 我们可以通过一个简单的 Java 类来发布这个服务。
// src/com/example/Publisher.java
package com.example;
import javax.xml.ws.Endpoint;
public class Publisher {
public static void main(String[] args) {
// 创建服务的实现实例
HelloWorldImpl helloService = new HelloWorldImpl();
// 发布服务到指定地址
// 这个地址可以在浏览器中访问,并生成 WSDL 文件
String address = "http://localhost:8080/JaxWsServer/HelloWorld";
Endpoint.publish(address, helloService);
System.out.println("SOAP Web Service 已发布在: " + address);
System.out.println("WSDL 文件地址: " + address + "?wsdl");
}
}
步骤 5:运行和测试
- 运行
Publisher.java的main方法。 - 打开浏览器,访问
http://localhost:8080/JaxWsServer/HelloWorld?wsdl,你应该能看到一个 XML 格式的 WSDL 文件。 - 使用工具(如 SoapUI)创建一个新的 SOAP 项目,WSDL URL 填入上面的地址,然后创建一个请求,测试
sayHello方法。
实战 2:创建 SOAP Web Service 客户端
在另一个项目中,我们如何调用上面发布的服务?
步骤 1:获取 WSDL
我们已经有了 WSDL 的 URL:http://localhost:8080/JaxWsServer/HelloWorld?wsdl
步骤 2:使用 wsimport 生成客户端代码
wsimport 是 JDK 自带的工具,它可以根据 WSDL 文件生成客户端所需的 Java 代码(接口、类等)。
打开命令行(或系统的 PATH 中包含 JDK 的目录),执行以下命令:
wsimport -p com.example.client -keep http://localhost:8080/JaxWsServer/HelloWorld?wsdl
-p com.example.client: 指定生成的包名。-keep: 保留生成的源文件,方便查看。
执行后,会在当前目录下生成 com/example/client 包,里面有 HelloWorld.java (接口), HelloWorldService.java (服务类) 等文件。
步骤 3:编写客户端代码
将生成的 com 文件夹复制到你的客户端项目中,或者直接将生成的 .java 文件编译。
// Client.java
import com.example.client.HelloWorld;
import com.example.client.HelloWorldService;
public class Client {
public static void main(String[] args) {
// 创建服务实例
HelloWorldService service = new HelloWorldService();
// 获取服务端点 (port)
HelloWorld helloWorld = service.getHelloWorldPort();
// 调用远程方法
String response = helloWorld.sayHello("WebService Client");
System.out.println("收到服务端响应: " + response);
}
}
运行这个客户端,你将看到输出:收到服务端响应: Hello, WebService Client!
第三部分:现代 RESTful Web Service 开发 (JAX-RS)
REST 更简单、更灵活,是目前 Web Service 的主流。
实战 3:使用 JAX-RS (Jersey) 创建 RESTful Web Service
Jersey 是 JAX-RS 的参考实现。
步骤 1:创建 Maven 项目 使用 Maven 可以方便地管理 Jersey 依赖。
<!-- pom.xml -->
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.example</groupId>
<artifactId>JaxRsJerseyServer</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<maven.compiler.source>11</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target>
<jersey.version>2.37</jersey.version>
</properties>
<dependencies>
<!-- Jersey 核心依赖 -->
<dependency>
<groupId>org.glassfish.jersey.containers</groupId>
<artifactId>jersey-container-servlet</artifactId>
<version>${jersey.version}</version>
</dependency>
<!-- JSON 支持 -->
<dependency>
<groupId>org.glassfish.jersey.media</groupId>
<artifactId>jersey-media-json-jackson</artifactId>
<version>${jersey.version}</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<version>3.3.2</version>
</plugin>
</plugins>
</build>
</project>
步骤 2:配置 web.xml
在 src/main/webapp/WEB-INF/web.xml 中配置 Jersey Servlet。
<?xml version="1.0" encoding="UTF-8"?>
<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.resource</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>
jersey.config.server.provider.packages: 告诉 Jersey 去哪个包里寻找资源类。
步骤 3:创建资源类 这是 RESTful 服务的核心,使用注解来映射 URL 和 HTTP 方法。
// src/main/java/com/example/resource/UserResource.java
package com.example.resource;
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<>();
static {
userDB.put(1, new User(1, "Alice"));
userDB.put(2, new User(2, "Bob"));
}
@GET // 处理 GET 请求
@Produces(MediaType.APPLICATION_JSON) // 指定返回的媒体类型
public List<User> getAllUsers() {
return new ArrayList<>(userDB.values());
}
@GET
@Path("/{id}") // 路径参数 {id}
@Produces(MediaType.APPLICATION_JSON)
public getUserById(@PathParam("id") int id) {
User user = userDB.get(id);
if (user == null) {
// 抛出 404 Not Found 异常
throw new NotFoundException("User with id " + id + " not found.");
}
return user;
}
@POST // 处理 POST 请求 (创建资源)
@Consumes(MediaType.APPLICATION_JSON) // 指定接收的媒体类型
@Produces(MediaType.APPLICATION_JSON)
public User createUser(User user) {
userDB.put(user.getId(), user);
return user; // 返回创建的用户
}
}
// 一个简单的 POJO (Plain Old Java Object)
class User {
private int id;
private String name;
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; }
}
步骤 4:部署和测试
-
将项目部署到 Tomcat 服务器。
-
使用 Postman 或
curl等工具进行测试。-
获取所有用户:
GET http://localhost:8080/JaxRsJerseyServer/api/users返回:[{"id":1,"name":"Alice"},{"id":2,"name":"Bob"}] -
获取 ID 为 1 的用户:
GET http://localhost:8080/JaxRsJerseyServer/api/users/1返回:{"id":1,"name":"Alice"} -
创建新用户:
POST http://localhost:8080/JaxRsJerseyServer/api/usersBody (raw, JSON):{ "id": 3, "name": "Charlie" }返回:
{"id":3,"name":"Charlie"}
-
第四部分:企业级框架 - Spring Boot 与 Web Service
Spring Boot 是目前 Java 开发的事实标准,它极大地简化了 Web Service 的开发。
实战 5:使用 Spring Boot 创建 RESTful Web Service
步骤 1:创建 Spring Boot 项目 最简单的方式是使用 Spring Initializr。
- Project: Maven Project
- Language: Java
- Spring Boot: 选择一个稳定版本 (如 3.x.x)
- Project Metadata:
- Group:
com.example - Artifact:
SpringBootRestServer - Name:
SpringBootRestServer - Packaging: Jar
- Java: 11+
- Group:
- Dependencies:
Spring Web: 用于构建 RESTful 应用。Spring Data JPA(可选,用于数据库操作)H2 Database(可选,用于内存数据库)
- 点击 "GENERATE" 下载项目,然后用 IDE (如 IntelliJ IDEA 或 Eclipse) 打开。
步骤 2:创建 Controller
在 src/main/java/com/example/springbootrestserver/ 目录下创建 UserController.java。
// src/main/java/com/example/springbootrestserver/UserController.java
package com.example.springbootrestserver;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
@RestController // @Controller + @ResponseBody 的组合,表示所有方法都返回 JSON/XML
@RequestMapping("/api/users") // 类级别的路径映射
public class UserController {
private final ConcurrentMap<Integer, User> userDB = new ConcurrentHashMap<>();
{
userDB.put(1, new User(1, "Alice"));
userDB.put(2, new User(2, "Bob"));
}
@GetMapping // 等价于 @RequestMapping(method = RequestMethod.GET)
public List<User> getAllUsers() {
return new ArrayList<>(userDB.values());
}
@GetMapping("/{id}")
public ResponseEntity<User> getUserById(@PathVariable int id) {
User user = userDB.get(id);
if (user == null) {
// 返回 404 Not Found
return ResponseEntity.notFound().build();
}
// 返回 200 OK 和用户对象
return ResponseEntity.ok(user);
}
@PostMapping
public ResponseEntity<User> createUser(@RequestBody User user) {
// 实际应用中应该生成新的 ID
userDB.put(user.getId(), user);
// 返回 201 Created 和新创建的资源
return new ResponseEntity<>(user, HttpStatus.CREATED);
}
}
// POJO
class User {
private int id;
private String name;
// 构造器、Getters、Setters...
public User() {}
public User(int id, String name) {
this.id = id;
this.name = name;
}
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; }
}
步骤 3:运行和测试
- 运行
SpringBootRestServerApplication.java中的main方法,Spring Boot 会启动一个内置的 Tomcat 服务器。 - 测试方法和之前完全一样,只是 URL 变成了
http://localhost:8080/api/users。
实战 6:在 Spring Boot 中集成 SOAP Web Service (CXF)
Spring Boot 可以非常方便地集成 Apache CXF 来提供 SOAP 服务。
步骤 1:添加依赖
在 pom.xml 中添加 Spring Boot Starter for Apache CXF。
<!-- pom.xml -->
<dependencies>
<!-- ... 其他依赖 ... -->
<!-- Spring Boot Web -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- Spring Boot Starter for Apache CXF -->
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-spring-boot-starter-jaxws</artifactId>
<version>3.5.5</version> <!-- 使用与 Spring Boot 版本兼容的版本 -->
</dependency>
</dependencies>
步骤 2:创建 SEI 和 SIB 和 JAX-WS 部分一样,创建接口和实现类。
// Hello.java
package com.example.cxf;
import javax.jws.WebService;
@WebService
public interface Hello {
String sayHello(String name);
}
// HelloImpl.java
package com.example.cxf;
import javax.jws.WebService;
@WebService(endpointInterface = "com.example.cxf.Hello")
public class HelloImpl implements Hello {
@Override
public String sayHello(String name) {
return "Hello from Spring Boot SOAP, " + name + "!";
}
}
步骤 3:暴露服务
在 Spring Boot 配置类中,使用 @Bean 来发布服务。
// CxfConfig.java
package com.example.cxf;
import org.apache.cxf.Bus;
import org.apache.cxf.jaxws.EndpointImpl;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import javax.xml.ws.Endpoint;
@Configuration
public class CxfConfig {
@Bean
public Endpoint helloEndpoint(Bus bus) {
EndpointImpl endpoint = new EndpointImpl(bus, new HelloImpl());
endpoint.publish("/hello"); // 发布的路径
return endpoint;
}
}
步骤 4:运行和测试
- 运行 Spring Boot 应用。
- 访问
http://localhost:8080/hello?wsdl,你应该能看到 WSDL 文件。 - 使用 SoapUI 或
wsimport生成客户端进行测试,方法和之前 JAX-WS 部分完全一样。
第五部分:总结与最佳实践
| 场景 | 推荐技术 | 理由 |
|---|---|---|
| 快速开发、公开 API、移动端后端、微服务 | Spring Boot + REST (JSON) | 开发效率最高,社区最活跃,性能好,是当前绝对的主流。 |
| 企业内部集成、金融/电信等高安全、高可靠性要求 | Spring Boot + SOAP (WS-Security) | 利用成熟的标准和安全协议,适合复杂的 B2B 集成场景。 |
| 维护旧项目、需要遵循 Java EE 规范 | JAX-WS / JAX-RS (在传统 Web 容器中) | 如果项目没有迁移到 Spring Boot 的计划,这是标准的 Java 解决方案。 |
| 学习基础原理 | JAX-WS / JAX-RS | 从底层 API 开始,能更好地理解 Web Service 的工作机制。 |
学习路径建议:
- 入门:从 REST 开始,因为它是更简单、更常用的模式,使用 Spring Boot 来构建你的第一个 RESTful API,这是最快、最现代的方式。
- 深入:了解 JAX-RS 的标准,知道 Jersey 和 RESTEasy 是它的实现,这有助于你理解框架背后的原理。
- 扩展:当你需要处理企业级需求时,再学习 SOAP 和 Spring WS 或 Apache CXF。
- 实践:选择一个你感兴趣的项目(如博客、天气查询),尝试用 REST API 来实现其后端服务,并编写一个简单的前端(如 Vue/React)来调用它,这是最好的巩固方式。
