You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用OpenAPI Spring代码生成器实现自定义请求头驱动的接口版本路由

解决方案:基于x-api-version请求头的路由实现(OpenAPI Spring生成器)

方法一:利用OpenAPI Spring扩展x-spring-headers

OpenAPI Spring代码生成器支持Spring专属扩展字段,直接在OpenAPI规范的操作节点中添加x-spring-headers,就能让生成的@RequestMapping自动包含headers属性,和原生Spring代码逻辑完全一致。

修改你的OpenAPI YAML中/places的GET操作:

/places:
  get:
    summary: Returns all places.
    operationId: getPlacesV2
    # 添加Spring扩展,指定路由匹配的请求头条件
    x-spring-headers:
      - X-API-VERSION=2
    parameters:
      # 保留原有所有参数,包括x-API-VERSION
      - name: x-API-VERSION
        in: header
        description: Is used for versioning
        required: true
        style: simple
        explode: false
        schema:
          type: integer
          format: int32
      # 其他参数...

生成后的控制器接口会自动生成带headers属性的@RequestMapping:

@RequestMapping(
    method = RequestMethod.GET,
    value = "/places",
    produces = {"application/json"},
    headers = {"X-API-VERSION=2"}
)
ResponseEntity<PlaceResponseV2> getPlacesV2(
    @RequestHeader(value = "Requestor", required = true) String requestor,
    @RequestHeader(value = "x-API-VERSION", required = true) Integer xAPIVERSION,
    // 其他参数...
);

这样Spring就能通过请求头区分不同版本的控制器,解决Bean映射冲突,同时在进入控制器前完成路由切换。

方法二:自定义OpenAPI生成器模板

如果需要批量处理所有版本路由,可修改生成器的Mustache模板,自动将指定请求头转换为@RequestMapping的headers条件:

  1. 复制OpenAPI Spring生成器的默认api.mustache模板到项目的src/main/resources/templates目录
  2. 找到模板中@RequestMapping的定义部分,添加逻辑判断:如果操作包含x-API-VERSION参数,则自动添加headers属性
    示例修改片段:
    @RequestMapping(
        method = {{{httpMethod}}},
        value = {{{path}}},
        {{#produces}}produces = {{{produces}}},{{/produces}}
        {{#consumes}}consumes = {{{consumes}}},{{/consumes}}
        {{#x-spring-headers}}headers = {{{x-spring-headers}}},{{/x-spring-headers}}
        // 新增逻辑:自动识别x-API-VERSION参数并生成headers条件
        {{#parameters}}
            {{#isHeader}}
                {{#name}}{{#startsWith this "x-API-VERSION"}}
                    headers = {"X-API-VERSION={{schema.default}}"},
                {{/startsWith}}{{/name}}
            {{/isHeader}}
        {{/parameters}}
    )
    
  3. 在build.gradle中配置模板路径:
    configOptions = [
            interfaceOnly: "true",
            dateLibrary: "java8",
            templateDirectory: "$rootDir/src/main/resources/templates"
    ]
    

方法三:Spring层面自定义路由规则

如果不想修改OpenAPI规范,可通过Spring的RequestMappingHandlerMapping自定义请求匹配逻辑:

  1. 创建API版本匹配条件类:

    public class ApiVersionCondition implements RequestCondition<ApiVersionCondition> {
        private final int version;
    
        public ApiVersionCondition(int version) {
            this.version = version;
        }
    
        @Override
        public ApiVersionCondition combine(ApiVersionCondition other) {
            return new ApiVersionCondition(other.version);
        }
    
        @Override
        public ApiVersionCondition getMatchingCondition(HttpServletRequest request) {
            String versionHeader = request.getHeader("X-API-VERSION");
            if (versionHeader != null && Integer.parseInt(versionHeader) == this.version) {
                return this;
            }
            return null;
        }
    
        @Override
        public int compareTo(ApiVersionCondition other, HttpServletRequest request) {
            return other.version - this.version;
        }
    }
    
  2. 创建自定义注解标记控制器版本:

    @Target({ElementType.TYPE})
    @Retention(RetentionPolicy.RUNTIME)
    public @interface ApiVersion {
        int value();
    }
    
  3. 自定义RequestMappingHandlerMapping,注入版本匹配条件:

    @Configuration
    public class ApiVersionConfig extends WebMvcConfigurationSupport {
        @Override
        protected RequestMappingHandlerMapping createRequestMappingHandlerMapping() {
            return new RequestMappingHandlerMapping() {
                @Override
                protected RequestCondition<?> getCustomTypeCondition(Class<?> handlerType) {
                    ApiVersion apiVersion = AnnotationUtils.findAnnotation(handlerType, ApiVersion.class);
                    return apiVersion != null ? new ApiVersionCondition(apiVersion.value()) : super.getCustomTypeCondition(handlerType);
                }
            };
        }
    }
    
  4. 在生成的控制器实现类上添加@ApiVersion注解:

    @ApiVersion(2)
    @RestController
    public class PlacesControllerV2 implements PlacesApiV2 {
        // 实现方法...
    }
    

这样即使生成的代码没有headers属性,Spring也会通过自定义条件匹配请求头,完成路由切换。


内容的提问来源于stack exchange,提问作者Patrick

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.16 13:07:45