java

关注公众号 jb51net

关闭
首页 > 软件编程 > java > SpringCloud Gateway断言路由和过滤器的使用

SpringCloud Gateway中断言路由和过滤器的使用详解

作者:Xwzzz_

这篇文章主要介绍了SpringCloud Gateway中断言路由和过滤器的使用,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教

一、Gateway概念

Spring Cloud Gateway(简称 Gateway)是一个基于 Spring WebFlux 的 API 网关解决方案,旨在为微服务架构中的客户端提供路由、负载均衡、认证、限流、监控等功能。

它作为微服务架构中的流量入口,通常位于客户端和后端微服务之间,处理来自客户端的请求并将其路由到相应的服务。

主要特性:

  1. 路由功能:Spring Cloud Gateway 可以根据请求的不同特征(如路径、方法、头部、参数等)将请求路由到不同的微服务。
  2. 负载均衡:支持与服务注册中心(如 Eureka)集成,能够将流量分发到多个实例,以实现负载均衡。
  3. 过滤器:提供了丰富的过滤器功能,可以在请求和响应的生命周期中进行定制化处理。例如,身份认证、日志记录、限流等。
  4. 反向代理:可以将请求转发给后端服务,实现反向代理功能。
  5. 高可用和可扩展性:通过与 Spring Cloud 配合使用,Spring Cloud Gateway 能够在微服务架构中提供高可用和扩展性支持。
  6. 监控:可以与 Spring Boot Actuator 集成,提供请求和响应的监控功能,帮助开发人员监控系统的健康状况和性能。

二、基本路由

路由是将客户端请求发送到后端服务的主要组件。它定义了请求的匹配规则以及请求将被转发到的目标(即URI)。每个路由都具有一个iduri以及predicates

spring:
    cloud:
        gateway:
            routes:
                - id: order-route
                  uri: lb://service-order
                  predicates:
                    - Path=/api/order/**

三、断言

断言(Predicates) 用于根据请求的各种属性来匹配路由,它们是路由的核心部分。

断言支持不同的匹配条件,如路径、请求方法、请求头等。通过不同的请求模式来匹配对应的微服务。

3.1在Spring Cloud Gateway的配置中,断言有两种写法

spring:
  cloud:
    gateway:
      routes:
        - id: order-route
          uri: lb://service-order
          predicates:
            - name: Path
              args:
                pattern: /api/order/**
spring:
  cloud:
    gateway:
      routes:
        - id: order-route
          uri: lb://service-order
          predicates:
            - Path=/api/order/**

系统内置断言(Predicates)

Spring Cloud Gateway 提供了很多内置的断言类型,用来处理各种请求匹配需求。常用的断言类型包括:

这张图展示了Spring Cloud Gateway中常用的路由断言(Predicates)及其相关参数说明。断言是路由配置的重要组成部分,它们用来判断请求是否满足特定条件,以决定是否将请求转发到目标服务。

每种断言都允许通过指定参数来对请求进行详细匹配。

3.2自定义断言

我们通过继承 AbstractRoutePredicateFactory 类,创建了一个名为 VipRoutePredicateFactory 的类,实现了自定义的路由断言逻辑,示例代码如下:

import org.springframework.cloud.gateway.handler.predicate.AbstractRoutePredicateFactory;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.apache.commons.lang3.StringUtils;

import java.util.Arrays;
import java.util.List;
import java.util.function.Predicate;

/**
 * 自定义路由断言工厂
 */
@Component
public class VipRoutePredicateFactory extends AbstractRoutePredicateFactory<VipRoutePredicateFactory.Config> {

    public VipRoutePredicateFactory() {
        super(Config.class);  // 传入Config类
    }

    @Override
    public List<String> shortcutFieldOrder() {
        // 返回配置类中的字段顺序
        return Arrays.asList("param", "value");
    }

    @Override
    public Predicate<ServerWebExchange> apply(Config config) {
        return new GatewayPredicate() {

            @Override
            public boolean test(ServerWebExchange serverWebExchange) {
                // 获取请求
                ServerHttpRequest request = serverWebExchange.getRequest();

                // 从请求的查询参数中获取 'param' 对应的值
                String first = request.getQueryParams().getFirst(config.param);

                // 比较查询参数的值与配置中的 'value' 是否匹配
                return StringUtils.isNotBlank(first) && first.equals(config.value);
            }
        };
    }

    // 配置类
    public static class Config {
        private String param;  // 查询参数名称
        private String value;  // 查询参数期望的值

        // Getter和Setter方法
        public String getParam() {
            return param;
        }

        public void setParam(String param) {
            this.param = param;
        }

