SpringCloud Gateway过滤器设置Reactor3 Context下游Controller无法获取求助
问题根因
- Reactor Context的作用域限制:Reactor的Context是单进程内响应式流订阅链路专属的上下文,仅在同一条响应式流的上下游传播。你当前场景中Spring Cloud Gateway和下游业务服务是两个独立运行的进程,网关只是负责转发HTTP请求,两个服务的响应式流完全独立,Context不可能跨进程传递。
- Context设置位置有误:Reactor的Context是从订阅端向上游传播的,你将
subscriberContext写在chain.filter(exchange)之后,执行过滤器链时还未写入Context,就算是同服务内的场景也无法读到值。
解决方案
场景1:网关转发到独立的下游服务
直接通过自定义请求头传递参数,网关将参数写入请求头后转发,下游服务读取请求头即可:
网关过滤器代码
@Override public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) { // 修改请求,添加自定义头携带参数 ServerHttpRequest newRequest = exchange.getRequest().mutate() .header("x-custom-key", "hello gate") .build(); return chain.filter(exchange.mutate().request(newRequest).build()); }
下游Controller代码
@ResponseBody @RequestMapping("/test") public Mono<String> test(@RequestHeader("x-custom-key") String key) { return Mono.just(key); }
如果参数敏感,可在下游服务的全局拦截器中读完请求头后移除,避免返回给客户端时泄露。
场景2:网关本身提供本地接口(未转发到其他服务)
如果是网关服务内部的Controller需要读取Context,要修正Context的API写法和位置:
注意:Reactor 3.4+版本已废弃
subscriberContext,统一使用contextWrite写入Context,deferContextual读取Context。
网关过滤器代码
@Override public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) { // contextWrite写在过滤器链执行前,确保能传播到下游流 return chain.filter(exchange) .contextWrite(ctx -> ctx.put("key", "hello gate")); }
网关本地Controller代码
@ResponseBody @RequestMapping("/local-test") public Mono<String> localTest() { return Mono.deferContextual(ctx -> Mono.just(ctx.get("key"))); }
内容的提问来源于stack exchange,提问作者LI_guoyu
相关产品推荐
相关产品推荐

