目录
- 什么是 RESTful API?
- Java RESTful API 的主流实现技术
- 1. JAX-RS (Java API for RESTful Web Services) - 标准
- 2. Spring MVC - 事实上的标准
- 3. Spring Boot - 现代首选
- 实战:使用 Spring Boot 创建一个 RESTful API
- 1. 环境准备
- 2. 创建项目和依赖
- 3. 定义数据模型 (Entity/DTO)
- 4. 创建 Controller
- 5. 启动并测试
- RESTful API 设计原则与最佳实践
- 1. URL 设计 (名词复数、版本控制、过滤、排序、分页)
- 2. HTTP 方法 的正确使用
- 3. HTTP 状态码 的正确使用
- 4. 数据格式
- 5. 错误处理
- 进阶主题
- 1. 全局异常处理 (
@ControllerAdvice) - 2. 使用 DTO (Data Transfer Object) 隔离内部模型
- 3. API 文档自动化 (Swagger/OpenAPI)
- 4. 认证与授权 (JWT, OAuth2)
- 1. 全局异常处理 (
什么是 RESTful API?
REST (Representational State Transfer,表述性状态转移) 是一种软件架构风格,而不是一个标准,它由 Roy Fielding 在他 2000 年的博士论文中首次提出,一个符合 REST 风格的 API 通常具有以下特点:

- 无状态: 服务器不保存客户端的状态,每个请求都必须包含处理该请求所需的所有信息。
- 客户端-服务器架构: 客户端和服务器是分离的,它们通过统一的接口进行交互。
- 面向资源: 将所有功能都抽象为资源,用户、订单、产品都是资源。
- 统一接口: 这是 REST 的核心,它包括:
- 资源标识: 通过 URI 来唯一标识一个资源。
- 通过表述操作资源: 客户端通过获取资源的表述(如 JSON, XML)来操作资源。
- 自描述消息: 每个消息都包含足够的信息来描述如何处理它。
- 超媒体作为应用状态引擎: 客户端通过服务器返回的链接来发现可以执行的操作,而不是硬编码 URL。
RESTful API 就是使用 HTTP 协议来操作服务器上资源的 Web 服务。
Java RESTful API 的主流实现技术
Java 生态中有多种技术可以用来构建 RESTful API。
1. JAX-RS (Java API for RESTful Web Services)
- 描述: 这是 Java EE(现在是 Jakarta EE)中定义的一套官方标准 API,它定义了一套注解(如
@Path,@GET,@POST,@Produces,@Consumes)来简化 RESTful Web 服务的开发。 - 实现框架:
- Jersey: Sun(Oracle)参考实现,也是最早、最成熟的。
- RESTEasy: JBoss 社区的一个实现。
- 优点: 标准化,不与特定服务器绑定。
- 缺点: 配置相对繁琐,需要部署到支持 Java EE 的应用服务器(如 Tomcat, WildFly, WebLogic)。
2. Spring MVC
- 描述: Spring 框架的核心模块之一,虽然它是一个全面的 MVC 框架,但其对 REST 的支持非常出色,通过
@RestController和@RequestMapping等注解,可以非常方便地构建 RESTful 服务。 - 优点: 功能强大,与 Spring 生态系统(如 Spring Data, Spring Security)无缝集成。
- 缺点: 最初是为传统 Web 应用设计的,虽然 REST 支持很好,但并非像 JAX-RS 那样纯粹。
3. Spring Boot
- 描述: 这不是一种新技术,而是对 Spring 的一种“增强”或“约定优于配置”的封装,它极大地简化了 Spring 应用的创建和部署过程。
- 优点:
- 快速启动: 几行代码就能运行一个 Web 应用。
- 内嵌服务器: 无需额外配置 Tomcat 或 Jetty。
- 自动配置: 自动配置 Spring 和第三方库。
- 生态繁荣: 拥有最活跃的社区和最多的第三方库支持。
- 底层仍然是 Spring MVC: 所以你依然在使用成熟、强大的 Spring MVC 来构建 RESTful API。
- 使用 Spring Boot 是开发 Java RESTful API 的绝对主流和首选方案。 本文后续内容将围绕 Spring Boot 展开。
实战:使用 Spring Boot 创建一个 RESTful API
我们将创建一个简单的用户管理 API,包含创建用户、获取所有用户、根据 ID 获取用户、更新用户和删除用户的功能。
1. 环境准备
- JDK 8+
- Maven 3+ 或 Gradle
- IDE (如 IntelliJ IDEA 或 Eclipse)
- API 测试工具 (如 Postman, Insomnia, 或
curl命令)
2. 创建项目和依赖
最简单的方式是使用 Spring Initializr (start.spring.io)。

- Project: Maven Project
- Language: Java
- Spring Boot: 选择一个稳定版本 (如 3.x.x)
- Project Metadata: 填写 Group, Artifact, Name 等。
- Dependencies:
- Spring Web: 提供了构建 Web 应用(包括 RESTful API)的核心支持。
- Spring Data JPA: 用于简化数据库访问。
- H2 Database: 一个内存数据库,方便快速测试和开发。
- Lombok: (可选) 通过注解简化 POJO 类的编写。
点击 "GENERATE" 下载项目,然后用你的 IDE 打开。
3. 定义数据模型
创建一个 User 类,作为我们的数据实体。
// src/main/java/com/example/demo/model/User.java
package com.example.demo.model;
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import lombok.Data;
@Data // Lombok 注解,自动生成 getter, setter, toString 等
@Entity // 声明这是一个 JPA 实体,对应数据库中的一张表
public class User {
@Id // 声明为主键
@GeneratedValue(strategy = GenerationType.IDENTITY) // 主键生成策略为自增
private Long id;
private String name;
private String email;
}
4. 创建 Repository
Repository 是用于数据访问的层,Spring Data JPA 会为我们自动实现 CRUD 方法。
// src/main/java/com/example/demo/repository/UserRepository.java
package com.example.demo.repository;
import com.example.demo.model.User;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
@Repository
public interface UserRepository extends JpaRepository<User, Long> {
// JpaRepository<User, Long> 表示这个 Repository 操作 User 实体,主键类型是 Long
// Spring Data JPA 会自动提供 save(), findById(), findAll(), deleteById() 等方法
}
5. 创建 Controller
Controller 是处理 HTTP 请求并返回响应的核心。

// src/main/java/com/example/demo/controller/UserController.java
package com.example.demo.controller;
import com.example.demo.model.User;
import com.example.demo.repository.UserRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import java.util.List;
import java.util.Optional;
@RestController // @Controller + @ResponseBody,表示所有方法都返回 JSON/XML 数据
@RequestMapping("/api/v1/users") // 定义基础路径
public class UserController {
@Autowired
private UserRepository userRepository;
// GET /api/v1/users - 获取所有用户
@GetMapping
public List<User> getAllUsers() {
return userRepository.findAll();
}
// GET /api/v1/users/{id} - 根据 ID 获取单个用户
@GetMapping("/{id}")
public ResponseEntity<User> getUserById(@PathVariable Long id) {
Optional<User> user = userRepository.findById(id);
// 使用 ResponseEntity 可以更灵活地控制响应状态码和 body
return user.map(ResponseEntity::ok)
.orElse(ResponseEntity.notFound().build());
}
// POST /api/v1/users - 创建一个新用户
@PostMapping
public ResponseEntity<User> createUser(@RequestBody User user) {
// @RequestBody 表示将请求体中的 JSON 数据映射到 User 对象
User savedUser = userRepository.save(user);
return new ResponseEntity<>(savedUser, HttpStatus.CREATED); // 返回 201 Created 状态码
}
// PUT /api/v1/users/{id} - 更新一个已存在的用户
@PutMapping("/{id}")
public ResponseEntity<User> updateUser(@PathVariable Long id, @RequestBody User userDetails) {
return userRepository.findById(id)
.map(user -> {
user.setName(userDetails.getName());
user.setEmail(userDetails.getEmail());
User updatedUser = userRepository.save(user);
return ResponseEntity.ok(updatedUser);
})
.orElse(ResponseEntity.notFound().build());
}
// DELETE /api/v1/users/{id} - 删除一个用户
@DeleteMapping("/{id}")
public ResponseEntity<Void> deleteUser(@PathVariable Long id) {
if (userRepository.existsById(id)) {
userRepository.deleteById(id);
return ResponseEntity.noContent().build(); // 返回 204 No Content 状态码
}
return ResponseEntity.notFound().build();
}
}
6. 启动并测试
- 运行主程序: 找到带有
@SpringBootApplication注解的类,运行其main方法。 - 测试 API:
- 创建用户:
curl -X POST http://localhost:8080/api/v1/users \ -H "Content-Type: application/json" \ -d '{"name": "Alice", "email": "alice@example.com"}' - 获取所有用户:
curl http://localhost:8080/api/v1/users
- 获取单个用户 (假设返回的用户ID是 1):
curl http://localhost:8080/api/v1/users/1
- 更新用户:
curl -X PUT http://localhost:8080/api/v1/users/1 \ -H "Content-Type: application/json" \ -d '{"name": "Alice Smith", "email": "alice.smith@example.com"}' - 删除用户:
curl -X DELETE http://localhost:8080/api/v1/users/1
- 创建用户:
RESTful API 设计原则与最佳实践
一个好的 RESTful API 不仅功能正确,更要易于理解、使用和维护。
1. URL 设计
- 使用名词复数表示资源集合:
/users,/products,/orders,不要使用动词,如/getUsers。 - 版本控制: 在 URL 中加入版本号,如
/api/v1/users,这有助于在不破坏旧版本 API 的情况下进行迭代。 - 过滤、排序、分页:
- 过滤:
GET /users?role=admin&status=active - 排序:
GET /users?sort=name,desc(按 name 降序) - 分页:
GET /users?page=0&size=10(第 0 页,每页 10 条)
- 过滤:
- 嵌套资源: 表示资源之间的关系,如
/users/1/orders(获取用户 1 的所有订单)。
2. HTTP 方法的正确使用
| HTTP 方法 | 行为 | 示例 URI | 幂等性 | 安全性 |
|---|---|---|---|---|
| GET | 获取资源 | /users |
是 | 是 |
| POST | 创建资源 | /users |
否 | 否 |
| PUT | 完整替换资源 | /users/1 |
是 | 否 |
| PATCH | 部分更新资源 | /users/1 |
否 | 否 |
| DELETE | 删除资源 | /users/1 |
是 | 否 |
- 幂等性: 多次执行同一操作,结果与第一次相同,GET, PUT, DELETE 是幂等的。
- 安全性: 不会改变服务器状态,GET 是安全的。
PUT vs PATCH:
PUT /users/1with{"name": "Bob"}: 完全替换用户 1 的信息,如果请求中没有提供email,那么用户的email会被置为null。PATCH /users/1with{"name": "Bob"}: 只更新用户 1 的name字段,email字段保持不变。
3. HTTP 状态码的正确使用
- 2xx - 成功:
200 OK: 通用成功状态码。201 Created: 资源创建成功,应在响应头中包含Location字段,指明新资源的 URI。204 No Content: 删除成功或成功但没有返回内容。
- 4xx - 客户端错误:
400 Bad Request: 请求格式错误或参数无效。401 Unauthorized: 未认证,请求需要用户验证。403 Forbidden: 已认证但无权限。404 Not Found: 资源不存在。405 Method Not Allowed: 不允许的 HTTP 方法。
- 5xx - 服务器错误:
500 Internal Server Error: 服务器内部错误。
4. 数据格式
- 首选 JSON: 现代 Web API 几乎都使用 JSON 作为数据交换格式,因为它轻量、易于人阅读和机器解析。
- Content-Type: 在请求和响应头中明确指定
Content-Type: application/json和Accept: application/json。
5. 错误处理
不要只返回 HTTP 状态码,提供一个结构化的错误响应体,让客户端能明确知道错误原因。
// 错误响应示例 (HTTP 400)
{
"timestamp": "2025-10-27T10:00:00Z",
"status": 400,
"error": "Bad Request",
"message": "邮箱格式不正确",
"path": "/api/v1/users"
}
进阶主题
1. 全局异常处理 (@ControllerAdvice)
使用 @ControllerAdvice 和 @ExceptionHandler 可以创建一个全局的异常处理器,避免在每个 Controller 方法中都写 try-catch。
// src/main/java/com/example/demo/exception/GlobalExceptionHandler.java
package com.example.demo.exception;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.context.request.WebRequest;
import java.util.Date;
@ControllerAdvice
public class GlobalExceptionHandler {
// 处理所有未捕获的异常
@ExceptionHandler(Exception.class)
public ResponseEntity<ErrorDetails> handleGlobalException(Exception ex, WebRequest request) {
ErrorDetails errorDetails = new ErrorDetails(
new Date(),
ex.getMessage(),
request.getDescription(false)
);
return new ResponseEntity<>(errorDetails, HttpStatus.INTERNAL_SERVER_ERROR);
}
// 处理特定异常,比如资源找不到
@ExceptionHandler(ResourceNotFoundException.class)
public ResponseEntity<ErrorDetails> handleResourceNotFoundException(ResourceNotFoundException ex, WebRequest request) {
ErrorDetails errorDetails = new ErrorDetails(
new Date(),
ex.getMessage(),
request.getDescription(false)
);
return new ResponseEntity<>(errorDetails, HttpStatus.NOT_FOUND);
}
}
// 自定义异常类
class ResourceNotFoundException extends RuntimeException {
public ResourceNotFoundException(String message) {
super(message);
}
}
// 错误详情类
class ErrorDetails {
private Date timestamp;
private String message;
private String details;
// ... 构造函数, getter, setter
}
2. 使用 DTO (Data Transfer Object)
直接将 Entity 暴露给 API 客户端是一个坏习惯,因为它会暴露数据库结构,并且难以控制客户端能看到哪些字段。
解决方案: 创建 DTO 类,在 Controller 和 Service 层之间传递数据。
// UserDTO.java
public class UserDTO {
private String name;
private String email;
// 没有 id,因为创建时不需要,更新时可能也不允许客户端提供
// ... getter, setter
}
// UserController 修改
@PostMapping
public ResponseEntity<UserDTO> createUser(@RequestBody UserDTO userDTO) {
// 1. DTO -> Entity
User userToSave = new User();
userToSave.setName(userDTO.getName());
userToSave.setEmail(userDTO.getEmail());
// 2. 保存
User savedUser = userRepository.save(userToSave);
// 3. Entity -> DTO (避免返回敏感信息或多余信息)
UserDTO responseDTO = new UserDTO();
responseDTO.setName(savedUser.getName());
responseDTO.setEmail(savedUser.getEmail());
return new ResponseEntity<>(responseDTO, HttpStatus.CREATED);
}
3. API 文档自动化 (Swagger/OpenAPI)
手动维护 API 文档是件痛苦且容易出错的事。Swagger (现为 OpenAPI Initiative) 是一个强大的工具,可以自动生成、描述、测试和记录你的 RESTful API。
在 Spring Boot 项目中,只需添加 springdoc-openapi-starter-webmvc-ui 依赖,即可在运行时访问一个交互式的 UI 文档页面(通常在 /swagger-ui.html 或 /api-docs)。
4. 认证与授权
- 认证: 验证用户身份,常用方式有 JWT (JSON Web Token)、Session-Cookie、OAuth2。
- 授权: 验证用户是否有权限访问某个资源。
Spring Security 是 Java 生态中处理认证和授权的黄金标准,它可以轻松地与 JWT 集成,为你的 API 提供安全保障。
开发 Java RESTful API,Spring Boot 是目前最强大、最高效的选择,理解 REST 的核心设计原则,并遵循 URL、HTTP 方法、状态码等最佳实践,是构建高质量 API 的基础,随着项目复杂度的增加,引入 DTO、全局异常处理、API 文档和认证授权机制,将使你的 API 更加健壮、安全和易于维护。
