Spring Cloud Gateway 基于WebFlux框架使用非阻塞API。它主要通过路由定义来决定请求如何被处理。每个路由可以指定一个或多个过滤器,这些过滤器可以修改请求和响应。
前置过滤器:这些过滤器在请求实际被路由到下游服务之前执行。它们可以用来修改请求头、查询参数、验证请求等。
后置过滤器:这些过滤器在请求被下游服务处理之后执行,通常用于修改响应或进行日志记录。
简单概念
过滤器工作流程
在Spring Cloud Gateway中,请求经过以下几个步骤:
请求匹配:判断请求是否匹配某个路由的条件。
前置过滤器执行:执行所有前置过滤器,可能修改请求。
请求路由:将请求转发到相应的下游服务。
后置过滤器执行:在得到下游服务响应后执行,可能修改响应。
源码解析
我们将看看关键的类和接口:
GatewayFilter:所有自定义过滤器需要实现这个接口,它定义了一个方法,该方法接受ServerWebExchange和GatewayFilterChain。
GlobalFilter:一种特殊类型的GatewayFilter,自动应用于所有路由。
ServerWebExchange:代表当前请求和响应的上下文,可以用来访问和修改请求和响应。
以下是一个简单的前置过滤器示例的伪代码:
public class ExamplePreFilter implements GatewayFilter, Ordered { @Override public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) { // 访问请求对象 ServerHttpRequest request = exchange.getRequest(); // 修改请求(例如:添加头信息) ServerHttpRequest modifiedRequest = request.mutate().header("New-Header", "Value").build(); // 将修改后的请求对象传递给下一个过滤器链 return chain.filter(exchange.mutate().request(modifiedRequest).build()); } @Override public int getOrder() { // 定义过滤器顺序 return -1; } }
后置过滤器的示例伪代码:
public class ExamplePostFilter implements GatewayFilter, Ordered { @Override public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) { // 继续过滤器链的执行 return chain.filter(exchange).then(Mono.fromRunnable(() -> { // 访问响应 ServerHttpResponse response = exchange.getResponse(); // 修改响应(例如:添加头信息) response.getHeaders().add("Post-Header", "Value"); })); } @Override public int getOrder() { // 定义过滤器顺序 return 1000; } }
在Spring Cloud Gateway的源代码中,这些类和接口被实现和使用,以提供强大的路由和过滤功能。每个过滤器的执行都是异步和非阻塞的,利用的是Project Reactor提供的反应式编程模型。
在Spring Boot中使用Spring Cloud Gateway的前置过滤器和后置过滤器的示例可以应用于许多实际场景。以下是一个具体的例子,我们将构建一个网关,它使用前置过滤器来校验请求中的API密钥,并使用后置过滤器来添加一些响应头信息。
场景实例
场景描述
假设我们有一个需要保护的微服务,只有提供了有效的API密钥的请求才能访问。我们还想在所有响应中添加一些标准的HTTP头,比如一个标识服务的自定义头。
步骤1: 设置Spring Boot和Spring Cloud Gateway
首先,确保你的Spring Boot项目包含了必要的依赖。可以在pom.xml
中添加如下依赖:
<dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-gateway</artifactId> <version>3.0.3</version> <!-- 使用合适的版本 --> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-webflux</artifactId> </dependency> </dependencies> <dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-dependencies</artifactId> <version>2020.0.3</version> <!-- 使用合适的版本 --> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement>
步骤2: 创建前置过滤器
创建一个检查API密钥的前置过滤器。如果API密钥无效,我们将阻止请求继续处理。
import org.springframework.cloud.gateway.filter.GatewayFilterChain; import org.springframework.cloud.gateway.filter.GlobalFilter; import org.springframework.core.Ordered; import org.springframework.http.HttpStatus; import org.springframework.http.server.reactive.ServerHttpRequest; import org.springframework.web.server.ServerWebExchange; import reactor.core.publisher.Mono; public class ApiKeyFilter implements GlobalFilter, Ordered { @Override public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) { ServerHttpRequest request = exchange.getRequest(); // 验证API密钥 String apiKey = request.getHeaders().getFirst("API-Key"); if (apiKey == null || !apiKey.equals("正确的密钥")) { exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED); return exchange.getResponse().setComplete(); // 中断请求 } return chain.filter(exchange); // 继续处理请求 } @Override public int getOrder() { return -100; // 优先级高 } }
步骤3: 创建后置过滤器
添加一个后置过滤器来在每个响应中添加自定义HTTP头。
import org.springframework.cloud.gateway.filter.GatewayFilterChain; import org.springframework.cloud.gateway.filter.GlobalFilter; import org.springframework.core.Ordered; import org.springframework.web.server.ServerWebExchange; import reactor.core.publisher.Mono; public class AddResponseHeaderFilter implements GlobalFilter, Ordered { @Override public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) { return chain.filter(exchange).then(Mono.fromRunnable(() -> { exchange.getResponse().getHeaders().add("X-Service-Name", "MyService"); })); } @Override public int getOrder() { return 1000; // 优先级低 } }
步骤4: 配置过滤器
在你的Spring Boot应用中配置这些过滤器。
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @Configuration public class GatewayConfig { @Bean public ApiKeyFilter apiKeyFilter() { return new ApiKeyFilter(); } @Bean public AddResponseHeaderFilter addResponseHeaderFilter() { return new AddResponseHeaderFilter(); } }
总结
这个示例创建了两个过滤器:一个用于在请求时检查API密钥的有效性,另一个用于在所有响应中添加自定义头。通过这种方式,你可以在Spring Cloud Gateway中灵活地处理请求和响应,实现多样化的路由逻辑和安全需求。