告别第三方库!Spring Boot 4 原生 API 版本控制全解析:4 种策略 + 实战案例

本文深入解析 Spring Boot 4.1.0 原生 API 版本控制机制,涵盖 4 种主流版本策略、客户端全链路支持、版本弃用管理,以及从 v1 到 v3 的平滑演进实战。


🎯 痛点场景:API 演进的"劫"

做后端的同学都经历过这种痛苦:

  • 😫 产品经理:「这个 API 需要改一下,加个字段」
  • 😨 :「改了旧客户端会不会崩?」
  • 🤯 结果:要么硬着头皮改(出问题),要么维护两套接口(代码臃肿)

于是你可能引入 spring-api-versioningSpringDoc 等第三方库来解决版本控制问题。

好消息:Spring Boot 4 原生支持 API 版本控制了! 🎉

零第三方依赖、深度集成、支持 4 种版本策略,告别"版本控制焦虑"。


📚 一、四种 API 版本控制策略对比

在深入 Spring Boot 4 的实现之前,我们先来了解业界主流的版本控制方式:

1️⃣ Header 方式

通过 HTTP 请求头传递版本号:

http 复制代码
GET /api/users HTTP/1.1
Host: example.com
X-API-Version: 2.0

优点 :URL 干净,不影响资源路径

缺点:客户端必须正确设置请求头

2️⃣ Query Parameter 方式

通过 URL 查询参数传递:

http 复制代码
GET /api/users?version=2.0 HTTP/1.1

优点 :简单直观,Postman/curl 调试方便

缺点:URL 不够优雅

3️⃣ Path Segment 方式

版本号嵌入 URL 路径:

http 复制代码
GET /api/v2/users HTTP/1.1

优点 :版本一目了然,符合 RESTful 风格

缺点:需要在 URL 中维护版本号

4️⃣ Media Type 方式

通过 Accept 头的媒体类型参数传递:

http 复制代码
GET /api/users HTTP/1.1
Accept: application/vnd.example.api+json;version=2.0

优点 :最 RESTful,支持内容协商

缺点:实现复杂度最高

📊 策略选择决策树

css 复制代码
                    ┌─────────────────────┐
                    │ 需要版本控制吗?    │
                    └──────────┬──────────┘
                               │ Yes
                    ┌──────────▼──────────┐
                    │ 主要是内部系统?    │
                    └──────────┬──────────┘
                               │
                    ┌──────────▼──────────┐
                    │ 是                  │ 否
                    ▼                     ▼
            ┌─────────────┐      ┌─────────────────────┐
            │ Header 方式 │      │ 公开 API?          │
            │ 干净 URL    │      └──────────┬──────────┘
            └─────────────┘                 │
                               ┌─────────────┼─────────────┐
                               ▼             ▼             ▼
                        ┌──────────┐  ┌────────────┐  ┌──────────────┐
                        │ 调试方便 │  │ RESTful    │  │ 需要内容协商 │
                        │ Query    │  │ Path       │  │ Media Type  │
                        └──────────┘  └────────────┘  └──────────────┘

🏗️ 二、Spring Boot 4 核心架构解析

2.1 核心接口体系

Spring Framework 7 定义了清晰的 API 版本控制接口体系:

接口 职责 使用场景
ApiVersionStrategy 版本策略核心契约 协调解析、验证、弃用提示
ApiVersionResolver 版本解析器 从请求中提取版本号
ApiVersionParser 版本解析器 将字符串解析为版本对象
ApiVersionDeprecationHandler 弃用处理器 处理版本弃用逻辑
DefaultApiVersionStrategy 默认实现 Spring Boot 自动配置

2.2 @RequestMapping 新增 version 属性

这是最核心的变化!在 @RequestMapping 及其变体注解中新增了 version 属性:

java 复制代码
@RestController
@RequestMapping("/api/products")
public class ProductController {

    // 版本 1 的实现
    @GetMapping(version = "1")
    public List<ProductV1> getProductsV1() {
        return productService.getProductsV1();
    }

