一、RESTful API 是什么?
一句话定义
RESTful API 是一种基于 HTTP 协议的软件架构风格,它使用标准 HTTP 方法(GET、POST、PUT、DELETE 等)对资源进行操作,让 Web 服务的设计更加简洁、统一。
核心原则(REST 六大约束)
-
客户端-服务器分离:前后端分离,独立演化
-
无状态:每次请求都包含所有必要信息,服务器不保存会话状态
-
可缓存:响应必须明确是否可缓存
-
统一接口:使用标准 HTTP 方法和状态码
-
分层系统:客户端不知道是与服务器还是中间件通信
-
按需代码(可选):服务器可返回可执行代码(如 JavaScript)
RESTful 的设计特征
# 传统 API(非 RESTful)
GET /getUser?id=1
POST /updateUser
GET /deleteUser?id=1
# RESTful API(资源导向)
GET /users/1 # 获取用户1
PUT /users/1 # 更新用户1
DELETE /users/1 # 删除用户1
POST /users # 创建新用户
实际示例
// RESTful 风格的控制器
@RestController
@RequestMapping("/api/products")
public class ProductController {
// GET /api/products - 获取所有产品
@GetMapping
public List<Product> getAllProducts() {
return productService.findAll();
}
// GET /api/products/{id} - 获取单个产品
@GetMapping("/{id}")
public Product getProduct(@PathVariable Long id) {
return productService.findById(id);
}
// POST /api/products - 创建产品
@PostMapping
public Product createProduct(@RequestBody Product product) {
return productService.save(product);
}
// PUT /api/products/{id} - 更新产品
@PutMapping("/{id}")
public Product updateProduct(@PathVariable Long id,
@RequestBody Product product) {
return productService.update(id, product);
}
// DELETE /api/products/{id} - 删除产品
@DeleteMapping("/{id}")
public void deleteProduct(@PathVariable Long id) {
productService.delete(id);
}
}
二、GET 和 POST 的区别
对比表格
| 特性 | GET | POST |
|---|---|---|
| 语义 | 获取数据(安全、幂等) | 提交数据(不安全、不幂等) |
| 参数位置 | URL 查询字符串 | 请求体(Body) |
| 参数可见性 | 明文显示在 URL | 隐藏在请求体中 |
| 数据长度 | 有限制(URL长度限制) | 无限制(理论上) |
| 安全性 | 较低(参数在URL中) | 较高(参数在Body中) |
| 缓存 | 可被缓存 | 不可缓存 |
| 浏览器历史 | 保留记录 | 不保留记录 |
| 后退/刷新 | 无害 | 会重新提交(浏览器提示) |
| 幂等性 | 幂等(多次请求结果相同) | 不幂等(每次可能产生不同结果) |
| 书签 | 可收藏为书签 | 不可收藏 |
详细解释
1. 语义区别(最重要)
-
GET :获取资源,不应改变服务器状态
GET /api/users/123 GET /api/products?category=electronics&page=2 -
POST :创建新资源,改变服务器状态
POST /api/users Content-Type: application/json {"name": "张三", "email": "zhangsan@example.com"}
2. 幂等性
-
GET 是幂等的:执行 1 次和 N 次效果相同
# 无论请求多少次,都不会创建新用户 GET /api/users/1 ✅ 安全 GET /api/users/1 ✅ 安全 GET /api/users/1 ✅ 安全 -
POST 不是幂等的:每次可能产生不同结果
# 每次请求都会创建新用户 POST /api/users → 创建用户A POST /api/users → 创建用户B POST /api/users → 创建用户C
3. 安全性
-
GET 是安全的:不应改变数据(只读)
-
POST 不安全:会改变数据
4. 参数传递
# GET - 参数在URL中
GET /api/search?keyword=java&page=1&size=20
# POST - 参数在Body中
POST /api/login
Content-Type: application/x-www-form-urlencoded
username=zhangsan&password=123456
# POST with JSON
POST /api/users
Content-Type: application/json
{
"name": "张三",
"age": 25,
"email": "zhangsan@example.com"
}
5. 缓存机制
// GET 请求可以被缓存
@GetMapping("/products/{id}")
@Cacheable(value = "products", key = "#id") // Spring Cache
public Product getProduct(@PathVariable Long id) {
return productService.findById(id);
}
// POST 请求不应该被缓存
@PostMapping("/orders")
public Order createOrder(@RequestBody OrderRequest request) {
return orderService.create(request); // 每次都执行
}
6. 实际使用场景
// ✅ GET 的正确使用场景
@GetMapping("/users") // 获取用户列表
@GetMapping("/users/{id}") // 获取单个用户
@GetMapping("/users/{id}/orders") // 获取用户的订单
@GetMapping("/search") // 搜索(参数少时)
// ✅ POST 的正确使用场景
@PostMapping("/users") // 创建用户
@PostMapping("/login") // 用户登录
@PostMapping("/orders") // 下订单
@PostMapping("/search") // 复杂搜索(参数多时)
三、面试回答模板
问题1:RESTful API 是什么?
标准回答:
"RESTful API 是一种基于 HTTP 协议的架构风格,核心思想是把一切视为资源,用统一的接口进行操作。它有六个约束原则,最重要的是无状态和统一接口。"
"具体来说,它用 URL 表示资源,用 HTTP 方法表示操作:GET 获取、POST 创建、PUT 更新、DELETE 删除。比如用户资源:GET /users 获取列表,POST /users 创建用户,GET /users/1 获取用户1,PUT /users/1 更新用户1,DELETE /users/1 删除用户1。"
加分回答:
"在我们项目中,RESTful API 带来了三个好处:第一是前后端解耦,前端只需要知道接口规范;第二是可缓存性提升性能;第三是自描述性,看 URL 就知道操作什么资源。"
问题2:GET 和 POST 有什么区别?
标准回答:
"GET 和 POST 有五大核心区别:
语义不同:GET 获取数据,POST 提交数据
参数位置:GET 在 URL 中,POST 在请求体里
安全性:GET 是安全的(只读),POST 不安全(会改数据)
幂等性:GET 是幂等的,POST 不是幂等的
可缓存性:GET 可缓存,POST 不可缓存"
"实际开发中,获取数据用 GET,创建数据用 POST。敏感数据如密码一定要用 POST,避免在 URL 中暴露。"
场景化回答:
"比如电商网站,搜索商品用 GET:
/api/products?q=手机&page=1,参数在 URL 中,可以收藏链接。下单用 POST:/api/orders,订单数据在请求体里,避免刷新重复下单。"
问题3:什么时候用 GET?什么时候用 POST?
判断标准:
-
用 GET:
-
获取数据(搜索、列表、详情)
-
参数少且不敏感
-
希望结果可缓存、可收藏
-
幂等操作(多次执行结果相同)
-
-
用 POST:
-
创建新资源(注册、下单)
-
参数多或包含敏感信息
-
改变服务器状态的操作
-
非幂等操作(每次可能不同)
-
实际示例:
# ✅ GET 合适场景
GET /api/articles?category=tech # 获取文章列表
GET /api/users/123 # 获取用户信息
GET /api/products/search?q=手机 # 搜索商品
# ✅ POST 合适场景
POST /api/login # 用户登录(密码敏感)
POST /api/orders # 创建订单(改变状态)
POST /api/files/upload # 上传文件(数据量大)
POST /api/payments # 支付请求(敏感操作)
四、高级话题(加分项)
1. 其他 HTTP 方法
-
PUT:更新整个资源(幂等)
-
PATCH:部分更新资源(不幂等)
-
DELETE:删除资源(幂等)
-
HEAD:获取响应头
-
OPTIONS:获取支持的 HTTP 方法
2. 幂等性实践
// PUT 是幂等的
@PutMapping("/users/{id}")
public User updateUser(@PathVariable Long id, @RequestBody User user) {
// 无论调用多少次,结果都一样
return userService.update(id, user);
}
// PATCH 可能不幂等
@PatchMapping("/users/{id}/balance")
public User addBalance(@PathVariable Long id, @RequestParam BigDecimal amount) {
// 每次调用余额增加,不幂等
return userService.addBalance(id, amount);
}
3. RESTful 最佳实践
-
使用复数名词:
/users而不是/user -
使用嵌套资源表示关系:
/users/1/orders -
使用合适的状态码:200 OK、201 Created、404 Not Found
-
版本控制:
/api/v1/users或 Header 中指定版本 -
过滤、分页、排序:
/users?active=true&page=2&size=20&sort=name,desc
一句话总结 :RESTful 是用 URL 定位资源,用 HTTP 方法描述操作;GET 是安全的只读操作,POST 是创建资源的非安全操作。