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

Springboot中多个Rest控制器能否使用相同request mapping?如何按RequestHeader匹配?

在Spring Boot中配置多个同RequestMapping的REST控制器并按RequestHeader路由

当然可以实现。Spring Boot支持多个控制器使用相同的@RequestMapping路径,核心是通过请求头(RequestHeader)的匹配规则来让Spring正确路由到对应的控制器,下面是两种常用的实现方案:


方式一:直接利用@RequestMapping的headers属性(简单场景)

这是最直接的实现方式,在@RequestMapping(或@GetMapping/@PostMapping等派生注解)中通过headers参数指定匹配条件,Spring会自动根据请求头判断调用哪个控制器方法。

示例代码:

// 匹配请求头包含X-Version=v1的请求
@RestController
@RequestMapping("/api/user")
public class UserV1Controller {
    @GetMapping(headers = "X-Version=v1")
    public String getUserInfo() {
        return "用户信息来自V1版本接口";
    }
}

// 匹配请求头包含X-Version=v2的请求
@RestController
@RequestMapping("/api/user")
public class UserV2Controller {
    @GetMapping(headers = "X-Version=v2")
    public String getUserInfo() {
        return "用户信息来自V2版本接口";
    }
}

// 作为默认匹配(当请求头不匹配上述两个控制器时触发)
@RestController
@RequestMapping("/api/user")
public class UserDefaultController {
    @GetMapping
    public String getUserInfo() {
        return "用户信息来自默认版本接口";
    }
}

说明:headers参数支持多种写法,比如headers = "X-Version!=v1"(排除指定值)、headers = "X-Version"(只要存在该请求头即可),可以根据需求灵活调整。


方式二:自定义请求匹配逻辑(复杂场景)

如果需要更灵活的匹配规则(比如正则匹配请求头值、多请求头组合判断),可以通过自定义RequestMappingHandlerMapping和RequestCondition来实现。

步骤1:创建自定义注解标记版本

@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface ApiVersion {
    // 指定用来匹配的请求头名称,默认X-Version
    String header() default "X-Version";
    // 指定请求头需要匹配的值
    String value();
}

步骤2:实现自定义请求匹配条件

public class HeaderVersionCondition implements RequestCondition<HeaderVersionCondition> {
    private final String versionHeader;
    private final String versionValue;

    public HeaderVersionCondition(String versionHeader, String versionValue) {
        this.versionHeader = versionHeader;
        this.versionValue = versionValue;
    }

    @Override
    public HeaderVersionCondition combine(HeaderVersionCondition other) {
        // 方法上的注解优先级高于类上的
        return new HeaderVersionCondition(other.versionHeader, other.versionValue);
    }

    @Override
    public HeaderVersionCondition getMatchingCondition(HttpServletRequest request) {
        String requestVersion = request.getHeader(versionHeader);
        // 匹配成功则返回当前条件,否则返回null表示不匹配
        return versionValue.equals(requestVersion) ? this : null;
    }

    @Override
    public int compareTo(HeaderVersionCondition other, HttpServletRequest request) {
        // 精确匹配的优先级更高
        return versionValue.equals(request.getHeader(versionHeader)) ? 1 : -1;
    }
}

步骤3:自定义RequestMappingHandlerMapping

@Component
public class VersionRequestMappingHandlerMapping extends RequestMappingHandlerMapping {
    @Override
    protected RequestCondition<?> getCustomTypeCondition(Class<?> handlerType) {
        // 解析类上的@ApiVersion注解
        ApiVersion apiVersion = AnnotationUtils.findAnnotation(handlerType, ApiVersion.class);
        return apiVersion != null ? new HeaderVersionCondition(apiVersion.header(), apiVersion.value()) : null;
    }

    @Override
    protected RequestCondition<?> getCustomMethodCondition(Method method) {
        // 解析方法上的@ApiVersion注解
        ApiVersion apiVersion = AnnotationUtils.findAnnotation(method, ApiVersion.class);
        return apiVersion != null ? new HeaderVersionCondition(apiVersion.header(), apiVersion.value()) : null;
    }
}

步骤4:在控制器上使用自定义注解

@RestController
@RequestMapping("/api/user")
@ApiVersion(value = "v1")
public class UserV1Controller {
    @GetMapping
    public String getUserInfo() {
        return "用户信息来自V1版本接口";
    }
}

@RestController
@RequestMapping("/api/user")
@ApiVersion(value = "v2")
public class UserV2Controller {
    @GetMapping
    public String getUserInfo() {
        return "用户信息来自V2版本接口";
    }
}

注意事项

  • 确保多个控制器的匹配条件互斥,否则Spring会抛出AmbiguousHandlerException(请求匹配歧义)。
  • 方法级别的注解匹配优先级高于类级别的注解。
  • 可以结合produces、consumes等属性进一步细化匹配规则。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.30 16:00:32