    // 版本 2 的实现
    @GetMapping(version = "2")
    public List<ProductV2> getProductsV2() {
        return productService.getProductsV2();
    }
}

效果

  • 相同的 URL 路径 /api/products
  • 根据请求的版本号自动路由到对应方法
  • 代码零冗余,清晰易维护

2.3 ApiVersionConfigurer 配置器

实现 WebMvcConfigurer 接口来自定义版本策略:

java 复制代码
@Configuration
public class VersionConfig implements WebMvcConfigurer {

    @Override
    public void configureApiVersioning(ApiVersionConfigurer configurer) {
        // 1. 设置默认版本(请求未指定版本时使用)
        configurer.setDefaultVersion("1.0");
        
        // 2. 声明支持的版本列表
        configurer.addSupportedVersions("1.0", "2.0", "3.0");
        
        // 3. 配置版本解析策略(按优先级顺序)
        configurer.useRequestHeader("X-API-Version");  // 优先从 Header 获取
        configurer.useQueryParam("version");           // 其次从查询参数获取
        
        // 4. 开启自动检测(从控制器注解中识别支持的版本)
        configurer.detectSupportedVersions(true);
    }
}

⚙️ 三、Spring Boot 自动配置全解

3.1 配置属性一览

Spring Boot 4.1.0 通过 spring.mvc.apiversion.* 前缀提供完整配置:

yaml 复制代码
spring:
  mvc:
    apiversion:
      # ===== 基础配置 =====
      required: false           # 是否强制要求版本(默认 false)
      default: "1.0"            # 默认版本号
      supported:                # 明确支持的版本列表
        - "1.0"
        - "1.1"
        - "2.0"
      detect-supported: true    # 是否自动检测控制器中的版本声明
      
      # ===== 版本解析策略(4 选 1 或组合)=====
      use:
        header: "X-API-Version"              # 方式 1:请求头
        query-parameter: "version"            # 方式 2:查询参数
        path-segment: 1                       # 方式 3:路径段索引
        media-type-parameter:                 # 方式 4:媒体类型参数
          application/json: "version"

3.2 配置项详细说明

配置项 类型 默认值 说明
spring.mvc.apiversion.required boolean false 是否强制要求版本
spring.mvc.apiversion.default String null 默认版本号
spring.mvc.apiversion.supported List<String> null 支持的版本列表
spring.mvc.apiversion.detect-supported boolean true 自动检测版本
spring.mvc.apiversion.use.header String null 请求头名称
spring.mvc.apiversion.use.query-parameter String null 查询参数名
spring.mvc.apiversion.use.path-segment Integer null 路径段索引

3.3 源码解析:自动配置工作流

来看 Spring Boot 是如何将配置属性转换为版本策略的:

java 复制代码
// 源码位置: WebMvcAutoConfiguration.java 第407-426行

@Override
public void configureApiVersioning(ApiVersionConfigurer configurer) {
    PropertyMapper map = PropertyMapper.get();
    Apiversion properties = this.mvcProperties.getApiversion();
    
    // 步骤 1:映射基础配置
    map.from(properties::getRequired).to(configurer::setVersionRequired);
    map.from(properties::getDefaultVersion).to(configurer::setDefaultVersion);
    map.from(properties::getSupported)
        .to((supported) -> supported.forEach(configurer::addSupportedVersions));
    map.from(properties::getDetectSupported)
        .to(configurer::detectSupportedVersions);
    
    // 步骤 2:配置版本解析策略
    configureApiVersioningUse(configurer, properties.getUse());
    
    // 步骤 3:注入自定义扩展点
    this.apiVersionResolvers.orderedStream()
        .forEach(configurer::useVersionResolver);
    this.apiVersionParser.ifAvailable(configurer::setVersionParser);
    this.apiVersionDeprecationHandler.ifAvailable(configurer::setDeprecationHandler);
}

