⭐⭐⭐ Spring Boot 项目实战 ⭐⭐⭐ Spring Cloud 项目实战
《Dubbo 实现原理与源码解析 —— 精品合集》 《Netty 实现原理与源码解析 —— 精品合集》
《Spring 实现原理与源码解析 —— 精品合集》 《MyBatis 实现原理与源码解析 —— 精品合集》
《Spring MVC 实现原理与源码解析 —— 精品合集》 《数据库实体设计合集》
《Spring Boot 实现原理与源码解析 —— 精品合集》 《Java 面试题 + Java 学习指南》

摘要: 原创出处 http://www.iocoder.cn/Spring-Cloud-Gateway/route-locator-intro/ 「芋道源码」欢迎转载,保留摘要,谢谢!

本文主要基于 Spring-Cloud-Gateway 2.0.X M4


🙂🙂🙂关注**微信公众号:【芋道源码】**有福利:

  1. RocketMQ / MyCAT / Sharding-JDBC 所有源码分析文章列表
  2. RocketMQ / MyCAT / Sharding-JDBC 中文注释源码 GitHub 地址
  3. 您对于源码的疑问每条留言将得到认真回复。甚至不知道如何读源码也可以请教噢
  4. 新的源码解析文章实时收到通知。每周更新一篇左右
  5. 认真的源码交流微信群。

阅读源码最好的方式,是使用 IDEA 进行调试 Spring Cloud Gateway 源码,不然会一脸懵逼。

胖友可以点击「芋道源码」扫码关注,回复 git019 关键字
获得艿艿添加了中文注释的 Spring Cloud Gateway 源码地址。

阅读源码很孤单,加入源码交流群,一起坚持!

1. 概述

本文主要对 路由定位器 RouteLocator 做整体的认识

《Spring-Cloud-Gateway 源码解析 —— 路由(1.1)之 RouteDefinitionLocator 一览》 中,我们对 RouteLocator 对了简单的介绍 :

  • RouteLocator 可以直接自定义路由( org.springframework.cloud.gateway.route.Route ) ,也可以通过 RouteDefinitionRouteLocator 获取 RouteDefinition ,并转换成 Route 。
  • RoutePredicateHandlerMapping 使用 RouteLocator 获得 Route 信息。

推荐 Spring Cloud 书籍

2. Route

org.springframework.cloud.gateway.route.Route ,路由。代码如下 :

public class Route implements Ordered {

/**
* 路由编号
*/
private final String id;
/**
* 路由向的 URI
*/
private final URI uri;
/**
* 顺序
*/
private final int order;
/**
* 谓语数组
*/
private final Predicate<ServerWebExchange> predicate;
/**
* 过滤器数组
*/
private final List<GatewayFilter> gatewayFilters;
}

  • id 属性,ID 编号,唯一
  • predicates 属性,谓语数组。请求通过 predicates 判断是否匹配
  • filters 属性,过滤器数组。
  • uri 属性,路由向的 URI 。
  • order 属性,顺序。当请求匹配到多个路由时,使用顺序的。

Route 内置 Builder 类,点击 链接 查看。


Route 提供 routeDefinition RouteDefinition 创建对象,代码如下 :

public static Builder builder(RouteDefinition routeDefinition) {
return new Builder()
.id(routeDefinition.getId())
.uri(routeDefinition.getUri())
.order(routeDefinition.getOrder());
}

  • predicate / gatewayFilters 属性,需要调用 Builder 相关方法进行设置。

3. RouteLocator

org.springframework.cloud.gateway.route.RouteLocator ,路由定位器接口,定义获得路由数组的方法。代码如下 :

public interface RouteLocator {

Flux<Route> getRoutes();

}

  • 对 Reactor Flux 暂时不熟悉的同学,可以阅读完本文 Google 进行学习。随着 Spring 5 对响应式编程的推广,厉害如你一定要去掌握。

