切换语言为:繁体

SpringBoot Gateway的前置过滤器和后置过滤器

  • 爱糖宝
  • 2024-07-25
  • 2081
  • 0
  • 0

Spring Cloud Gateway 基于WebFlux框架使用非阻塞API。它主要通过路由定义来决定请求如何被处理。每个路由可以指定一个或多个过滤器,这些过滤器可以修改请求和响应。

  • 前置过滤器:这些过滤器在请求实际被路由到下游服务之前执行。它们可以用来修改请求头、查询参数、验证请求等。

  • 后置过滤器:这些过滤器在请求被下游服务处理之后执行,通常用于修改响应或进行日志记录。

简单概念

过滤器工作流程

在Spring Cloud Gateway中,请求经过以下几个步骤:

  1. 请求匹配:判断请求是否匹配某个路由的条件。

  2. 前置过滤器执行:执行所有前置过滤器,可能修改请求。

  3. 请求路由:将请求转发到相应的下游服务。

  4. 后置过滤器执行:在得到下游服务响应后执行,可能修改响应。

源码解析

我们将看看关键的类和接口:

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

0条评论

您的电子邮件等信息不会被公开,以下所有项均必填

OK! You can skip this field.