// 策略配置的具体实现
private void configureApiVersioningUse(ApiVersionConfigurer configurer, Use use) {
    PropertyMapper map = PropertyMapper.get();
    map.from(use::getHeader).whenHasText().to(configurer::useRequestHeader);
    map.from(use::getQueryParameter).whenHasText().to(configurer::useQueryParam);
    use.getMediaTypeParameter().forEach(configurer::useMediaTypeParameter);
    map.from(use::getPathSegment).to(configurer::usePathSegment);
}

工作流程

  1. 读取 WebMvcProperties.Apiversion 配置
  2. 映射基础属性(required、default、supported 等)
  3. 根据 use 配置创建版本解析器(Header/Query/Path/MediaType)
  4. 注入用户自定义的扩展组件

🚀 四、四种策略实战代码

实战 1:Header 方式

场景:内部系统 API,需要干净的 URL

配置

yaml 复制代码
spring:
  mvc:
    apiversion:
      default: "1"
      use:
        header: "X-API-Version"

控制器

java 复制代码
@RestController
@RequestMapping("/api/users")
public class UserController {

    @GetMapping(version = "1")
    public List<UserV1> getUsersV1() {
        return List.of(new UserV1(1L, "张三"));
    }

    @GetMapping(version = "2")
    public List<UserV2> getUsersV2() {
        return List.of(new UserV2(1L, "张三", "zhangsan@example.com"));
    }
}

调用测试

bash 复制代码
# 调用 v1
curl -H "X-API-Version: 1" http://localhost:8080/api/users

# 调用 v2
curl -H "X-API-Version: 2" http://localhost:8080/api/users

# 不指定版本(使用默认版本 v1)
curl http://localhost:8080/api/users

实战 2:Query Parameter 方式

场景:公开 API,调试友好

配置

yaml 复制代码
spring:
  mvc:
    apiversion:
      default: "1"
      use:
        query-parameter: "v"

调用测试

bash 复制代码
# 调用 v1
curl http://localhost:8080/api/users?v=1

# 调用 v2
curl http://localhost:8080/api/users?v=2

实战 3:Path Segment 方式

场景:RESTful 风格,版本号可见

配置

yaml 复制代码
spring:
  mvc:
    apiversion:
      default: "1"
      use:
        path-segment: 1  # URL 的第 1 段为版本号

控制器

java 复制代码
@RestController
public class UserController {

    @GetMapping("/api/{version}/users")
    public List<User> getUsers() {
        // 版本信息自动从路径解析
        return userService.getUsers();
    }
}

调用测试

bash 复制代码
# 调用 v1
curl http://localhost:8080/api/v1/users

# 调用 v2
curl http://localhost:8080/api/v2/users

实战 4:Media Type 方式

场景:需要内容协商的超媒体 API

配置

yaml 复制代码
spring:
  mvc:
    apiversion:
      default: "1"
      use:
        media-type-parameter:
          application/json: "version"

调用测试

bash 复制代码
# 调用 v1
curl -H "Accept: application/json;version=1" http://localhost:8080/api/users

# 调用 v2
curl -H "Accept: application/json;version=2" http://localhost:8080/api/users

🔄 五、版本弃用与平滑演进

5.1 标记版本弃用

当 v1 需要废弃时,使用 @Deprecated 注解标记:

java 复制代码
@RestController
@RequestMapping("/api/orders")
public class OrderController {

    @Deprecated  // 标记为弃用
    @GetMapping(version = "1")
    public OrderV1 getOrderV1() {
        return orderService.getOrderV1();
    }

    @GetMapping(version = "2")
    public OrderV2 getOrderV2() {
        return orderService.getOrderV2();
    }

    @GetMapping(version = "3")  // 最新版本
    public OrderV3 getOrderV3() {
        return orderService.getOrderV3();
    }
}

5.2 配置弃用处理器

Spring 内置了 StandardApiVersionDeprecationHandler,可以自动设置 RFC 9745 和 RFC 8594 标准弃用响应头(DeprecationSunsetLink)。

