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

如何在Spring Cloud Gateway中统一去除所有路由的断言路径前缀?

Spring Cloud Gateway 全局自动去除路由前缀方案

Spring Cloud Gateway 4.x 没有原生提供类似 Zuul 1.x 中自动去除路由前缀的全局配置,但可以通过自定义全局过滤器实现相同效果,自动适配不同路由的前缀段数。

自定义全局过滤器实现自动StripPrefix

这个过滤器会自动识别当前路由的Path断言模式,计算需要去除的前缀段数,无需在每个路由中单独配置StripPrefix过滤器。

实现代码

import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.cloud.gateway.route.Route;
import org.springframework.cloud.gateway.route.builder.PathRoutePredicateFactory;
import org.springframework.core.Ordered;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;
import java.util.Optional;

@Component
public class AutoStripPrefixGlobalFilter implements GlobalFilter, Ordered {

    private static final String GATEWAY_ROUTE_ATTR = "org.springframework.cloud.gateway.support.ServerWebExchangeUtils.gatewayRoute";

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        Route currentRoute = exchange.getAttribute(GATEWAY_ROUTE_ATTR);
        if (currentRoute == null) {
            return chain.filter(exchange);
        }

        // 提取路由的Path断言规则
        Optional<PathRoutePredicateFactory.PathSpec> pathSpec = currentRoute.getPredicate()
                .getArgs().values().stream()
                .filter(arg -> arg instanceof PathRoutePredicateFactory.PathSpec)
                .map(arg -> (PathRoutePredicateFactory.PathSpec) arg)
                .findFirst();

        if (pathSpec.isPresent()) {
            String pattern = pathSpec.get().getPattern();
            // 移除断言末尾的/**,计算前缀段数
            String prefix = pattern.replace("/**", "");
            int segmentCount = prefix.isEmpty() ? 0 : prefix.split("/").length - 1;

            if (segmentCount > 0) {
                String originalPath = exchange.getRequest().getPath().value();
                String[] pathSegments = originalPath.split("/");
                
                // 拼接去除前缀后的新路径
                StringBuilder newPath = new StringBuilder();
                for (int i = segmentCount + 1; i < pathSegments.length; i++) {
                    newPath.append("/").append(pathSegments[i]);
                }
                if (newPath.length() == 0) {
                    newPath.append("/");
                }

                // 修改请求路径
                exchange.getRequest().mutate().path(newPath.toString()).build();
                return chain.filter(exchange.mutate().request(exchange.getRequest()).build());
            }
        }
        return chain.filter(exchange);
    }

    @Override
    public int getOrder() {
        // 设置优先级,确保在其他路径处理过滤器前执行
        return -1;
    }
}

工作原理

  1. 从请求上下文获取当前匹配的路由信息
  2. 解析路由的Path断言(比如/api/example/**),移除末尾的/**后计算前缀的路径段数(这里是2段)
  3. 截取原始请求路径,去除对应段数的前缀,生成新的请求路径
  4. 修改请求上下文的路径后,继续执行过滤器链

替代方案:路由配置层面统一处理(无需代码)

如果不想编写自定义过滤器,可以在每条路由中使用RewritePath过滤器,通过变量统一配置:

spring:
  cloud:
    gateway:
      routes:
        - id: example_route
          uri: https://samplehost.com:12345
          predicates:
            - Path=/api/example/**
          filters:
            - RewritePath=/api/example/(?<remaining>.*), /${remaining}
        - id: another_route
          uri: https://anotherhost.com
          predicates:
            - Path=/example/**
          filters:
            - RewritePath=/example/(?<remaining>.*), /${remaining}

但这种方式需要为30多条路由逐一配置,适合路由数量较少的场景。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.24 01:26:16