ModifyRequestBody GatewayFilter 工厂
你可以使用 ModifyRequestBody 过滤器在网关将请求发送到下游之前修改请求体(Request Body)。
注意
此过滤器只能使用 Java DSL 进行配置(不支持在 application.yml 中配置)。
以下代码演示了如何修改请求体:
Java 配置示例
java
@Bean
public RouteLocator routes(RouteLocatorBuilder builder) {
return builder.routes()
.route("rewrite_request_obj", r -> r.host("*.rewriterequestobj.org")
.filters(f -> f.prefixPath("/httpbin")
.modifyRequestBody(String.class, Hello.class, MediaType.APPLICATION_JSON_VALUE,
(exchange, s) -> Mono.just(new Hello(s.toUpperCase()))))
.uri(uri))
.build();
}
// 示例内部类 Hello
static class Hello {
String message;
public Hello() { }
public Hello(String message) {
this.message = message;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
}代码解析:
- 输入类型 (
String.class): 告诉过滤器将原始请求体读取为 String。 - 输出类型 (
Hello.class): 告诉过滤器修改后的请求体应该被转换成 Hello 对象(最终序列化为 JSON)。 - Content-Type (
MediaType.APPLICATION_JSON_VALUE): 设置下游请求的 Content-Type。 - 转换逻辑 (
RewriteFunction): 这里的 Lambda 表达式(exchange, s) -> ...接收原始的字符串s,将其转换为大写,放入Hello对象中并返回。
注意:空请求体处理
如果请求没有 Body(即 Body 为 null),RewriteFunction 接收到的参数也会是 null。 如果你希望在这种情况下仍然保持请求体为空,应该返回 Mono.empty()。
补充教学 —— 为什么要修改请求体?
场景 1:数据格式转换
- 客户端发送的是 XML 格式的数据。
- 后端微服务升级了,只支持 JSON 格式。
- 网关可以在中间拦截,把 XML 读出来,转成 JSON 对象,再发给后端。
场景 2:参数注入/脱敏
- 注入:所有的请求体里都需要加一个公共字段(比如
traceId或者timestamp),可以在网关层统一加上,不用每个端点都写一遍。 - 脱敏:客户端上传的数据包含敏感信息(如明文密码),网关可以在转发给日志服务或特定后端前,把敏感字段替换成
******。
场景 3:请求体大小写转换
- 如上面的示例代码所示,把请求体里的字符串全部变成大写。
关键点: 由于请求体修改涉及到反序列化(读出对象) -> 修改逻辑 -> 序列化(写回字节流),这在响应式编程(WebFlux)中稍微有点复杂,所以 Spring Cloud Gateway 目前只支持用 Java 代码(Java DSL)来写这个逻辑,因为 YAML 配置文件没法写复杂的 Lambda 函数。