使用内置实现(推荐)

java 复制代码
import org.springframework.web.accept.StandardApiVersionDeprecationHandler;

@Configuration
public class WebConfig implements WebMvcConfigurer {

    @Override
    public void configureApiVersioning(ApiVersionConfigurer configurer) {
        configurer.useRequestHeader("X-API-Version");
        // 使用 Spring 内置的标准弃用处理器
        // 会自动添加 Deprecation、Sunset、Link 头
    }
    
    @Bean
    public ApiVersionDeprecationHandler apiVersionDeprecationHandler(
            ApiVersionParser<?> parser) {
        return new StandardApiVersionDeprecationHandler(parser);
    }
}

注意 :WebFlux 用户应使用 org.springframework.web.reactive.accept.StandardApiVersionDeprecationHandler

自定义弃用处理器(高级用法)

如果需要更灵活的控制(如添加日志、发送告警),可以实现 ApiVersionDeprecationHandler 接口。

WebMvc 版本:org.springframework.web.accept.ApiVersionDeprecationHandler WebFlux 版本:org.springframework.web.reactive.accept.ApiVersionDeprecationHandler

java 复制代码
// WebMvc (Servlet) 示例
import org.springframework.web.accept.ApiVersionDeprecationHandler;
import jakarta.servlet.http.HttpServletResponse;

@Component
public class LoggingDeprecationHandler implements ApiVersionDeprecationHandler {

    private static final Logger log = LoggerFactory.getLogger(LoggingDeprecationHandler.class);

    @Override
    public void handleDeprecation(org.springframework.web.accept.ApiVersion version, 
                                  HttpServletResponse response) {
        // 添加标准弃用头(也可以同时使用 StandardApiVersionDeprecationHandler)
        response.setHeader("Deprecation", "true");
        response.setHeader("Sunset", "2026-06-30");
        response.setHeader("Link", 
            "<https://api.example.com/api/v2/orders>; rel=\"success-version\"");
        
        // 记录告警日志
        log.warn("API version is deprecated, please upgrade to latest version");
    }
}

提示 :建议优先使用 StandardApiVersionDeprecationHandler,它已实现 RFC 标准弃用头的自动设置。自定义处理器适用于需要特殊逻辑的场景。

5.3 版本演进路线图

yaml 复制代码
📅 时间线规划:

2025 Q1          2025 Q3          2025 Q4
┌─────────┐     ┌─────────┐     ┌─────────┐
│  v1.0   │────►│  v2.0   │────►│  v3.0   │
│  新功能  │     │  重构API │     │  完整重写 │
└─────────┘     └─────────┘     └─────────┘
    │               │               │
    ▼               ▼               ▼
 正常使用        v1 标记弃用     v1 正式下线
 无警告         添加 Sunset 头   仅支持 v2/v3

演进建议

  1. 弃用期:至少 6 个月,让客户端有足够时间升级
  2. 双版本并行:新旧版本同时可用,确保平滑过渡
  3. 弃用响应头 :添加 DeprecationSunset 标准头

🔌 六、客户端全链路版本控制

Spring Boot 4 不仅支持服务端版本控制,还支持客户端自动插入版本信息。

6.1 HTTP Service Client 配置

Spring Boot 4 统一使用 spring.http.serviceclient.<group-name> 配置 HTTP 服务客户端,支持 RestClient 和 WebClient 两种后端。

配置文件

yaml 复制代码
spring:
  http:
    serviceclient:
      order-service:
        base-url: https://api.example.com
        apiversion:
          default: "2.0"
          insert:
            header: "X-API-Version"

使用代码

首先定义 HTTP Service 接口:

java 复制代码
@HttpExchange(url = "/orders")
public interface OrderServiceClient {

    @GetExchange
    List<Order> getOrders();
}

然后在主应用类中导入:

