1、重构的本质与 API 演进的哲学
1.1 API 作为契约的隐喻_稳定与演进的平衡艺术
技术解析
API 本质是服务提供者与消费者之间的数字契约。重构的难点在于:如何在保证现有消费者不受影响(契约稳定)的前提下,实现技术升级和功能扩展(契约演进)。
经典案例
某金融平台将交易流水 ID 从 int
升级为 UUID
字符串格式,需保证旧客户端(依赖数值型 ID 排序)不受影响:
// 新旧 ID 兼容方案
public class Transaction {
@JsonIgnore // 新字段不暴露给旧客户端
private String uuid;
@JsonProperty("id")
@Deprecated
public long getLegacyId() {
return convertUuidToLong(uuid); // 生成兼容 ID
}
}
// 旧客户端仍接收数值型 ID
// 新客户端通过 Header 指定版本获取 UUID
@GetMapping(value = "/transactions/{id}", headers = "X-API-Version=2")
public TransactionV2 getTransactionV2(@PathVariable String id) {
return service.findByUuid(id);
}
演进策略
- 显式版本控制:通过 URL 路径、Header 或 Query 参数声明版本
- 隐式兼容处理:在数据层进行双向转换,隔离新旧格式差异
1.2 向后兼容的四个层次_构建全方位防御体系
层次 | 技术要点 | 防御方案示例 |
---|---|---|
语法兼容 | 字段名/类型/结构变更 | 使用 Jackson 的 @JsonAlias 处理字段重命名 |
语义兼容 | 业务逻辑一致性维护 | 金额单位转换时新旧接口并存 |
协议兼容 | HTTP 方法/状态码规范 | 用 308 替代 301 实现永久重定向 |
安全兼容 | 认证鉴权机制升级 | OAuth 1.0 与 2.0 双协议支持 |
协议层示例:正确处理 HTTP 308 状态码
# 旧路径永久重定向
location /old-api {
return 308 /new-api$request_uri;
}
2、向后兼容的设计原则与模式
2.1 Hyrum’s Law 的警示_隐式契约的破坏与防御
问题场景
某社交平台将用户列表的默认分页大小从 20 改为 10,导致依赖默认值的客户端数据展示不全。
防御方案
@GetMapping("/posts")
public Page<Post> getPosts(
@RequestParam(defaultValue = "20") int size, // 显式声明默认值
@RequestParam(required = false) String cursor
) {
if (size > 100) throw new InvalidParamException("分页大小超限")