如何使用Spring Cloud API Gateway (MVC)实现请求参数转路径的动态过滤器?
在Spring Cloud API Gateway (MVC)中转换查询参数为路径参数
需求说明
需要处理GET请求,将带查询参数的请求路径转换为路径参数形式:
- 原始请求:
v1/sample-resource/methodName?id=id12345 - 目标请求:
v1/sample-resource/methodName/id12345
当前使用的依赖版本:
id 'org.springframework.boot' version '3.3.1' implementation 'org.springframework.cloud:spring-cloud-starter-gateway-mvc'
现有尝试代码
文件路径:com/example/demo/routes/RouteConfiguration.java
@Configuration class RouteConfiguration { @Bean public RouterFunction<ServerResponse> gatewayRouterAddRequestParam() { return route("add_request_parameter_route") .GET("v1/resource-name/id12345/methodName", http("https://example.org")) .before( rewritePath("v1/resource-name/(?<segment>.*)", "v1/resource-name/methodName") .andThen(addRequestParameter("id", "id12345")) ) .build(); } }
解决方案
你的现有代码存在两个核心问题:路由匹配规则与原始请求不匹配,且未实现动态提取查询参数值。以下是修正后的实现:
1. 核心实现思路
- 匹配原始请求路径
v1/sample-resource/methodName,且要求携带id查询参数 - 从请求中动态提取
id参数的值 - 重写请求路径,将查询参数转为路径参数
- 可选移除原查询参数,避免传递到下游服务
2. 修正后的代码(直接处理请求方式)
@Configuration class RouteConfiguration { @Bean public RouterFunction<ServerResponse> gatewayRouter() { return route("query_to_path_param_route") // 匹配原始请求路径及带id参数的GET请求 .GET("v1/sample-resource/methodName", request -> { // 动态获取id查询参数,无参数时抛出异常 String id = request.queryParam("id").orElseThrow(() -> new IllegalArgumentException("id参数不能为空")); // 构造目标路径 String rewrittenPath = String.format("v1/sample-resource/methodName/%s", id); // 修改请求路径并移除原查询参数 ServerHttpRequest modifiedRequest = request.mutate() .path(rewrittenPath) .queryParams(params -> params.remove("id")) .build(); // 转发到下游服务,替换为你的实际服务地址 return ServerResponse.status(HttpStatus.OK) .build(http("https://example.org").exchange(modifiedRequest)); }) .build(); } }
3. Filter链式调用写法
如果偏好使用Filter链式处理,可自定义前置Filter实现:
@Configuration class RouteConfiguration { @Bean public RouterFunction<ServerResponse> gatewayRouterWithFilter() { return route("query_to_path_param_filter_route") .GET("v1/sample-resource/methodName", http("https://example.org")) .before(request -> { // 提取id参数 String id = request.queryParam("id").orElseThrow(() -> new IllegalArgumentException("id参数不能为空")); // 拼接新路径 String newPath = request.path() + "/" + id; // 修改请求并移除原查询参数 return request.mutate() .path(newPath) .queryParams(params -> params.remove("id")) .build(); }) .build(); } }
关键注意点
- 路由匹配规则必须对应原始请求路径,而非目标路径
- 用
request.queryParam("id")动态获取参数值,避免硬编码 - 通过
request.mutate()修改请求对象,确保下游收到正确的路径参数 - 若
id为可选参数,可移除orElseThrow,改为设置默认值或跳过路径重写逻辑
内容的提问来源于stack exchange,提问作者user23524156
相关产品推荐
相关产品推荐

