一、RESTful 架构核心概念
1. REST 六大原则
-
客户端-服务器分离:前后端分离架构
-
无状态:每次请求包含完整信息
-
可缓存:明确标识可缓存资源
-
统一接口:HTTP方法标准化操作
-
分层系统:中间件透明处理
-
按需代码:可选的客户端扩展
2. REST vs SOAP
REST:
- 基于HTTP
- 轻量级,易理解
- JSON/XML格式
- 性能更好
SOAP:
- 基于XML
- 协议复杂
- 自带WS-Security
- 企业级应用
二、RESTful API 设计规范
1. 资源命名规范
// 使用名词复数形式
GET /api/users // 获取用户列表
GET /api/users/{id} // 获取单个用户
POST /api/users // 创建用户
PUT /api/users/{id} // 更新用户(全量)
PATCH /api/users/{id} // 更新用户(部分)
DELETE /api/users/{id} // 删除用户
GET /api/users/{id}/orders // 获取用户的订单
2. HTTP 方法语义
| 方法 | 幂等性 | 安全性 | 描述 |
|---|---|---|---|
| GET | 是 | 是 | 获取资源 |
| POST | 否 | 否 | 创建资源 |
| PUT | 是 | 否 | 全量更新资源 |
| PATCH | 否 | 否 | 部分更新资源 |
| DELETE | 是 | 否 | 删除资源 |
| HEAD | 是 | 是 | 获取响应头 |
| OPTIONS | 是 | 是 | 获取支持方法 |
3. 版本管理策略
// 方案1:URI路径版本
GET /api/v1/users
GET /api/v2/users
// 方案2:查询参数版本
GET /api/users?version=1
// 方案3:请求头版本
Accept: application/vnd.myapp.v1+json
// 推荐:URI路径版本,简单直观
4. 响应设计规范
// 统一响应格式
{
"code": 200, // 状态码
"message": "success", // 消息
"data": { ... }, // 数据
"timestamp": 1631234567
}
// 分页响应
{
"code": 200,
"message": "success",
"data": {
"items": [...], // 数据列表
"total": 100, // 总记录数
"page": 1, // 当前页
"size": 10, // 每页大小
"pages": 10 // 总页数
}
}
三、HTTP 状态码使用
1. 常见状态码
// 2xx 成功
200 OK // 请求成功
201 Created // 创建成功
204 No Content // 删除成功,无返回体
// 3xx 重定向
301 Moved Permanently // 永久重定向
302 Found // 临时重定向
304 Not Modified // 资源未修改
// 4xx 客户端错误
400 Bad Request // 请求格式错误
401 Unauthorized // 未认证
403 Forbidden // 无权限
404 Not Found // 资源不存在
409 Conflict // 资源冲突
422 Unprocessable Entity // 参数验证失败
// 5xx 服务器错误
500 Internal Server Error // 服务器内部错误
502 Bad Gateway // 网关错误
503 Service Unavailable // 服务不可用
2. 状态码使用场景
POST /api/users → 201 Created
GET /api/users/1 → 200 OK
DELETE /api/users/1 → 204 No Content
PUT /api/users/1 → 200 OK
GET /api/users/999 → 404 Not Found
POST /api/users (重复) → 409 Conflict
四、请求参数设计
1. 参数传递方式
// 路径参数
GET /api/users/{id}
@PathVariable Long id
// 查询参数
GET /api/users?name=jack&age=20
@RequestParam String name
@RequestParam(required = false) Integer age
// 请求体参数
POST /api/users
@RequestBody User user
// 请求头参数
@RequestHeader("Authorization") String token
// 表单参数
@RequestParam Map<String, String> params
2. 查询参数规范
// 过滤
GET /api/users?name=jack&age_gt=18&age_lt=30
// 分页
GET /api/users?page=1&size=10&sort=name,asc&sort=age,desc
// 字段选择
GET /api/users?fields=id,name,email
// 搜索
GET /api/users?q=keyword&searchFields=name,email
五、安全性设计
1. 认证与授权
// 1. JWT认证
@PostMapping("/login")
public Result login(@RequestBody LoginRequest request) {
// 验证用户名密码
String token = jwtUtil.generateToken(user);
return Result.success(token);
}
// 2. 接口鉴权
@GetMapping("/admin/users")
@PreAuthorize("hasRole('ADMIN')")
public Result getAdminUsers() {
// 需要ADMIN角色
}
2. API 安全措施
# 防止常见攻击
- 输入验证和清理
- SQL注入防护
- XSS防护
- CSRF Token
- 速率限制
- HTTPS强制
- 参数加密
六、API 文档
1. Swagger/OpenAPI 配置
@Configuration
@EnableOpenApi
public class SwaggerConfig {
@Bean
public Docket api() {
return new Docket(DocumentationType.OAS_30)
.apiInfo(apiInfo())
.select()
.apis(RequestHandlerSelectors.basePackage("com.example"))
.paths(PathSelectors.any())
.build();
}
private ApiInfo apiInfo() {
return new ApiInfoBuilder()
.title("用户管理API")
.description("用户管理接口文档")
.version("1.0")
.build();
}
}
2. API 文档注解
@Api(tags = "用户管理")
@RestController
@RequestMapping("/api/users")
public class UserController {
@ApiOperation("获取用户列表")
@ApiImplicitParams({
@ApiImplicitParam(name = "page", value = "页码", dataType = "int"),
@ApiImplicitParam(name = "size", value = "每页数量", dataType = "int")
})
@GetMapping
public Result<List<User>> getUsers(
@RequestParam(defaultValue = "1") int page,
@RequestParam(defaultValue = "10") int size) {
// 实现
}
}
七、错误处理
1. 全局异常处理
@RestControllerAdvice
public class GlobalExceptionHandler {
// 业务异常
@ExceptionHandler(BusinessException.class)
public Result handleBusinessException(BusinessException e) {
return Result.error(e.getCode(), e.getMessage());
}
// 参数验证异常
@ExceptionHandler(MethodArgumentNotValidException.class)
public Result handleValidationException(MethodArgumentNotValidException e) {
String message = e.getBindingResult()
.getFieldErrors()
.stream()
.map(fieldError -> fieldError.getField() + ": " + fieldError.getDefaultMessage())
.collect(Collectors.joining("; "));
return Result.error(400, message);
}
// 未授权异常
@ExceptionHandler(AccessDeniedException.class)
public Result handleAccessDeniedException(AccessDeniedException e) {
return Result.error(403, "无权访问");
}
}
2. 自定义异常
public class BusinessException extends RuntimeException {
private final int code;
public BusinessException(int code, String message) {
super(message);
this.code = code;
}
public int getCode() {
return code;
}
}
// 使用
throw new BusinessException(1001, "用户不存在");
八、性能优化
1. 缓存策略
// HTTP缓存
@GetMapping("/users/{id}")
@CacheControl(maxAge = 3600) // 缓存1小时
public ResponseEntity<User> getUser(@PathVariable Long id) {
User user = userService.getUser(id);
return ResponseEntity.ok()
.cacheControl(CacheControl.maxAge(1, TimeUnit.HOURS))
.eTag(user.getVersion().toString())
.body(user);
}
2. 分页优化
// 避免深度分页
@GetMapping("/users")
public Result<PageResult<User>> getUsers(
@RequestParam(defaultValue = "1") int page,
@RequestParam(defaultValue = "10") int size) {
// 使用游标分页
if (page > 100) {
throw new BusinessException(400, "分页深度过大");
}
// 使用覆盖索引
Page<User> userPage = userRepository.findAll(PageRequest.of(page-1, size));
return Result.success(PageResult.of(userPage));
}
九、API 测试
1. Postman 测试
# 测试用例设计
- 正常场景测试
- 边界值测试
- 异常场景测试
- 性能测试
- 安全性测试
2. 单元测试
@SpringBootTest
@AutoConfigureMockMvc
class UserControllerTest {
@Autowired
private MockMvc mockMvc;
@MockBean
private UserService userService;
@Test
void testGetUser() throws Exception {
// 准备数据
User user = new User(1L, "张三", "zhangsan@example.com");
when(userService.getUser(1L)).thenReturn(user);
// 执行请求
mockMvc.perform(get("/api/users/1")
.contentType(MediaType.APPLICATION_JSON))
.andExpect(status().isOk())
.andExpect(jsonPath("$.code").value(200))
.andExpect(jsonPath("$.data.name").value("张三"));
}
}
十、API 网关与监控
1. 网关功能
# 常见网关功能
- 路由转发
- 负载均衡
- 限流熔断
- 身份认证
- 日志监控
- API聚合
2. 监控指标
// 重要监控指标
- 请求量(QPS)
- 响应时间(P50, P90, P99)
- 错误率
- 成功率
- 吞吐量
- 系统资源(CPU, 内存)
十一、版本管理策略
1. 版本演进示例
// v1版本
@GetMapping("/api/v1/users/{id}")
public UserV1 getUserV1(@PathVariable Long id) {
// 返回v1数据结构
}
// v2版本 - 向后兼容
@GetMapping("/api/v2/users/{id}")
public UserV2 getUserV2(@PathVariable Long id) {
// 返回v2数据结构
// 可以兼容v1客户端
}
// 弃用旧版本
@Deprecated
@GetMapping("/api/v1/users/{id}")
public UserV1 getUserV1(@PathVariable Long id) {
// 返回弃用信息
}
十二、实际案例设计
1. 电商用户模块 API 设计
// 用户模块接口
POST /api/v1/register // 注册
POST /api/v1/login // 登录
POST /api/v1/logout // 登出
GET /api/v1/users/{id} // 获取用户信息
PUT /api/v1/users/{id} // 更新用户信息
PATCH /api/v1/users/{id}/password // 修改密码
GET /api/v1/users/{id}/orders // 用户订单
GET /api/v1/users/{id}/addresses // 用户地址
POST /api/v1/users/{id}/addresses // 添加地址
2. 订单模块 API 设计
// 订单模块接口
GET /api/v1/orders // 订单列表
POST /api/v1/orders // 创建订单
GET /api/v1/orders/{id} // 订单详情
PUT /api/v1/orders/{id} // 更新订单
DELETE /api/v1/orders/{id} // 取消订单
POST /api/v1/orders/{id}/pay // 支付订单
GET /api/v1/orders/{id}/items // 订单商品
十三、常见面试题
1. RESTful 设计原则题
Q: 设计一个博客系统的API接口
要求:
1. 用户可以发布、修改、删除文章
2. 文章可以被分类、打标签
3. 用户可以评论文章
4. 需要支持分页查询
你的设计方案:
2. 实际问题解决题
Q: 如何设计一个支持高并发的短链接生成服务?
考虑点:
1. 短链接生成算法
2. 重定向性能优化
3. 防重复设计
4. 过期机制
5. 统计功能
3. API 设计评审题
// 找出以下API设计的问题
GET /getUserList
POST /addUser
POST /updateUser
GET /deleteUser?id=1
POST /userLogin
GET /getOrdersByUserId?userId=1
面试准备要点:
-
深入理解RESTful设计原则
-
掌握HTTP协议和状态码
-
熟悉Spring Boot实现RESTful API
-
了解API安全性和性能优化
-
准备实际项目设计案例
-
熟悉API文档和测试工具
-
了解微服务架构下的API设计
高频问题:
-
RESTful API设计规范
-
HTTP方法的选择依据
-
如何设计版本管理
-
如何保证API安全性
-
如何处理API兼容性
-
如何设计分页接口
-
如何进行API性能优化
-
如何设计错误处理机制