摘要: 原创出处 http://www.iocoder.cn/Spring-Cloud-Gateway/filter-forward-routing/ 「芋道源码」欢迎转载,保留摘要,谢谢!
本文主要基于 Spring-Cloud-Gateway 2.0.X M4
阅读源码最好的方式,是使用 IDEA 进行调试 Spring Cloud Gateway 源码,不然会一脸懵逼。
1. 概述
本文主要分享 ForwardRoutingFilter 的代码实现。
RouteToRequestUrlFilter ,转发路由网关过滤器。其根据 forward:// 前缀( Scheme )过滤处理,将请求转发到当前网关实例本地接口。
举个例子,配置 RouteDefinition 路由定义如下 :
spring:
application:
name: juejin-gateway
cloud:
gateway:
routes:
# =====================================
- id: forward_sample
uri: forward:///globalfilters
order: 10000
predicates:
- Path=/globalfilters
filters:
- PrefixPath=/application/gateway我们假定网关端口为
8080。当请求
http://127.0.0.1:8080/globalfilters接口,Spring Cloud Gateway 处理过程如下 :匹配到路由 Route (
id = forward_sample) 。配置的 PrefixPathGatewayFilterFactory 将请求改写成
http://127.0.0.1:8080/application/gateway/globalfilters。ForwardRoutingFilter 判断有
forward://前缀( Scheme ),过滤处理,将请求转发给 DispatcherHandler 。DispatcherHandler 匹配并转发到当前网关实例本地接口
application/gateway/globalfilters。
为什么需要配置 PrefixPathGatewayFilterFactory ?需要通过 PrefixPathGatewayFilterFactory 将请求重写路径,以匹配本地 API ,否则 DispatcherHandler 转发会失败。
另外,RouteToRequestUrlFilter 是 Spring Cloud Gateway 实现的一种路由网关过滤器,目前还提供 WebsocketRoutingFilter / NettyRoutingFilter / WebClientHttpRoutingFilter 。
推荐 Spring Cloud 书籍:
请支持正版。下载盗版,等于主动编写低级 BUG 。
程序猿DD —— 《Spring Cloud微服务实战》
两书齐买,京东包邮。
2. RouteToRequestUrlFilter
org.springframework.cloud.gateway.filter.ForwardRoutingFilter ,代码如下 :
public class ForwardRoutingFilter implements GlobalFilter, Ordered {
private static final Log log = LogFactory.getLog(ForwardRoutingFilter.class);
private final DispatcherHandler dispatcherHandler;
public ForwardRoutingFilter(DispatcherHandler dispatcherHandler) {
this.dispatcherHandler = dispatcherHandler;
}
@Override
public int getOrder() {
return Ordered.LOWEST_PRECEDENCE;
}
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
// 获得 requestUrl
URI requestUrl = exchange.getRequiredAttribute(GATEWAY_REQUEST_URL_ATTR);
// 判断是否能够处理
String scheme = requestUrl.getScheme();
if (isAlreadyRouted(exchange) || !scheme.equals("forward")) {
return chain.filter(exchange);
}
// 设置已经路由
setAlreadyRouted(exchange);
//TODO: translate url?
if (log.isTraceEnabled()) {
log.trace("Forwarding to URI: "+requestUrl);
}
// DispatcherHandler 匹配并转发到当前网关实例本地接口
return this.dispatcherHandler.handle(exchange);
}
}实现 GlobalFilter 接口。
#getOrder()方法,返回顺序为Integer.MAX_VALUE。在 《Spring-Cloud-Gateway 源码解析 —— 过滤器 (4.1) 之 GatewayFilter 一览》「3. GlobalFilter」 ,我们列举了所有 GlobalFilter 的顺序。第 19 行 :获得
requestUrl。第 22 至 25 行 :判断 ForwardRoutingFilter 是否能够处理该请求,需要满足两个条件 :
forward://前缀( Scheme ) 。调用
ServerWebExchangeUtils#isAlreadyRouted(ServerWebExchange)方法,判断该请求暂未被其他 Routing 网关处理。代码如下 :public static boolean isAlreadyRouted(ServerWebExchange exchange) { return exchange.getAttributeOrDefault(GATEWAY_ALREADY_ROUTED_ATTR, false); }x
第 28 行 :设置该请求已经被处理。代码如下 :
public static void setAlreadyRouted(ServerWebExchange exchange) { exchange.getAttributes().put(GATEWAY_ALREADY_ROUTED_ATTR, true); }第 37 行 :将请求转发给 DispatcherHandler 。DispatcherHandler 匹配并转发到当前网关实例本地接口。