java 复制代码
@SpringBootApplication
@ImportHttpServices(types = OrderServiceClient.class, group = "order-service")
public class MyApplication {
    public static void main(String[] args) {
        SpringApplication.run(MyApplication.class, args);
    }
}

调用代码

java 复制代码
@Service
public class OrderService {

    private final OrderServiceClient orderServiceClient;

    public OrderService(OrderServiceClient orderServiceClient) {
        this.orderServiceClient = orderServiceClient;
    }

    public List<Order> getOrders() {
        // 版本号自动通过配置的 header 插入
        return orderServiceClient.getOrders();
    }
}

6.2 客户端版本插入策略配置

支持 4 种版本插入方式,与服务端版本解析策略对应:

yaml 复制代码
spring:
  http:
    serviceclient:
      api-service:
        base-url: https://api.example.com
        apiversion:
          default: "2.0"
          insert:
            # 方式 1:插入到请求头
            header: "X-API-Version"
            # 方式 2:插入到查询参数
            # query-parameter: "version"
            # 方式 3:插入到路径段
            # path-segment: 1
            # 方式 4:插入到媒体类型参数
            # media-type-parameter: "version"

6.3 版本插入器原理

PropertiesApiVersionInserter 实现了自动版本插入:

java 复制代码
// 源码位置: PropertiesApiVersionInserter.java

public final class PropertiesApiVersionInserter implements ApiVersionInserter {

    @Override
    public URI insertVersion(Object version, URI uri) {
        // 版本号插入到 URI(如查询参数)
        return this.delegate.insertVersion(version, uri);
    }

    @Override
    public void insertVersion(Object version, HttpHeaders headers) {
        // 版本号插入到请求头
        this.delegate.insertVersion(version, headers);
    }

    // 从配置属性创建插入器
    public static PropertiesApiVersionInserter get(ApiversionProperties.Insert properties) {
        Builder builder = builder(properties);
        return (builder != null) ? new PropertiesApiVersionInserter(builder.build()) : EMPTY;
    }
}

🎨 七、完整实战:订单 API 演进

7.1 场景描述

订单系统需要三次大的 API 变更:

  • v1:基础订单查询
  • v2:增加筛选和分页
  • v3:重构返回结构,增加扩展字段

7.2 数据模型

java 复制代码
// ============ V1 数据结构 ============
public record OrderV1(
    Long id,
    String customerName,
    BigDecimal total
) {}

// ============ V2 数据结构 ============
public record OrderV2(
    Long id,
    String customerName,
    BigDecimal total,
    OrderStatus status,
    LocalDateTime createdAt
) {}

// ============ V3 数据结构 ============
public record Customer(
    Long id,
    String name,
    String email
) {}

public record OrderV3(
    Long id,
    Customer customer,
    BigDecimal total,
    OrderStatus status,
    LocalDateTime createdAt,
    Map<String, Object> metadata  // 扩展字段
) {}

7.3 控制器实现

java 复制代码
@RestController
@RequestMapping("/api/orders")
public class OrderController {

    private final OrderService orderService;

    public OrderController(OrderService orderService) {
        this.orderService = orderService;
    }

    // ============ V1:基础实现(已弃用)============
    @Deprecated
    @GetMapping(version = "1")
    public List<OrderV1> getOrdersV1() {
        return orderService.getAllOrders().stream()
                .map(order -> new OrderV1(
                    order.getId(),
                    order.getCustomer().getName(),
                    order.getTotal()
                ))
                .toList();
    }

    // ============ V2:增加筛选和分页 ============
    @GetMapping(version = "2")
    public Page<OrderV2> getOrdersV2(
            @RequestParam(required = false) OrderStatus status,
            @RequestParam(defaultValue = "0") int page,
            @RequestParam(defaultValue = "20") int size) {
        
        return orderService.getOrders(status, PageRequest.of(page, size))
                .map(order -> new OrderV2(
                    order.getId(),
                    order.getCustomer().getName(),
                    order.getTotal(),
                    order.getStatus(),
                    order.getCreatedAt()
                ));
    }

