<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>api-design on </title>
    <link>/tags/api-design/</link>
    <description>Recent content in api-design on </description>
    <generator>Hugo -- gohugo.io</generator>
    <language>en</language>
    <lastBuildDate>Wed, 06 May 2026 10:00:00 +0800</lastBuildDate><atom:link href="/tags/api-design/index.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>Contract First 落地实践：工具栈、团队协作与我踩到的坑</title>
      <link>/posts/openapi-contract-first-workflow/</link>
      <pubDate>Wed, 06 May 2026 10:00:00 +0800</pubDate>
      
      <guid>/posts/openapi-contract-first-workflow/</guid>
      <description>Contract First（也叫 API First）的理念并不新鲜：在写任何代码之前，先把 API 的形状定义清楚，让前后端、移动端、第三方消费者都从这份约定出发并行开发。但这套思路在很多团队里一直停留在 PPT，原因往往不是不认可，而是落地成本比想象中高——谁来写 spec、风格谁来管、变更谁来通知、breaking change 谁来拦，每一个问题都可能让一个团队悄悄退回 Code First。
这篇是我自己在 Spring Boot + 前端栈（TypeScript / React 或 Angular）里反复试错后整理的实践笔记，关注的是怎么让 Contract First 跑起来，并尽量持续不退回老路，而不是介绍 OpenAPI 语法。
如果你只想看 JVM 团队怎么把 contract 做成可执行验证（Spring Cloud Contract、WireMock、CI Quality Gates），可以直接跳到《Java 项目怎么做 contract testing：一次 Spring Cloud Contract 实践》。本文聚焦在 spec、协作和治理这一层。
为什么坚持 Contract First？ Code First 在小项目里没什么问题：后端先写完接口，把 Swagger 文档丢出去，前端照着对接。问题出现在团队和系统变大之后：
文档总是滞后——后端改了实现却忘了同步 Swagger 注解，前端按旧文档调用，联调阶段才发现 前端只能等——接口没写完，前端只能压时间或自己 mock，等真接口出来再返工 跨团队沟通成本高——每加一个消费方（移动端、第三方、内部 BFF），就要重新解释一遍接口 breaking change 靠口头同步——后端&amp;quot;顺手&amp;quot;改了字段类型，下游调用才发现问题 Contract First 的核心价值，是让 API 契约成为单一事实来源（single source of truth）。spec 不是事后的文档，而是开发的起点：所有人从同一份 YAML 出发，前后端可以并行，breaking change 最好显式审批。我倾向把它理解成一种&amp;quot;用工程约束代替口头沟通&amp;quot;的解耦机制，对微服务、电商、支付这种跨团队跨系统的场景尤其有价值。</description>
    </item>
    
    <item>
      <title>REST API 版本管理：四种常见策略、Spring Boot 4 原生支持与一些陷阱</title>
      <link>/posts/api-versioning-strategies/</link>
      <pubDate>Sun, 26 Apr 2026 12:45:14 +0800</pubDate>
      
      <guid>/posts/api-versioning-strategies/</guid>
      <description>API 版本管理是微服务架构中一个看似简单、实则充满细节的话题。客户端很多，升级节奏也各不相同，一个&amp;quot;破坏性变更&amp;quot;稍有不慎就可能让线上支付或推送流程出问题。本文尝试梳理四种主流策略，并逐一对比 Spring Boot 4 原生支持与历史实现方案，最后总结生产环境中常见的问题。
为什么需要版本管理 REST API 一旦对外发布，就变成了一份&amp;quot;隐式合同&amp;quot;。只要还有一个客户端在运行，你就不能随意更改字段含义、删除字段或修改响应结构。版本管理的本质，是为破坏性变更（Breaking Change）提供一条可控的演进通道，让新旧客户端能在同一套基础设施上共存。
什么算 Breaking Change？
删除或重命名字段 修改字段类型（如 amount: int → amount: BigDecimal） 修改 HTTP 状态码语义 业务流程从同步改为异步 认证机制变更（如从 API Key 改为 OAuth2） 非破坏性变更（如新增可选字段、新增接口）通常不需要升版本。
四种主流策略 1. URL 路径版本化 版本号嵌入 URL 路径，是目前很常见的方案，Stripe、GitHub、PayPal 等公开 API 也都能看到这种风格。
GET /api/v1/payments GET /api/v2/payments 优点： 直观、易调试、网关路由配置简单（前缀匹配）、Swagger 文档可以生成完全隔离的两套页面。
缺点： 粒度较粗。90% 的接口没有变化，但客户端却需要将所有调用路径从 /v1/ 改为 /v2/。
关于 /api/v1/payments 与 /api/payments/v1 的选择：前者将版本视为整个 API 服务的快照，网关路由更友好；后者将版本视为某个资源的属性，粒度更细但运维复杂度更高。在我接触到的大多数团队里，前者更常见。
2. 查询参数版本化 版本号以 Query Parameter 的形式传递：
GET /api/payments?version=1 GET /api/payments?</description>
    </item>
    
    <item>
      <title>从 OpenAPI 3.0 到 3.1：一次升级验证记录</title>
      <link>/posts/openapi-31-upgrade/</link>
      <pubDate>Fri, 10 Apr 2026 14:00:00 +0800</pubDate>
      
      <guid>/posts/openapi-31-upgrade/</guid>
      <description>📦 本文基于的完整项目源码：https://github.com/meirongdev/shop
🏷️ 当前文章对应的代码版本：openapi_3_1_upgrade
背景 我们的电商平台自启动以来，一直使用 OpenAPI 3.0.x 作为 API 文档规范。近期在整理 SpringDoc 2.8.9 和 JSON Schema 2020-12 工具链时，我顺手验证了一次 OpenAPI 3.1 升级的可行性，最后决定先在项目里试着切过去。
就这次实践看，升级过程主要是一行配置，没有涉及 Java 代码改动。下面更像是一份升级笔记：记录我为什么做这件事、哪些收益比较直接，以及哪些兼容性边界要先确认。
OpenAPI 3.1 的核心变化 OpenAPI 3.1 于 2021 年底发布（官方发布公告），虽然看起来只是小版本号 +1，但它底层做了一个根本性的改变：全面对齐 JSON Schema Draft 2020-12（JSON Schema 2020-12 规范）。
这不只是&amp;quot;换了一个标准&amp;quot;，更像是把 OpenAPI Schema 往 JSON Schema 工具链上靠近了一步。
变化一：nullable 语义重构 OpenAPI 3.0 的写法：
{ &amp;#34;type&amp;#34;: &amp;#34;string&amp;#34;, &amp;#34;nullable&amp;#34;: true } 这是一个 OpenAPI 自定义扩展字段。JSON Schema 标准中不存在 nullable，这意味着：
标准 JSON Schema 校验器不认识它 代码生成器需要专门处理 OpenAPI 特有的逻辑 与 JSON Schema 生态工具链不互通 OpenAPI 3.</description>
    </item>
    
  </channel>
</rss>
