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中灵活地处理请求和响应,实现多样化的路由逻辑和安全需求。