    // ============ V3:完整重构 ============
    @GetMapping(version = "3")
    public Page<OrderV3> getOrdersV3(
            @RequestParam(required = false) OrderStatus status,
            @RequestParam(defaultValue = "0") int page,
            @RequestParam(defaultValue = "20") int size,
            @RequestParam(defaultValue = "false") boolean includeMetadata) {
        
        return orderService.getOrders(status, PageRequest.of(page, size))
                .map(order -> {
                    Map<String, Object> metadata = includeMetadata 
                        ? Map.of(
                            "source", "web",
                            "channel", "api",
                            "version", "3.0"
                        )
                        : Map.of();
                    
                    return new OrderV3(
                        order.getId(),
                        new Customer(
                            order.getCustomer().getId(),
                            order.getCustomer().getName(),
                            order.getCustomer().getEmail()
                        ),
                        order.getTotal(),
                        order.getStatus(),
                        order.getCreatedAt(),
                        metadata
                    );
                });
    }
}

7.4 配置文件

yaml 复制代码
# application.yml
spring:
  mvc:
    apiversion:
      # 默认使用最新版本
      default: "3"
      # 声明支持的版本
      supported:
        - "1"
        - "2"
        - "3"
      # 自动检测控制器中声明的版本
      detect-supported: true
      # 使用请求头传递版本号
      use:
        header: "X-API-Version"

7.5 调用测试

bash 复制代码
# ✅ 默认版本(v3,带元数据)
curl http://localhost:8080/api/orders

# ✅ 调用 v1(已弃用,会有告警)
curl -H "X-API-Version: 1" http://localhost:8080/api/orders

# ✅ 调用 v2(带筛选和分页)
curl -H "X-API-Version: 2" \
     "http://localhost:8080/api/orders?status=PAID&page=0&size=10"

# ✅ 调用 v3(完整功能)
curl -H "X-API-Version: 3" \
     "http://localhost:8080/api/orders?status=PAID&include-metadata=true"

# ❌ 不支持的版本(返回 400 错误)
curl -H "X-API-Version: 99" http://localhost:8080/api/orders
# 响应: {"error":"UNSUPPORTED_API_VERSION","message":"Invalid API version: 99"}

📊 八、方案对比与选型

8.1 vs 第三方库

对比项 Spring Boot 4 原生 spring-api-versioning
维护方 Spring 官方 社区
学习曲线 ⭐ 平缓 ⭐⭐⭐ 较陡
功能完整性 ⭐⭐⭐⭐⭐ ⭐⭐⭐⭐
自动配置 ✅ 支持 ❌ 手动配置
客户端支持 ✅ RestClient/WebClient ❌ 需额外配置
双栈支持 ✅ MVC + WebFlux ✅ MVC + WebFlux

8.2 vs 传统 URL 版本

对比项 传统 URL (/api/v1) Spring Boot 4 原生
URL 整洁性 ❌ 版本号在 URL 中 ✅ 干净的 URL
路由复杂度 ❌ 每个版本独立路由 ✅ 同一方法多版本映射
代码组织 ❌ 分散在不同类 ✅ 集中在同一方法
弃用处理 ❌ 手动实现 ✅ 原生支持 Sunset 头
测试复杂度 ❌ 测试多个 URL ✅ 测试同 URL + 不同 Header

8.3 选型建议

场景 推荐方案
新项目 Spring Boot 4 原生
升级 Spring Boot 3 升级到 4.0 使用原生
复杂版本策略 原生方案(支持自定义解析器)
快速原型 原生方案(零配置)

💡 九、最佳实践与避坑指南

✅ 正确做法

  1. 使用语义化版本

    MAJOR.MINOR.PATCH
    1.0.0 → 首个稳定版本
    1.1.0 → 向后兼容的新功能
    2.0.0 → 破坏性变更

  2. 声明支持的版本

yaml 复制代码
spring:
  mvc:
    apiversion:
      supported:
        - "1.0"
        - "1.1"
        - "2.0"
  1. 开启自动检测
