如何在Spring Boot中代理转发端点请求?开发环境路径转发方案
实现Spring Boot开发环境下的路径代理(类似webpack devServer.proxy)
问题分析
你之前的代码使用redirect会触发浏览器重定向,直接请求目标端口18896,这和代理需求不符——代理需要后端内部转发请求,前端完全感知不到目标地址。同时代码没有保留请求路径的后缀部分(比如/something/1中的1),导致转发路径不完整。
解决方案
以下两种方案都能实现类似webpack devServer.proxy的代理效果,且仅在开发环境生效,无需修改前端代码。
方案一:使用Spring Cloud Gateway(推荐,配置驱动)
这种方式无需编写Java代码,仅通过配置即可实现代理,适合大多数场景。
- 引入依赖
在pom.xml中添加Spring Cloud Gateway依赖:
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-gateway</artifactId> </dependency>
- 开发环境配置
在application-dev.yml中添加路由配置(仅在开发环境加载):
spring: cloud: gateway: routes: - id: something-service-proxy uri: http://localhost:18896 # 目标服务地址 predicates: - Path=/something/** # 匹配需要代理的路径
当前端请求http://localhost:19988/something/1时,Gateway会自动将请求转发到http://localhost:18896/something/1,并将响应原封不动返回给前端。
方案二:使用Controller + WebClient(无额外依赖,代码实现)
如果不想引入Spring Cloud Gateway,可以通过编写Controller结合WebClient实现转发,确保仅在开发环境生效。
- 配置目标地址
在application-dev.yml中添加代理目标地址:
proxy: target-url: http://localhost:18896
- 编写代理Controller
import org.springframework.beans.factory.annotation.Value; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpMethod; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.*; import org.springframework.web.reactive.function.client.WebClient; @RestController @RequestMapping("/something") @Profile("dev") # 仅在开发环境启用该Controller public class SomethingProxyController { private final WebClient webClient; private final String targetBaseUrl; public SomethingProxyController(WebClient.Builder webClientBuilder, @Value("${proxy.target-url}") String targetBaseUrl) { this.webClient = webClientBuilder.baseUrl(targetBaseUrl).build(); this.targetBaseUrl = targetBaseUrl; } @RequestMapping(value = "/**", method = {RequestMethod.GET, RequestMethod.POST, RequestMethod.PUT, RequestMethod.DELETE}) public ResponseEntity<?> proxyRequest(@PathVariable("**") String pathSegment, @RequestHeader HttpHeaders headers, @RequestBody(required = false) String requestBody, HttpMethod requestMethod) { // 移除可能导致转发冲突的Host头 headers.remove(HttpHeaders.HOST); return webClient.method(requestMethod) .uri("/something/{path}", pathSegment) .headers(httpHeaders -> httpHeaders.addAll(headers)) .bodyValue(requestBody) .retrieve() .toEntity(String.class) .block(); } }
@Profile("dev")确保该Controller仅在开发环境生效,生产环境不会加载。@PathVariable("**")捕获/something之后的所有路径部分(比如1、detail/2等)。- WebClient负责将请求转发到目标服务,保留原请求的方法、头信息和请求体,并将目标服务的响应返回给前端。
注意事项
- 生产环境无需任何配置,因为两服务共用同一URL,请求会直接到达对应服务。
- 如果项目使用同步编程模型,可以用
RestTemplate替代WebClient,核心逻辑一致。
内容的提问来源于stack exchange,提问作者Damian Pereira
相关产品推荐
相关产品推荐

