1:我个人所了解到的有两种方式,都是利用路由谓词过滤器获取:
同样的获取方式
// 获取缓存里请求体的body值
String requestBody = exchange.getAttribute("cachedRequestBodyObject");
1:在代码里使用RouteLocator
import org.springframework.cloud.gateway.route.RouteLocator;
import org.springframework.cloud.gateway.route.builder.RouteLocatorBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Component;
import reactor.core.publisher.Mono;
@Component
public class AccessLogFilter {
@Bean
public RouteLocator myRouteLocator(RouteLocatorBuilder builder) {
return builder.routes()
// 路由id随意指定,和其他路由id不重复即可
.route("routeId", p -> p
// api-user 代表下游微服务的一级路由
.path("/api-user/account/save")
// 此处的 1 代表将上面的/api-user截取掉, 这样后面的路径就是下个微服务的请求接口(/account/save)
.filters(f -> f.stripPrefix(1)
.modifyRequestBody(String.class, String.class, (webExchange, originalBody) -> {
if (originalBody != null) {
webExchange.getAttributes().put("cachedRequestBodyObject", originalBody);
return Mono.just(originalBody);
} else {
return Mono.empty();
}
}))
// lb: 代表着路由到其他的微服务, service-user: 是你要路由的微服务启动后的服务名
.uri("lb://service-user"))
.build();
}
}
2:在配置文件里使用predicates
import org.springframework.stereotype.Component;
import java.util.function.Predicate;
/**
* 是否记录请求体的body, 根据配置文件里的path进行生效
* 配置文件里搜索 @requestBodyPredicate 定位到该路由规则
*/
@Component
public class RequestBodyPredicate implements Predicate {
/**
* 是否缓存 请求体里的body 值
*
* @param body 请求体里的对象
* @return boolean false: 不缓存, true: 缓存, 在下面的filter里获取方式: exchange.getAttribute("cachedRequestBodyObject");
*/
@Override
public boolean test(Object body) {
return true;
}
}
# 参考java代码里的注释
spring:
cloud:
gateway:
routes:
- id: routeId
uri: lb://service-user
predicates:
- Path=/api-user/account/save
# 使用该Factory,会将body自动放入到过滤器中
- name: ReadBodyPredicateFactory
args:
inClass: "#{T(String)}"
# requestBodyPredicate 对应着 spring bean 的名称
predicate: "#{@requestBodyPredicate}"
filters:
- StripPrefix=1