SpringMVC RESTful 核心要点
使用 SpringMVC 快速构建符合 REST 风格的 API
RESTful说明
REST 是 Representational State Transfer(表述性状态转移)的缩写,RESTful 是一种设计 Web 服务(API)的风格或规范,而不是一个具体的技术或标准。它的核心思想是:把服务器上的数据或功能都看作“资源”(Resource),然后通过标准的 HTTP 方法来操作这些资源。构建以资源 (URI) 为中心、表述可协商 (JSON/XML)、无状态、可缓存、接口统一的 Web 服务。
RESTful API 的核心特点
以资源为中心
任何数据或服务都抽象成“资源”,用 /users/123 这类唯一地址定位。
统一接口
这是 REST 最核心的约束。用 HTTP 方法(GET/POST/PUT/PATCH/DELETE…)表达动作,URI 永远只做名词。
GET
:检索/获取资源的表述。POST
:创建新资源。PUT
:整体替换/更新已存在资源。也可用于创建(如果客户端知道完整 URI)。DELETE
:删除资源。PATCH
:部分更新资源。HEAD
:获取资源的元数据。OPTIONS
:获取资源支持的通信选项。操作语义由 HTTP 方法定义,而非 URI 或请求体中的动词。URI 仅标识资源本身(名词)。
表述性
- 交换的是“副本”:客户端拿到的是资源的某种格式副本(JSON/XML…),通过 Accept/Content-Type 协商。
无状态
服务器不记状态,所有上下文随请求一次性带齐。
可缓存
响应声明缓存策略,客户端/中间层按需复用。
客户端-服务器分离
客户端管 UI,服务器管数据;二者只通过标准 HTTP 对话,可独立升级。
分层系统
架构可叠加代理、网关等层,必要时服务器还能把代码(如 JS)推给客户端临时扩展功能。
按需代码
服务器可以临时扩展客户端功能,例如向客户端发送可执行代码(如 JavaScript 小程序)。
这是 REST 中唯一一个可选的约束,在 Web API 设计中较少使用。
核心注解
注解 | 作用描述 | 常用位置 | |
---|---|---|---|
@RestController | 核心,标记整个类为 REST 控制器。等于 @Controller + @ResponseBody 。所有方法返回值直接写入 HTTP 响应体 (JSON/XML)。 | 类上方 | |
| 映射 HTTP GET 请求到方法。用于查询/获取资源。 | 方法上方 | |
| 映射 HTTP POST 请求到方法。用于创建新资源。 | 方法上方 | |
| 映射 HTTP PUT 请求到方法。用于整体更新已有资源。 | 方法上方 | |
| 映射 HTTP DELETE 请求到方法。用于删除资源。 | 方法上方 | |
| 定义基础请求路径。常与 method 属性一起用,但更推荐用上面的专用注解。 | 类或方法上方 | |
| 从 URL 路径中获取变量值。例如 /users/{id} 中的 {id} 。 | 方法参数前 | |
| 将 HTTP 请求体 (通常是 JSON) 绑定到 Java 对象。用于接收客户端提交的数据。 | 方法参数前 |
构造响应
方式/注解 | 作用描述 | 何时使用 | |
---|---|---|---|
直接返回对象 | 最简单!方法返回对象,Spring 自动转 JSON。状态码默认 200 OK。 | 查询成功时 | |
| 完全控制响应:状态码 + 响应头 + 响应体。最推荐常用方式 | 需要精确控制状态码、添加响应头时 | |
| 标注在方法或异常类上,指定返回的 HTTP 状态码。 | 方法成功执行需特定状态码,或统一异常处理时 |
一些常用的状态码
200 OK
:成功 (GET/PUT/PATCH)201 Created
:资源创建成功 (POST), 务必在响应头Location
中返回新资源URI204 No Content
:操作成功,无返回内容 (DELETE)400 Bad Request
:客户端请求错误 (如参数校验失败)404 Not Found
:资源不存在500 Internal Server Error
:服务器内部错误
一些错误处理
方式 | 作用描述 | 关键点 | |
---|---|---|---|
@ExceptionHandler | 在控制器内处理特定类型的异常。 | 快速处理单个控制器内的特定错误。 | |
@ControllerAdvice | 全局! 定义类处理所有控制器抛出的异常。推荐! | 统一处理整个应用的异常,返回结构化错误信息。 |
URI设计实践
用名词(复数),别用动词:
/users
(好),/getUsers
(不好)。层级表示关系:
/users/{userId}/orders
(获取某用户的所有订单)。HTTP 方法代表操作:
GET /users
- 获取用户列表GET /users/123
- 获取 ID=123 的用户POST /users
- 创建新用户PUT /users/123
- 整体更新 ID=123 的用户DELETE /users/123
- 删除 ID=123 的用户
版本控制 (简单做法): 把版本号放在 URI 开头,例如
/api/v1/users
。
常用流程复习
类上加 @RestController
和基础路径 @RequestMapping
。
方法上加 @GetMapping
/@PostMapping
/@PutMapping
/@DeleteMapping
定义具体路径和操作。
用 @PathVariable
获取 URL 中的参数。
用 @RequestBody
接收客户端发来的 JSON 数据 (POST/PUT)。
方法返回 ResponseEntity
精确控制状态码和响应体 (最灵活),或直接返回对象 (默认 200 OK)。
用 @ControllerAdvice
全局处理异常,返回友好的错误信息 JSON。
接下来演示一个restful的web示例
示例
创建用户
@RestController
@RequestMapping("/api/v1/users") // ① 类注解:REST控制器 + 基础路径
public class UserController {@PostMapping // ② 方法注解:处理 POST 请求到 /api/v1/userspublic ResponseEntity<User> createUser(@RequestBody User newUser) { // ③ 接收请求体JSON转对象User savedUser = userService.save(newUser); // 业务逻辑// ④ 构造新资源的URI (重要!符合RESTful)URI location = ServletUriComponentsBuilder.fromCurrentRequest() // 当前请求URI: /api/v1/users.path("/{id}") // 追加 /{id}.buildAndExpand(savedUser.getId()) // 替换 {id} 为真实ID.toUri();return ResponseEntity.created(location).body(savedUser); // ⑤ 返回201 Created + Location头 + 新用户JSON}// ... 其他方法 (GET /{id}, PUT /{id}, DELETE /{id}) ...
}
全局异常处理
@RestControllerAdvice
public class GlobalExceptionHandler {@ExceptionHandler(UserNotFoundException.class) // 处理特定异常public ResponseEntity<ErrorMsg> handleUserNotFound(UserNotFoundException ex) {ErrorMsg error = new ErrorMsg(404, "User Not Found", ex.getMessage());return ResponseEntity.status(HttpStatus.NOT_FOUND).body(error); // 返回404和JSON错误信息}@ExceptionHandler(Exception.class) // 兜底,处理所有其他异常public ResponseEntity<ErrorMsg> handleAll(Exception ex) {ErrorMsg error = new ErrorMsg(500, "Internal Server Error", "An unexpected error occurred");return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(error); // 返回500和JSON错误信息}
}