Spring Cloud Gateway MVC路径重写及路由调用URL排查问题
Spring Cloud Gateway MVC路由404问题排查与解决
问题场景
使用Spring Boot搭配Spring Cloud Gateway MVC,现有两台服务器:
- 服务器1:
localhost:8082,上下文路径为/crm - 服务器2:
localhost:8001,上下文路径为/acme/crm
需求是:当调用服务器1的localhost:8082/crm/bff/book/1时,转发至服务器2的localhost:8001/acme/crm/book/1。但以下路由配置出现404错误:
@Bean public RouterFunction<ServerResponse> inventoryServiceRoute() { return route("crm_bff") .route(RequestPredicates.path("/bff/**"), http("http://localhost:8001/acme/crm")) .before(rewritePath("/(?<segment>.*)", "/${segment}")) .build(); }
404问题原因
- 路径匹配规则不准确:服务器1的上下文路径是
/crm,实际请求路径为/crm/bff/**,但原配置用RequestPredicates.path("/bff/**")匹配,无法命中正确的请求。 - 路径重写逻辑错误:原重写规则
/(?<segment>.*)没有处理请求路径中的/crm/bff前缀,导致转发后的路径不符合服务器2的接口要求。
修正后的路由配置
调整路径重写规则,并优化路径匹配(可选但更精准),修正后的代码如下:
@Bean public RouterFunction<ServerResponse> inventoryServiceRoute() { return route("crm_bff") // 匹配包含服务器1上下文路径的完整请求路径 .route(RequestPredicates.path("/crm/bff/**"), http("http://localhost:8001")) // 将/crm/bff/xxx重写为/acme/crm/xxx,匹配服务器2的上下文路径+目标接口 .before(rewritePath("/crm/bff/(?<segment>.*)", "/acme/crm/${segment}")) .build(); }
注:也可以保持原路径匹配
/bff/**,但需要确保网关的上下文路径配置正确,不过显式匹配/crm/bff/**更不容易出错。
查看网关实际转发URL的方法
方法1:开启调试日志
在配置文件中添加日志级别配置,打印网关转发的详细信息:
logging: level: org.springframework.cloud.gateway: DEBUG org.springframework.web.reactive.function.client: DEBUG
启动服务后,日志中会输出转发的目标URL、请求参数、响应状态等细节。
方法2:添加自定义前置过滤器
在路由配置中加入自定义逻辑,直接打印目标URL:
@Bean public RouterFunction<ServerResponse> inventoryServiceRoute() { return route("crm_bff") .route(RequestPredicates.path("/crm/bff/**"), http("http://localhost:8001")) .before(exchange -> { // 获取网关转发的目标URI URI targetUri = exchange.getAttribute(ServerWebExchangeUtils.GATEWAY_REQUEST_URL_ATTR); System.out.println("网关实际转发URL: " + targetUri); return Mono.empty(); }) .before(rewritePath("/crm/bff/(?<segment>.*)", "/acme/crm/${segment}")) .build(); }
每次请求转发时,控制台会直接输出实际调用的URL。
内容的提问来源于stack exchange,提问作者robert trudel
相关产品推荐
相关产品推荐