yaml 复制代码
spring:
  mvc:
    apiversion:
      detect-supported: true  # 自动识别控制器中的版本声明
  1. 配置默认版本
yaml 复制代码
spring:
  mvc:
    apiversion:
      default: "2.0"  # 请求未指定版本时使用

❌ 常见陷阱

  1. 不要混用多种策略
java 复制代码
// ❌ 错误:不要同时配置多种策略
@Configuration
public class BadConfig implements WebMvcConfigurer {
    @Override
    public void configureApiVersioning(ApiVersionConfigurer configurer) {
        configurer.useRequestHeader("X-Version");
        configurer.useQueryParam("version");  // 可能冲突
    }
}
  1. 不要在 URL 中硬编码版本号
java 复制代码
// ❌ 错误:每个版本独立路由
@GetMapping("/api/v1/users")
public List<UserV1> getUsersV1() { ... }

@GetMapping("/api/v2/users")
public List<UserV2> getUsersV2() { ... }

// ✅ 正确:同一 URL,不同版本
@GetMapping(value = "/api/users", version = "1")
public List<UserV1> getUsersV1() { ... }

@GetMapping(value = "/api/users", version = "2")
public List<UserV2> getUsersV2() { ... }
  1. 及时标记弃用版本
java 复制代码
// ✅ 正确:标记弃用
@Deprecated
@GetMapping(version = "1")
public OrderV1 getOrderV1() { ... }

🎯 生产环境 Checklist

  • 配置默认版本号
  • 声明支持的版本列表
  • 开启自动版本检测
  • 选择一种版本解析策略(Header/Query/Path/MediaType)
  • 标记弃用版本
  • 添加 Sunset 响应头
  • 编写版本兼容性测试
  • 配置 API 版本变更告警

📝 十、总结与行动清单

核心优势回顾

特性 说明
🎯 零配置 只需 version 属性,Spring Boot 自动配置
🔄 多策略 支持 4 种主流版本传递方式
双栈支持 Spring MVC + WebFlux 同时支持
🔌 客户端支持 RestClient/WebClient 自动插入版本
🏷️ 弃用机制 原生支持 Sunset 头和弃用提示
🔧 可扩展 提供自定义解析器/解析器扩展点

迁移步骤清单

vbnet 复制代码
Step 1: 升级到 Spring Boot 4.0+
Step 2: 在 @RequestMapping 中添加 version 属性
Step 3: 配置 spring.mvc.apiversion.* 属性
Step 4: 标记旧版本为 @Deprecated
Step 5: 配置弃用处理器和 Sunset 头
Step 6: 编写版本兼容性测试
Step 7: 客户端(RestClient/WebClient)配置版本插入

一句话总结

Spring Boot 4 的原生 API 版本控制,让"版本无感知"开发成为现实,告别第三方库,拥抱原生支持! 🚀


相关推荐
神奇小汤圆1 小时前
把Spring Boot 4的Native Image玩明白了,启动3秒变50毫秒的踩坑全记录
后端
东方小月1 小时前
从零开发一个 Coding Agent(五):使用 TypeBox 校验工具参数
前端·人工智能·后端
Scene2161 小时前
Agent Harness、Loop 与 Graph:构建生产级 AI Agent 的三大架构支柱
后端
小小洋洋1 小时前
OpenWrt 从U盘迁移到内置 eMMC,并完成扩容与 Docker 安装
java·docker·eureka
SomeB1oody2 小时前
【RustyML入门】2.0. 经典机器学习
开发语言·后端·机器学习·rust·教程
就改了2 小时前
SpringBoot 自定义线程池 + 实时监控指标
java·spring boot·后端
暗黑小白2 小时前
脱敏引擎工程化
后端·ai agent
plainGeekDev2 小时前
运行时获取依赖 → 编译时注入
android·java·kotlin
用户8181870627462 小时前
第23章 JPA / Hibernate 异常
后端