在上文中,我们也看到了 RouteLocator 的多个实现类,类图如下 :

  • 本文只解析 CompositeRouteLocator / CachingRouteLocator 的源码实现。其他的实现类会在后面文章详细解析。
  • 自定义的 RouteLocator ,通过内部类实现,类图暂时不好体现。

4. CompositeRouteLocator

org.springframework.cloud.gateway.route.CompositeRouteLocator ,组合多种 RouteLocator 的实现类,为 RoutePredicateHandlerMapping 提供统一入口访问路由。代码如下 :

public class CompositeRouteLocator implements RouteLocator {

private final Flux<RouteLocator> delegates;

public CompositeRouteLocator(Flux<RouteLocator> delegates) {
this.delegates = delegates;
}

@Override
public Flux<Route> getRoutes() {
return this.delegates.flatMap(RouteLocator::getRoutes);
}
}

  • #getRoutes() 方法,提供统一方法,将组合的 delegates 的路由全部返回。

5. CachingRouteLocator

org.springframework.cloud.gateway.route.CachingRouteLocator缓存路由的 RouteLocator 实现类。RoutePredicateHandlerMapping 调用 CachingRouteLocator 的 RouteLocator#getRoutes() 方法,获取路由。

CachingRouteLocator 代码如下 :

public class CachingRouteLocator implements RouteLocator {

private final RouteLocator delegate;
/**
* 路由缓存
*/
private final AtomicReference<List<Route>> cachedRoutes = new AtomicReference<>();

public CachingRouteLocator(RouteLocator delegate) {
this.delegate = delegate;
this.cachedRoutes.compareAndSet(null, collectRoutes());
}

@Override
public Flux<Route> getRoutes() {
return Flux.fromIterable(this.cachedRoutes.get());
}

/**
* Sets the new routes
* @return old routes
*/
public Flux<Route> refresh() {
return Flux.fromIterable(this.cachedRoutes.getAndUpdate(
routes -> CachingRouteLocator.this.collectRoutes()));
}

private List<Route> collectRoutes() {
List<Route> routes = this.delegate.getRoutes().collectList().block();
// 排序
AnnotationAwareOrderComparator.sort(routes);
return routes;
}

@EventListener(RefreshRoutesEvent.class)
/* for testing */ void handleRefresh() {
refresh();
}
}

  • cachedRoutes 属性,路由缓存
  • CachingRouteLocator 构造方法,调用 #collectRoutes() 方法获得路由,并缓存到 cachedRoutes 属性。
  • #collectRoutes() 方法,从 delegate 获取路由数组。
  • #getRoutes() 方法,返回路由缓存
  • #refresh() 方法,刷新缓存 cachedRoutes 属性。
  • #handleRefresh() 方法,监听 org.springframework.context.ApplicationEvent.RefreshRoutesEvent 事件,刷新缓存

GatewayWebfluxEndpoint 有一个 HTTP API 调用了 ApplicationEventPublisher ,发布 RefreshRoutesEvent 事件。代码如下 :

@RestController
@RequestMapping("${management.context-path:/application}/gateway")
public class GatewayWebfluxEndpoint implements ApplicationEventPublisherAware {

// ... 省略其他代码

/**
* 应用事件发布器
*/
private ApplicationEventPublisher publisher;

@PostMapping("/refresh")
public Mono<Void> refresh() {
this.publisher.publishEvent(new RefreshRoutesEvent(this));
return Mono.empty();
}

}

  • POST "/refresh ,发布 RefreshRoutesEvent 事件。CachingRouteLocator 监听到该事件,刷新缓存。

666. 彩蛋

知识星球

又是比较干爽( 水更 )的一篇文章。

胖友,分享一波朋友圈可好!

文章目录
  1. 1. 1. 概述
  2. 2. 2. Route
  3. 3. 3. RouteLocator
  4. 4. 4. CompositeRouteLocator
  5. 5. 5. CachingRouteLocator
  6. 6. 666. 彩蛋