RESTful API
什么是RESTful API:
REST(REpresentational State Transfer:表现层状态转换)是一种设计网络应用程序的架构风格,是一种流行的接口规范,是一种软件架构风格、设计风格,而不是标准,只是提供了一组设计原则和约束条件。它主要用于客户端和服务器交互类的软件。基于这个风格设计的软件可以更简洁,更有层次,更易于实现缓存等机制。
REST并没有一个明确的标准,而更像是一种设计的风格,满足这种设计风格的程序或接口我们称之为RESTful(从单词字面来看就是一个形容词)。所以RESTful API 就是满足REST架构风格的接口。
综上,就是REST与RESTful的联系与区别
REST架构特征:
RESTful是一种风格而不是标准,这个风格有以下几个特征:
1. 客户端-服务器分离(Client-Server Architecture)
特征:客户端负责用户界面和交互逻辑,服务器负责数据处理和存储,两者独立演化。
意义:解耦前端和后端,支持不同团队分工协作,提升可扩展性。
例子:浏览器(客户端)请求服务器 API 获取数据,渲染页面。
2. 无状态(Stateless)
特征:每个客户端请求必须包含服务器处理该请求所需的所有信息,服务器不保存客户端状态。
意义:简化服务器设计,提高可伸缩性(无需维护会话状态)。
例子:
✅ 正确:客户端在请求头中携带 Token(如
Authorization: Bearer xxx
)标识身份。❌ 错误:服务器依赖 Session ID 维护登录状态。
3. 可缓存(Cacheable)
特征:服务器需明确告知客户端哪些响应可以缓存,客户端或中间层(如 CDN)可缓存响应。
意义:减少重复请求,提升性能。
实现方式:
HTTP 头部字段:
Cache-Control: max-age=3600
(缓存 1 小时)。状态码:
304 Not Modified
(资源未变化,使用本地缓存)。
4. 统一接口(Uniform Interface)
特征:客户端与服务器的交互方式标准化,包括:
资源标识:通过 URI(如
/users/123
)唯一标识资源。资源操作:通过 HTTP 方法(GET、POST、PUT、DELETE)定义操作。
自描述消息:消息(请求/响应)包含足够信息供接收方处理(如
Content-Type: application/json
)。HATEOAS(可选):响应中提供资源相关的链接(如
"links": { "self": "/users/123" }
),客户端通过链接导航。
意义:降低系统耦合度,提升通用性。
5. 分层系统(Layered System)
特征:系统可分层构建(如负载均衡、缓存层、安全层),客户端无需关心底层结构。
意义:增强可扩展性和安全性。
例子:
客户端请求 → 负载均衡器 → 缓存层 → 应用服务器 → 数据库。
6. 按需代码(Code-On-Demand,可选)
特征:服务器可向客户端发送可执行代码(如 JavaScript),动态扩展客户端功能。
意义:灵活性高,但非强制要求。
例子:网页中嵌入 JavaScript 脚本,由浏览器执行。
REST 架构的衍生特征
除了六大核心约束,REST 架构在实践中还表现出以下特征:
1. 资源为中心(Resource-Oriented)
一切数据抽象为资源(如用户、订单),通过 URI 唯一标识。
例子:
/products/456
表示 ID 为 456 的商品。
2. 使用标准 HTTP 方法
通过 HTTP 方法(GET、POST、PUT、DELETE 等)表达操作意图,而非在 URI 中使用动词。
✅ 正确:
DELETE /users/123
(删除用户)。❌ 错误:
GET /deleteUser?id=123
。
3. 无会话(Sessionless)
服务器不维护客户端状态,每次请求独立处理。
实现方式:客户端通过 Token、API Key 等机制传递身份信息。
4. 支持多种数据格式
数据格式不限定(如 JSON、XML),但需在请求头中声明(如
Accept: application/json
)。
补充:
使用 Spring Boot 或 Spring MVC 框架本身不意味着自动符合 RESTful 规范。RESTful 是一种架构风格,而 Spring MVC 是技术实现工具。关键区别在于如何设计接口,而不仅仅是技术选型。
Spring MVC 可以构建 RESTful 接口,但也能构建非 RESTful 的传统 MVC 接口(如返回 HTML 页面)。
是否符合 RESTful 取决于接口设计,而非框架本身。
反例:
@Controller // 注意是 @Controller,不是 @RestController
public class UserController {
@GetMapping("/users")
public String listUsers(Model model) {
model.addAttribute("users", userService.findAll());
return "users.html"; // 返回 HTML 视图
}
}
返回 HTML 页面,而非资源的表现层(如 JSON),属于传统 MVC 模式。
@RestController
public class BadController {
// ❌ 路径包含动词,且使用 GET 方法修改资源
@GetMapping("/createUser")
public User createUser(@RequestParam String name) {
return userService.save(name);
}
}
URI 包含动词
createUser
(应改为/users
+POST
方法)。GET 方法用于修改资源(违反 HTTP 语义)。
正例:
@RestController
@RequestMapping("/api/users")
public class UserController {
// 获取所有用户(GET 方法 + 资源路径)
@GetMapping
public List<User> getAllUsers() {
return userService.findAll();
}
// 创建用户(POST 方法 + 资源路径)
@PostMapping
@ResponseStatus(HttpStatus.CREATED)
public User createUser(@RequestBody User user) {
return userService.save(user);
}
// 获取单个用户(GET 方法 + 资源 ID)
@GetMapping("/{id}")
public User getUserById(@PathVariable Long id) {
return userService.findById(id);
}
// 更新用户(PUT 方法 + 资源 ID)
@PutMapping("/{id}")
public User updateUser(@PathVariable Long id, @RequestBody User user) {
return userService.update(id, user);
}
// 删除用户(DELETE 方法 + 资源 ID)
@DeleteMapping("/{id}")
@ResponseStatus(HttpStatus.NO_CONTENT)
public void deleteUser(@PathVariable Long id) {
userService.delete(id);
}
}
符合 RESTful 的关键点:
✅ URI 使用名词
/users
,而非动词。✅ 正确使用 HTTP 方法(GET/POST/PUT/DELETE)。
✅ 返回 JSON 数据(资源的表现层)。
✅ 无状态(不依赖 Session 等服务器状态)。
Tip:前后端分离是一种架构模式(前端和后端独立开发部署),而 RESTful 是一种接口设计风格(关注资源、HTTP 方法、状态码)。二者可以自由组合,没有必然绑定。Thymeleaf 是服务端渲染技术(适合简单页面或 SEO),但后端依然可以同时提供 RESTful API(供其他客户端调用)。