Spring Cloud Config Server含斜杠路径时useDefaultLabel映射异常
问题描述
基于spring-cloud-config-server-4.0.0搭建配置服务,已配置spring.cloud.config.server.git.default-label指定默认分支:
- 无斜杠路径请求:
GET http://localhost:8888/myAppName/myProfiles/test.txt?useDefaultLabel可正常返回资源 - 带斜杠路径请求:
GET http://localhost:8888/myAppName/myProfiles/path/test.txt?useDefaultLabel抛出RefNotFoundException: Ref path cannot be resolved异常,栈指向org.springframework.cloud.config.server.resource.ResourceController.retrieve(ResourceController.java:107)
经排查,该请求被错误路由到@GetMapping("/{name}/{profile}/{label}/**")端点,而非预期的@GetMapping(value = "/{name}/{profile}/{path:.*}", params = "useDefaultLabel")端点,尝试编码斜杠、将useDefaultLabel设为"true"均无效。
问题分析
Spring MVC的路径匹配优先级规则导致:带**的通配符路径优先级高于正则匹配的{path:.*},即使后者带有params条件约束。当请求路径包含多段斜杠时,Spring MVC会优先匹配/{name}/{profile}/{label}/**,将path识别为label参数,进而触发分支查找逻辑,导致找不到名为path的分支,抛出异常。
解决方案
临时 workaround:调整请求路径格式
将请求路径中的label位置留空,保留useDefaultLabel参数,示例请求:
GET http://localhost:8888/myAppName/myProfiles//path/test.txt?useDefaultLabel
空的label位置不会被{label}占位符捕获(默认占位符不匹配空值),Spring MVC会转而匹配带useDefaultLabel参数的端点,触发默认分支逻辑。
永久修复:自定义控制器覆盖路由逻辑
创建自定义控制器,提升带useDefaultLabel参数的端点优先级,确保请求被正确路由:
import org.springframework.cloud.config.server.resource.ResourceController; import org.springframework.core.Ordered; import org.springframework.core.annotation.Order; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; @RestController @Order(Ordered.HIGHEST_PRECEDENCE) public class CustomConfigResourceController extends ResourceController { @GetMapping(value = "/{name}/{profile}/{path:.*}", params = "useDefaultLabel") public Object retrieveWithDefaultLabel(@PathVariable String name, @PathVariable String profile, @PathVariable String path, @RequestParam("useDefaultLabel") boolean useDefaultLabel) { // 强制使用配置的默认分支处理请求 String defaultLabel = getEnvironment().getProperty("spring.cloud.config.server.git.default-label"); return super.retrieve(name, profile, defaultLabel, path); } }
通过@Order(Ordered.HIGHEST_PRECEDENCE)确保该控制器的路由规则优先于默认的ResourceController。
版本调整
- 降级到spring-cloud-config-server 3.1.x版本:该版本的路径匹配逻辑对
params条件的优先级处理更合理,可避免此问题 - 升级到最新的4.x补丁版本:检查官方是否已修复该路由优先级bug,优先使用官方修复方案
内容的提问来源于stack exchange,提问作者bourne2program

