本文将带你一步步构建一个高性能的响应式 API 网关。该网关支持多服务器适配、URL 规范化、CORS 配置等核心功能,适用于高并发场景。
一、环境准备
前置依赖
- JDK 17 或更高版本
- Maven 3.6+
- 开发工具(IntelliJ IDEA 或 Eclipse)
创建 Maven 项目
第一创建一个空的 Maven 项目,然后在 pom.xml 中添加核心依赖:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.example</groupId>
<artifactId>reactive-gateway-demo</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
<spring.version>6.2.0</spring.version>
<reactor-netty.version>1.2.0</reactor-netty.version>
</properties>
<dependencies>
<!-- Spring 核心依赖 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webflux</artifactId>
<version>${spring.version}</version>
</dependency>
<!-- 服务器依赖 -->
<dependency>
<groupId>io.projectreactor.netty</groupId>
<artifactId>reactor-netty-http</artifactId>
<version>${reactor-netty.version}</version>
</dependency>
<!-- 日志依赖 -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>2.0.16</version>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.5.12</version>
</dependency>
</dependencies>
</project>
二、核心组件实现
1. 创建启动类
创建 GatewayApplication 作为应用入口:
package com.example.gateway;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.server.reactive.HttpHandler;
import org.springframework.web.server.adapter.WebHttpHandlerBuilder;
@Configuration
@ComponentScan("com.example.gateway")
public class GatewayApplication {
public static void main(String[] args) throws Exception {
// 初始化 Spring 上下文
AnnotationConfigApplicationContext context =
new AnnotationConfigApplicationContext(GatewayApplication.class);
// 构建 HttpHandler
HttpHandler handler = WebHttpHandlerBuilder.applicationContext(context).build();
// 启动 Reactor Netty 服务器
startReactorNetty(handler, "localhost", 8080);
// 保持应用运行
Thread.currentThread().join();
}
// 启动 Reactor Netty 服务器的方法
private static void startReactorNetty(HttpHandler handler, String host, int port) {
ReactorHttpHandlerAdapter adapter = new ReactorHttpHandlerAdapter(handler);
HttpServer.create().host(host).port(port).handle(adapter).bindNow();
System.out.println("Server started on " + host + ":" + port);
}
}
2. 配置 Web 处理链
创建 WebHandlerConfig 配置请求处理逻辑:
package com.example.gateway.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.server.WebFilter;
import org.springframework.web.server.WebHandler;
import org.springframework.web.server.session.DefaultWebSessionManager;
import org.springframework.web.server.session.WebSessionManager;
@Configuration
public class WebHandlerConfig {
// 核心请求处理逻辑
@Bean
public WebHandler webHandler() {
return exchange -> {
// 这里可以添加自定义的请求处理逻辑
return exchange.getResponse().setComplete();
};
}
// 自定义过滤器
@Bean
public WebFilter loggingFilter() {
return (exchange, chain) -> {
System.out.println("Processing request: " + exchange.getRequest().getPath());
return chain.filter(exchange)
.doFinally(signalType ->
System.out.println("Finished processing: " + exchange.getRequest().getPath()));
};
}
// 会话管理配置
@Bean
public WebSessionManager webSessionManager() {
return new DefaultWebSessionManager();
}
}
3. 配置 URL 规范化
创建 UrlFilterConfig 处理 URL 尾部斜杠问题:
package com.example.gateway.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpStatus;
import org.springframework.web.filter.reactive.UrlHandlerFilter;
@Configuration
public class UrlFilterConfig {
@Bean
public UrlHandlerFilter urlHandlerFilter() {
return UrlHandlerFilter
// 对 /api/** 路径的带斜杠 URL 执行 308 永久重定向
.trailingSlashHandler("/api/**").redirect(HttpStatus.PERMANENT_REDIRECT)
// 对 /admin/** 路径的带斜杠 URL 修改请求路径(内部处理)
.trailingSlashHandler("/admin/**").mutateRequest()
.build();
}
}
4. 配置跨域支持
创建 CorsConfig 解决跨域问题:
package com.example.gateway.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.reactive.CorsWebFilter;
import org.springframework.web.cors.reactive.UrlBasedCorsConfigurationSource;
@Configuration
public class CorsConfig {
@Bean
public CorsWebFilter corsWebFilter() {
CorsConfiguration config = new CorsConfiguration();
config.setAllowCredentials(true);
config.addAllowedOrigin("https://your-frontend-domain.com");
config.addAllowedHeader("*");
config.addAllowedMethod("*");
config.setMaxAge(3600L); // 预检请求缓存时间
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", config);
return new CorsWebFilter(source);
}
}
5. 配置代理转发头处理
创建 ForwardedHeaderConfig 处理代理服务器传递的头信息:
package com.example.gateway.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.server.adapter.ForwardedHeaderTransformer;
@Configuration
public class ForwardedHeaderConfig {
@Bean
public ForwardedHeaderTransformer forwardedHeaderTransformer() {
ForwardedHeaderTransformer transformer = new ForwardedHeaderTransformer();
// 如果不需要使用代理头信息,仅需要移除,可以设置为 true
// transformer.setRemoveOnly(true);
return transformer;
}
}
三、扩展功能实现
1. 多服务器支持
如果需要切换到 Tomcat 或 Jetty 服务器,可以添加对应的启动方法:
// 在 GatewayApplication 中添加
private static void startTomcat(HttpHandler handler, String host, int port) throws Exception {
Servlet servlet = new TomcatHttpHandlerAdapter(handler);
Tomcat server = new Tomcat();
File base = new File(System.getProperty("java.io.tmpdir"));
Context rootContext = server.addContext("", base.getAbsolutePath());
Tomcat.addServlet(rootContext, "main", servlet);
rootContext.addServletMappingDecoded("/", "main");
server.setHostname(host);
server.setPort(port);
server.getConnector(); // 触发连接器创建
server.start();
}
private static void startJetty(HttpHandler handler, String host, int port) throws Exception {
JettyCoreHttpHandlerAdapter adapter = new JettyCoreHttpHandlerAdapter(handler);
Server server = new Server();
server.setHandler(adapter);
ServerConnector connector = new ServerConnector(server);
connector.setHost(host);
connector.setPort(port);
server.addConnector(connector);
server.start();
}
然后在 main 方法中根据需要调用对应的启动方法即可。
2. 请求日志追踪
添加请求 ID 日志追踪功能:
package com.example.gateway.config;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.server.WebFilter;
@Configuration
public class LogConfig {
private static final Logger logger = LoggerFactory.getLogger(LogConfig.class);
@Bean
public WebFilter logIdFilter() {
return (exchange, chain) -> {
// 获取请求专属日志前缀
String logPrefix = exchange.getLogPrefix();
logger.info("{} Handling request: {}", logPrefix,
exchange.getRequest().getURI());
return chain.filter(exchange)
.doFinally(signalType ->
logger.info("{} Completed request with status: {}",
logPrefix,
exchange.getResponse().getStatusCode()));
};
}
}
四、运行与测试
启动应用
直接运行 GatewayApplication 的 main 方法,或使用 Maven 命令:
mvn compile exec:java -Dexec.mainClass="com.example.gateway.GatewayApplication"
应用将在 localhost:8080 启动。
测试功能
- URL 规范化测试:
- 访问 http://localhost:8080/api/test/ ,则会被重定向到 http://localhost:8080/api/test(308 状态码)
- 访问 http://localhost:8080/admin/user/ 会被内部处理为 http://localhost:8080/admin/user
- 跨域测试:
- 从配置的前端域名发送请求到网关,应能正常处理跨域请求
- 日志测试:
- 查看控制台输出,应能看到包含请求 ID 的日志信息
五、总结
通过本文的步骤,你已经搭建了一个基于 Spring Framework 6.2 的响应式网关,具备以下功能:
- 支持 Reactor Netty、Tomcat、Jetty 多种服务器
- 自动处理 URL 尾部斜杠,保证路由一致性
- 完善的跨域资源共享配置
- 支持代理服务器转发头处理
- 请求级别的日志追踪
你可以根据实际需求,进一步扩展网关功能,如添加路由转发、负载均衡、认证授权等功能。
© 版权声明
文章版权归作者所有,未经允许请勿转载。
相关文章
暂无评论...




