Spring Webflux中通过WebFilter实现服务端请求转发到外部应用
Spring Boot Webflux 服务端请求转发实现方案
你需要实现的是服务端反向代理转发,整个转发逻辑在应用内部完成,客户端无感知,可完整保留原始请求的请求头、请求体。
你之前使用的
response.getHeaders().setLocation(mutatedURL)属于客户端3xx重定向逻辑:服务端仅返回重定向状态码和目标地址,由客户端主动发起新请求到目标地址,会丢失原始请求的非GET类请求体,且客户端可感知到地址变化,不符合你的需求。
实现步骤(手动WebClient方案,最灵活,支持自定义过滤逻辑)
1. 基础依赖确认
确保项目已引入WebFlux starter,包含所需的WebClient响应式HTTP客户端:
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-webflux</artifactId> </dependency>
2. 编写全局WebFilter实现转发逻辑
直接实现org.springframework.web.server.WebFilter接口,在过滤器中完成请求拦截、逻辑判断、转发、响应回写的全流程:
import org.springframework.web.reactive.function.BodyInserters; import org.springframework.web.reactive.function.client.WebClient; import org.springframework.web.server.WebFilter; import org.springframework.web.server.WebFilterChain; import org.springframework.http.server.reactive.ServerHttpRequest; import org.springframework.http.server.reactive.ServerHttpResponse; import org.springframework.core.io.buffer.DataBuffer; import reactor.core.publisher.Mono; @Component public class ForwardFilter implements WebFilter { // 初始化WebClient,可根据需求配置连接超时、连接池、SSL校验等参数 private final WebClient webClient = WebClient.create(); @Override public Mono<Void> filter(ServerWebExchange exchange, WebFilterChain chain) { ServerHttpRequest originalRequest = exchange.getRequest(); ServerHttpResponse originalResponse = exchange.getResponse(); // 你的自定义过滤逻辑:判断是否需要转发,不符合则走原有业务流程 boolean needForward = checkNeedForward(originalRequest); if (!needForward) { return chain.filter(exchange); } // 构造目标转发地址,替换为你的外部应用地址+原始请求路径+查询参数 String targetUrl = "http://你的外部应用地址" + originalRequest.getPath().value() + (originalRequest.getQueryParams().isEmpty() ? "" : "?" + originalRequest.getQueryParams()); // 转发请求,携带原始请求的方法、头、完整请求体 return webClient.method(originalRequest.getMethod()) .uri(targetUrl) // 复制原始请求头,可按需过滤不需要传递的头(如Host等) .headers(httpHeaders -> { httpHeaders.addAll(originalRequest.getHeaders()); httpHeaders.remove("Host"); // 避免目标服务Host校验失败 }) .body(BodyInserters.fromDataBuffers(originalRequest.getBody())) .exchangeToMono(forwardResponse -> { // 复制外部应用返回的响应头到原始响应 originalResponse.getHeaders().putAll(forwardResponse.headers().asHttpHeaders()); // 复制外部应用返回的状态码到原始响应 originalResponse.setStatusCode(forwardResponse.statusCode()); // 把外部应用的响应体写回给原始请求的调用方 return originalResponse.writeWith(forwardResponse.bodyToFlux(DataBuffer.class)); }); } private boolean checkNeedForward(ServerHttpRequest request) { // 实现你的自定义判断逻辑,比如按路径、请求头、参数判断是否需要转发 return request.getPath().value().startsWith("/需要转发的路径前缀/"); } }
关键注意事项
- 该方案基于响应式流实现,可完美处理大文件上传、大响应体等场景,不会出现内存溢出问题
- 可根据业务需求自定义WebClient的超时、连接池、重试策略等配置,满足不同外部服务的调用要求
- 如果转发规则比较固定,也可引入Spring Cloud Gateway依赖,通过配置式路由实现转发,无需手动编码
内容的提问来源于stack exchange,提问作者Vikram Thakur
相关产品推荐
相关产品推荐

