本文使用 springcloud 版本为: 2020.0.5
本文只记录我读源码的过程。案例demo和某些名词可以到官网翻阅。
目录
2.7 RoutePredicateHandlerMapping
1、配置文件
spring gateway的初始化配置文件 spring.factories 在 spring-cloud-gateway-server的META-INF下。
根据springboot基础知识,我们知道当我们集成引用gateway后,会进行AutoConfiguration的加载。那么当有这么多configuration的时候,根据经验,我们先看以项目名命名的GatewayAutoConfiguration。
2、GatewayAutoConfiguration
2.1 Init Befor and After
2.1.1 AutoConfigureBefore
我们看到在gatewayAutoConfiguration的类上有一些注解,我们只看和初始化相关的
@AutoConfigureBefore({ HttpHandlerAutoConfiguration.class, WebFluxAutoConfiguration.class })
@AutoConfigureAfter({ GatewayReactiveLoadBalancerClientAutoConfiguration.class,
GatewayClassPathWarningAutoConfiguration.class })
Before就是指定当前类的加载需要在这两个类之前,虽然我们不知道这两个类具体是坐什么的,但是我们根据这两个类的包或者名字可以看出来是 WebFlux和Reactive相关的,这个要涉及到这块的一些基础知识,我只知道他是响应式编程,是和springMvc差不多的架构,而根据里面的配置其实就是初始化一些WebFlux框架相关的组件。例如一些HttpHandler,RequestMappingHandler等,这块我也不是很懂,就不误人子弟了。
2.1.2 AutoConfigureAfter
- GatewayClassPathWarningAutoConfiguration
这个类其实就是检查gateway所需要的组件环境的,gateway是基于webflux开发的,所以我们的环境内不能包含springmvc的东西。所以如果在项目中的某些依赖暗含了对spring-boot-starter-web的依赖,是需要排除依赖关系的。
- GatewayReactiveLoadBalancerClientAutoConfiguration
从名字就可以看出来这个是做负载均衡配置的,他After了 spring cloud的loadbalancer配置。而里面的两个初始化bean从名字看都是filter,都实现了GlobalFilter接口。而根据官网对此的解释如下:Spring Cloud Gateway
The
GlobalFilter
interface has the same signature asGatewayFilter
. These are special filters that are conditionally applied to all routes.
可以看到这是一个全局过滤器。而且和Gateway的filter可以组合起来用 order来决定执行顺序。从ReactiveLoadBalancerClientFilter内的filter执行逻辑来看,我先猜测他就是做负载均衡转换的,会转换lb开头的服务名到目前服务。
2.2 GatewayProperties
是解析我们在项目中配置文件定义的gateway配置的解析文件。当我们不知道都支持哪些配置或者配置支持哪些类型时,可以翻阅这个类来查看参考。比如 router路由配置,里面定义的是RouteDefinition,我们学过spring,根据Definition这个后缀就可以知道,这个和BeanDefinition原理是一样的,spring将配置解析到这个类里,然后由这个类做一些加工检查等最后生成相应的路由bean。其他的例如 FilterDefinition等原理一致。
下面看一些在autoConfiguration种初始化的主要bean。
2.3 RouteDefinitionLocator
我们刚刚说了RouteDefinition,而这个Locator我们可以点进去查看这个类的方法,只存在一个方法,就是获取 RouteDefinitions,所以我猜测它就是一个加工RouteDefinition并获取列表的服务类。
它的参数是一个同类型的列表,而这个类型我们可以根据IDEA工具查看它有哪些子类,可以按这些子类在查下,我们看到它的这些子类也大部分会被执行初始化bean的方法。例如:DiscoveryClientRouteDefinitionLocator是在GatewayDiscoveryClientAutoConfiguration内,InMemoryRouteDefinitionRepository就是在本gatewayAutoConfiguration中。
而返回值CompositeRouteDefinitionLocator,我们点进去看它的构造方法,可以看到它其实就是把构造参数集合内的属性都整合在一起,委派了内部的一个属性,并在接口方法getRouteDefinitions时进行了统一处理并返回。
2.4 RouteLocator
和上面方法一样,我们可以从名字以及查看返回值类内方法来判断,它是一个支持RouteDefinition转换成 Route的类。RouteDefinitionRouteLocator这个是它的实现类,可以看它的
getRoutes方法,它会将谓词,过滤器等Definition都转换成对应的目标类并设置进route的属性。
2.5 RouteRefreshListener
从名字上来看,这就是路由刷新的监听程序,ConditionalOnClass规定只有当我们引用了springcloud 的discovery服务发现时候才会进行初始化这个bean。listener会注册监听程序,监听ApplicationEvent,当有event进来会发布RefreshRoutesEvent,会有相应的监听程序来监听这个event并且执行相应的刷新操作。这个等后续写动态路由再写。
2.6 FilteringWebHandler
这个是核心的web处理类,它最终会糅合GlobalFilter和GatewayFilter组成过滤器链并排序后执行各过滤器逻辑。后续记录整体执行流程时就知道了。
构造方法:
public FilteringWebHandler(List<GlobalFilter> globalFilters) {
this.globalFilters = loadFilters(globalFilters);
}
private static List<GatewayFilter> loadFilters(List<GlobalFilter> filters) {
return filters.stream().map(filter -> {
//将globalFilter使用gatewayFilter适配器进行适配
GatewayFilterAdapter gatewayFilter = new GatewayFilterAdapter(filter);
//当是order子类时,使用order相关适配器适配返回,保证排序
if (filter instanceof Ordered) {
int order = ((Ordered) filter).getOrder();
return new OrderedGatewayFilter(gatewayFilter, order);
}
return gatewayFilter;
}).collect(Collectors.toList());
}
2.7 RoutePredicateHandlerMapping
这个类是当有请求进来后,会使用这个handlerMapping查找请求地址匹配哪些路由
2.8 其他
其他还有很多需要初始化的Bean,这些对象都是处理路由的具体Filter和Predicate,比如 处理AddRequestHeader的addRequestHeaderGatewayFilterFactory()方法,它对应的就是配置文件中:- AddRequestHeader=X-Request-red, blue 这部分。
而这些GatewayFilterFactory都最终实现了 GatewayFilterFactory类。那么这些factory是在哪里应用的呢?还记得我们之前的 RouteDefinitionRouteLocator 么,这个是构造最终路由的实现类。我们看到它的构造方法里有一个参数,是List<GatewayFilterFactory>,我们可以debug看看
正是我们想要查找的各种factory,这个类内有个属性gatewayFilterFactories,我们看代码它是将参数内的factory放到了这个属性内,它是一个HashMap,key就是factory的name,这个name就等于我们在application.yml中做的配置的key,例如AddRequestHeaderGatewayFilterFactory,它的name就是AddRequestHeader。这样我们就可以用routeDefinition中初始化的filter属性的key来寻找它应该由哪个filterFactory进行构造filter进行处理。
//参数id就是route配置的id,list<filterDefinition> 就是我们配置在route内的filter集合
List<GatewayFilter> loadGatewayFilters(String id, List<FilterDefinition> filterDefinitions) {
ArrayList<GatewayFilter> ordered = new ArrayList<>(filterDefinitions.size());
for (int i = 0; i < filterDefinitions.size(); i++) {
FilterDefinition definition = filterDefinitions.get(i);
//我们上面说了,factory的name就是我们配置的key,不然也对应不上
GatewayFilterFactory factory = this.gatewayFilterFactories.get(definition.getName());
if (factory == null) {
throw new IllegalArgumentException(
"Unable to find GatewayFilterFactory with name " + definition.getName());
}
if (logger.isDebugEnabled()) {
logger.debug("RouteDefinition " + id + " applying filter " + definition.getArgs() + " to "
+ definition.getName());
}
// @formatter:off
Object configuration = this.configurationService.with(factory)
.name(definition.getName())
.properties(definition.getArgs())
.eventFunction((bound, properties) -> new FilterArgsEvent(
// TODO: why explicit cast needed or java compile fails
RouteDefinitionRouteLocator.this, id, (Map<String, Object>) properties))
.bind();
// @formatter:on
// some filters require routeId
// TODO: is there a better place to apply this?
if (configuration instanceof HasRouteId) {
HasRouteId hasRouteId = (HasRouteId) configuration;
hasRouteId.setRouteId(id);
}
//这里转换成gatewayfilter并加入到排序集合内
GatewayFilter gatewayFilter = factory.apply(configuration);
if (gatewayFilter instanceof Ordered) {
ordered.add(gatewayFilter);
}
else {
ordered.add(new OrderedGatewayFilter(gatewayFilter, i + 1));
}
}
return ordered;
}