Spring响应式栈(Netty)中如何便捷获取请求URI及相关属性?
响应式栈(Netty)中便捷获取请求URI属性的方案
方案1:借助ServerWebExchangeContext直接获取上下文请求
在Spring WebFlux的响应式环境中,可通过ServerWebExchangeContext在请求上下文范围内的任意组件中直接获取当前请求的ServerWebExchange,进而提取URI属性:
- 仅能在Web请求的处理上下文(如控制器方法、过滤器、被请求上下文调用的Bean)中使用
- 代码示例:
import org.springframework.web.server.ServerWebExchange; import org.springframework.web.server.ServerWebExchangeContext; // 在需要提取属性的代码段中调用 ServerWebExchange exchange = ServerWebExchangeContext.current(); URI uri = exchange.getRequest().getURI(); // 提取目标属性 String scheme = uri.getScheme(); String schemeSpecificPart = uri.getSchemeSpecificPart(); String host = uri.getHost(); int port = uri.getPort();
注意:该方式依赖请求上下文的绑定,非请求线程中调用会抛出异常。
方案2:通过过滤器封装属性到Reactor Context
如果需要在异步操作或下游组件中传递URI属性,可自定义过滤器将属性存入Reactor的Context,实现全请求链路的可访问性:
- 编写自定义过滤器:
import org.springframework.http.server.reactive.ServerHttpRequest; import org.springframework.web.server.ServerWebExchange; import org.springframework.web.server.WebFilter; import org.springframework.web.server.WebFilterChain; import reactor.core.publisher.Mono; public class UriContextFilter implements WebFilter { @Override public Mono<Void> filter(ServerWebExchange exchange, WebFilterChain chain) { ServerHttpRequest request = exchange.getRequest(); URI uri = request.getURI(); // 将URI属性写入Reactor Context return chain.filter(exchange) .contextWrite(ctx -> ctx .put("uri.scheme", uri.getScheme()) .put("uri.schemeSpecificPart", uri.getSchemeSpecificPart()) .put("uri.host", uri.getHost()) .put("uri.port", uri.getPort())); } }
- 注册过滤器到Spring容器:
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @Configuration public class WebConfig { @Bean public UriContextFilter uriContextFilter() { return new UriContextFilter(); } }
- 在业务逻辑中从Context提取属性:
import reactor.core.publisher.Mono; public Mono<String> getHostFromContext() { return Mono.deferContextual(ctxView -> { String host = ctxView.get("uri.host"); return Mono.just(host); }); }
方案3:针对特定属性的简化提取
部分属性可通过请求头或请求状态直接推断,无需完整获取URI:
import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; import org.springframework.http.server.reactive.ServerHttpRequest; import reactor.core.publisher.Mono; @RestController public class DemoController { @GetMapping("/demo") public Mono<String> demo(@RequestHeader("Host") String host, ServerHttpRequest request) { // 通过请求是否安全推断scheme String scheme = request.isSecure() ? "https" : "http"; int port = request.getURI().getPort(); return Mono.just(String.format("Scheme: %s, Host: %s, Port: %d", scheme, host, port)); } }
该方式适合仅需部分属性的简单场景,无需全局传递上下文。
内容的提问来源于stack exchange,提问作者Sebastian Lore
相关产品推荐
相关产品推荐

