版本

spring-cloud-starter-gateway 版本

  • 2021.0.2

背景

继上一次SpringCloud Gateway网关入门 现在我们来深入理解下spring cloud gateway(SCG)的一些核心概念。

后面我们都以SCG简称spring cloud gateway

理解了这些核心概念也就基本掌握了SCG

核心概念

上次我们配置了简单的路由转发功能
类似这样

spring:
  application:
    name: gate-way
  cloud:
    gateway:
      routes:
        - id: zou_route
          uri: http://localhost:10080
          predicates:
            - Path=/zou/**

然后网关就有了转发能力。我们今天就聊聊这几个配置具体配置了啥

GatewayProperties

不难发现我们配置了前缀为spring.cloud.gateway的配置,如果我们去源码里面搜索相关的key,就会找到GatewayProperties这个配置类

Spring Cloud Gateway 进行了两次转码导致get请求参数问题_spring

可以看到配置类中有两个非常核心的属性

  • List<RouteDefinition> routes
  • List<FilterDefinition> defaultFilters

RouteDefinition

RouteDefinition即路由定义,也就是我们在配置文件中配置的routes

RouteDefinition主要由4个属性组成

  • id
  • uri
  • 一组断言(predicates)
  • 一组过滤器(filters)

配置文件中我们都配置过

Spring Cloud Gateway 进行了两次转码导致get请求参数问题_1024程序员节_02

比较核心的就是下面这两个属性

  • List<PredicateDefinition> predicates
/**
 * 谓语定义,在 Route 里,PredicateDefinition 将转换成 Predicate
 */
@Validated
public class PredicateDefinition {
	/**
     * 谓语定义名字
     * 通过 name 对应到 org.springframework.cloud.gateway.handler.predicate.RoutePredicateFactory 的实现类。
     * 例如: name=Query 对应到 QueryRoutePredicateFactory
     */
    @NotNull
    private String name;

	/**
     * 参数数组
     * 例如,name=Host / args={"_genkey_0" : "iocoder.cn"} ,匹配请求的 hostname 为 iocoder.cn
     */
    private Map<String, String> args = new LinkedHashMap();

	...
}
  • List<FilterDefinition> filters
/**
 * 过滤器定义,在 Route 里,FilterDefinition将转换成 GatewayFilter
 */
@Validated
public class FilterDefinition {
	/**
     * 过滤器定义名字
     * 通过 name 对应到 org.springframework.cloud.gateway.filter.factory.GatewayFilterFactory 的实现类。
     * 例如,name=AddRequestParameter 对应到 AddRequestParameterGatewayFilterFactory
     */
    @NotNull
    private String name;

	/**
     * 参数数组
     * 例如 name=AddRequestParameter / args={"_genkey_0": "foo", "_genkey_1": "bar"} ,添加请求参数 foo 为 bar
     */
    private Map<String, String> args = new LinkedHashMap();

	...
}

SCG 目前内置了很多断言

Spring Cloud Gateway 进行了两次转码导致get请求参数问题_java_03

我们这里暂时不去分析PredicateDefinition是如何加载的,后面再去分析

SCG 也内置了许多过滤器(filter)

Spring Cloud Gateway 进行了两次转码导致get请求参数问题_spring cloud_04

总的来说核心定义就是如下图所示

Spring Cloud Gateway 进行了两次转码导致get请求参数问题_spring cloud_05

这里通过这张图就可以很清晰的理解为什么说SCG有两种过滤器,一种全局的、一种针对单个Route的

Route

上面都是一些定义,类似与Spring中的BeanDefinition,只是定义了Bean的一些属性,类似与元数据管理,并不是真正启作用的Bean,同样SCG里面也是如此,SCG里面核心其作用的其实是Route 可以理解为路由,路由的定义就是由上面那些定义出来的

比如我们通过配置文件yaml定义出一个RouteDefinition

spring:
  cloud:
    gateway:
      routes:
        - id: zou_route
          uri: http://localhost:10080
          predicates:
            - Path=/zou/**

也可以通过java Bean的方式去定义

@Bean
    public RouteLocator customRouteLocator(RouteLocatorBuilder builder) {
        return builder.routes()
                .route(r -> r.path("/zou/**")
                        .filters(f -> f.stripPrefix(2))
                        .uri("http://localhost:10080"))
                .build();
    }

我们查看RouteLocator接口会发现他只有一个方法就是获取路由

Spring Cloud Gateway 进行了两次转码导致get请求参数问题_1024程序员节_06

Spring Cloud Gateway 进行了两次转码导致get请求参数问题_spring_07

总结

这里我们主要介绍了SCG中的一些核心**Definition,后面我们将介绍这些**Definition是如何转换成真正起作用的Bean,即Route中的predicategatewayFilters