        public String getValue() {
            return value;
        }

        public void setValue(String value) {
            this.value = value;
        }
    }
}

VipRoutePredicateFactory

shortcutFieldOrder() 方法

spring:
  cloud:
    gateway:
      routes:
        - id: vip-route
          uri: https://example.com
          predicates:
            - name: Vip(RoutePredicateFactory)//vip是断言工厂名前缀
              args:
                param: q
                value: test

apply(Config config) 方法

这里的 Predicate<ServerWebExchange> 表示一个函数,它接收一个 ServerWebExchange(表示当前请求),并返回一个布尔值,表示该请求是否匹配该断言。

test(ServerWebExchange serverWebExchange) 方法

Config

四、过滤器

过滤器(Filters) 是用于在请求和响应过程中执行特定操作的机制。它们是在路由决策之前或之后执行的,可以对请求进行修改(如添加头部、修改请求体)或响应进行处理(如修改响应内容、记录日志等)。

过滤器的使用大致可以分为两种类型:前置过滤器(pre-filter)和后置过滤器(post-filter)。前置过滤器在请求到达目标服务之前执行,后置过滤器则在响应返回客户端之前执行。

过滤器主要用于以下目的:

4.1基本的过滤器使用步骤

添加依赖: 需要在pom.xml文件中加入Spring Cloud Gateway的依赖:

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>

创建过滤器: 可以通过实现GatewayFilter接口来创建自定义过滤器。Spring Cloud Gateway提供了GatewayFilter接口和GlobalFilter接口,分别用于处理特定路由和全局的请求过滤。

import org.springframework.cloud.gateway.filter.GatewayFilter;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

@Component
public class MyCustomFilter implements GatewayFilter {

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        // 在请求处理之前执行的逻辑
        System.out.println("请求被过滤: " + exchange.getRequest().getURI());

        // 执行后续过滤器链
        return chain.filter(exchange);
    }
}

注册过滤器: 自定义过滤器可以通过注入GatewayFilter的方式注册到Spring的上下文中。可以将过滤器注入到@Configuration中,或者直接使用@Component注解让其自动注册。

配置路由过滤器: 在路由配置中,可以为某个特定的路由设置过滤器。

spring:
  cloud:
    gateway:
      routes:
        - id: my_route
          uri: http://httpbin.org:80
          predicates:
            - Path=/get
          filters:
            - name: RequestHeaderToRequestUri
              args:
                name: X-Request-Id

4.2全局过滤器使用步骤

全局过滤器是应用于所有路由请求的过滤器,它们在请求到达目标服务之前和响应返回时都会被执行。全局过滤器对于记录日志、身份验证等场景非常有用。

import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;


@Component
public class LoggingGlobalFilter implements GlobalFilter {
    
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        // 记录请求的URL
        String path = exchange.getRequest().getURI().getPath();
        System.out.println("Request Path: " + path);
        
        // 继续处理链中的下一个过滤器
        return chain.filter(exchange);
    }
}

4.3自定义过滤器使用步骤

Spring Cloud Gateway允许开发者创建自定义过滤器。

自定义过滤器有两种类型:

import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.web.server.ServerWebExchange;
import org.springframework.http.HttpStatus;
import reactor.core.publisher.Mono;

@Component
public class LoggingGlobalFilter implements GlobalFilter {

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        // 获取请求的路径
        String path = exchange.getRequest().getURI().getPath();

        // 记录请求的路径
        System.out.println("Request Path: " + path);

        // 向请求中添加一个自定义的请求头
        exchange.getRequest().mutate()
                .header("X-Request-ID", "Request-" + System.currentTimeMillis())  // 设置一个自定义请求头
                .build();

        // 继续处理请求
        return chain.filter(exchange)
                .doOnTerminate(() -> {
                    // 记录响应结束时的日志
                    System.out.println("Request " + path + " processed.");
                });
    }
}

LoggingGlobalFilter 实现了 GlobalFilter 接口

该过滤器会应用于所有的请求,不管是哪个路由请求都会执行这个过滤器的逻辑。

filter() 方法

4.4过滤器的执行顺序

Spring Cloud Gateway的过滤器按以下顺序执行:

4.5常用过滤器

Spring Cloud Gateway提供了一些内置的过滤器,可以直接使用。例如:

添加请求头的过滤器举例:

spring:
  cloud:
    gateway:
      routes:
        - id: add-header-route
          uri: http://localhost:8081
          predicates:
            - Path=/add-header/**
          filters:
            - AddRequestHeader=X-Custom-Header, Value

总结

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

您可能感兴趣的文章:
阅读全文