IT俱乐部 Java SpringCloud Gateway DispatcherHandler调用方法详细介绍

SpringCloud Gateway DispatcherHandler调用方法详细介绍

前言

之前几节我们分析了请求是如何调用到HttpWebHandlerAdapter的,然后再调用到DispatcherHandler中,通过handle方法来处理具体的请求。

DispatcherHandler的注入在自动装配那一节已经说过了,忘记的同学可以重新会看一下。

DispatcherHandler类声明

1
public class DispatcherHandler implements WebHandler, PreFlightRequestHandler, ApplicationContextAware {

可以看到实现了ApplicationContextAware接口,并实现了setApplicationContext方法

1
2
3
4
@Override
public void setApplicationContext(ApplicationContext applicationContext) {
    initStrategies(applicationContext);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
protected void initStrategies(ApplicationContext context) {
    Map mappingBeans = BeanFactoryUtils.beansOfTypeIncludingAncestors(
            context, HandlerMapping.class, true, false);
    ArrayList mappings = new ArrayList(mappingBeans.values());
    AnnotationAwareOrderComparator.sort(mappings);
    this.handlerMappings = Collections.unmodifiableList(mappings);
    Map adapterBeans = BeanFactoryUtils.beansOfTypeIncludingAncestors(
            context, HandlerAdapter.class, true, false);
    this.handlerAdapters = new ArrayList(adapterBeans.values());
    AnnotationAwareOrderComparator.sort(this.handlerAdapters);
    Map beans = BeanFactoryUtils.beansOfTypeIncludingAncestors(
            context, HandlerResultHandler.class, true, false);
    this.resultHandlers = new ArrayList(beans.values());
    AnnotationAwareOrderComparator.sort(this.resultHandlers);
}

可以看到,这里初始化了核心的三部分内容,具体是handlerMappingshandlerAdaptersresultHandlers

通过名字我们可以猜想它们的具体作用,后面会详细解析

  • 通过handlerMappings确定具体处理网关请求的handler
  • 通过handlerAdapters确定具体支持处理handler的handlerAdapter,并处理handler。因为负责处理请求的方式不只一种,可以是注解的方法,也可以是函数式接口(lambda 表达式),也就是通过handlerMappings映射返回的对象是不一样的, 要把它们适配成统一的API。
  • 最终由resultHandler生成返回结果

handle方法

接下来我们来看下最核心的handle方法是如何具体处理请求的

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
@Override
public Mono handle(ServerWebExchange exchange) {
    if (this.handlerMappings == null) {
        return createNotFoundError();
    }
    if (CorsUtils.isPreFlightRequest(exchange.getRequest())) {
        return handlePreFlight(exchange);
    }
     //循环遍历所有的handlerMappings通过getHandler找到具体的handler
    return Flux.fromIterable(this.handlerMappings)
            .concatMap(mapping -> mapping.getHandler(exchange))
              //next方法表示如果循环遍历handlerMappings时有多个匹配的handler,通过next方法只取出第一个匹配的handler执行下面的调用方法
            .next()
            .switchIfEmpty(createNotFoundError())
               //处理具体的handler
            .flatMap(handler -> invokeHandler(exchange, handler))
               //处理结果
            .flatMap(result -> handleResult(exchange, result));
}

首先看getHandler方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
AbstractHandlerMapping.java
@Override
public Mono<object data-origwidth="" data-origheight="" style="width: 1264px;"> getHandler(ServerWebExchange exchange) {
    return getHandlerInternal(exchange).map(handler -> {
        if (logger.isDebugEnabled()) {
            logger.debug(exchange.getLogPrefix() + "Mapped to " + handler);
        }
        ServerHttpRequest request = exchange.getRequest();
        if (hasCorsConfigurationSource(handler) || CorsUtils.isPreFlightRequest(request)) {
            CorsConfiguration config = (this.corsConfigurationSource != null ?
                    this.corsConfigurationSource.getCorsConfiguration(exchange) : null);
            CorsConfiguration handlerConfig = getCorsConfiguration(handler, exchange);
            config = (config != null ? config.combine(handlerConfig) : handlerConfig);
            if (config != null) {
                config.validateAllowCredentials();
            }
            if (!this.corsProcessor.process(config, exchange) || CorsUtils.isPreFlightRequest(request)) {
                return NO_OP_HANDLER;
            }
        }
        return handler;
    });
}</object>

其中会调用getHandlerInternal方法,是一个抽象方法

1
protected abstract Mono> getHandlerInternal(ServerWebExchange exchange);

通过断点调试可以看到,其中handlerMappings一共有四个

getHandlerInternal方法具体实现

可以分别去每个实现方法中断点查看不难找到RoutePredicateHandlerMapping就是我们需要的,通过名字可以猜到就是用来处理路由转发的

找到它的getHandlerInternal实现方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
@Override
protected Mono> getHandlerInternal(ServerWebExchange exchange) {
    // don't handle requests on management port if set and different than server port
    if (this.managementPortType == DIFFERENT && this.managementPort != null
            && exchange.getRequest().getURI().getPort() == this.managementPort) {
        return Mono.empty();
    }
    exchange.getAttributes().put(GATEWAY_HANDLER_MAPPER_ATTR, getSimpleName());
    //lookupRoute方法将根据配置文件中指定的predicates断言器和请求路径做匹配,如果匹配成功就会返回FilteringWebHandler
    return lookupRoute(exchange)
            // .log("route-predicate-handler-mapping", Level.FINER) //name this
            .flatMap((Function>) r -> {
                exchange.getAttributes().remove(GATEWAY_PREDICATE_ROUTE_ATTR);
                if (logger.isDebugEnabled()) {
                    logger.debug("Mapping [" + getExchangeDesc(exchange) + "] to " + r);
                }
                exchange.getAttributes().put(GATEWAY_ROUTE_ATTR, r);
                  //上面定义的,private final FilteringWebHandler webHandler;
                return Mono.just(webHandler);
            }).switchIfEmpty(Mono.empty().then(Mono.fromRunnable(() -> {
                exchange.getAttributes().remove(GATEWAY_PREDICATE_ROUTE_ATTR);
                if (logger.isTraceEnabled()) {
                    logger.trace("No RouteDefinition found for [" + getExchangeDesc(exchange) + "]");
                }
            })));
}

lookupRoute关于路由相关的以后单独再讲,现在知道了返回的handler就是FilteringWebHandler

下面关注invokeHandler方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
private Mono invokeHandler(ServerWebExchange exchange, Object handler) {
    if (ObjectUtils.nullSafeEquals(exchange.getResponse().getStatusCode(), HttpStatus.FORBIDDEN)) {
        return Mono.empty();  // CORS rejection
    }
     //遍历所有的handlerAdapters找到能够支持当前handler的handlerAdapter,并执行handle方法
    if (this.handlerAdapters != null) {
        for (HandlerAdapter handlerAdapter : this.handlerAdapters) {
            if (handlerAdapter.supports(handler)) {
                return handlerAdapter.handle(exchange, handler);
            }
        }
    }
    return Mono.error(new IllegalStateException("No HandlerAdapter: " + handler));
}

可以看到supports方法具体有四个实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
@Override
public boolean supports(Object handler) {
    return handler instanceof HandlerFunction;
}
@Override
public boolean supports(Object handler) {
    return handler instanceof HandlerMethod;
}
@Override
public boolean supports(Object handler) {
    return WebHandler.class.isAssignableFrom(handler.getClass());
}
@Override
public boolean supports(Object handler) {
    return WebSocketHandler.class.isAssignableFrom(handler.getClass());
}

我们目前支持的就是WebHandler,也就是会执行SimpleHandlerAdapter中的handle方法

1
2
3
4
5
6
7
@Override
public Mono handle(ServerWebExchange exchange, Object handler) {
     //FilteringWebHandler
    WebHandler webHandler = (WebHandler) handler;
    Mono mono = webHandler.handle(exchange);
    return mono.then(Mono.empty());
}

之后会执行FilteringWebHandler的handle方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
@Override
public Mono handle(ServerWebExchange exchange) {
     //找到该请求对应的路由
    Route route = exchange.getRequiredAttribute(GATEWAY_ROUTE_ATTR);
     //找到该路由对应的GatewayFilter
    List gatewayFilters = route.getFilters();
    //得到全局的的GatewayFilter
    List combined = new ArrayList(this.globalFilters);
    combined.addAll(gatewayFilters);
    // TODO: needed or cached?
     //对全局过滤器和配置文件指定的路由局部过滤器统一排序
    AnnotationAwareOrderComparator.sort(combined);
 
    if (logger.isDebugEnabled()) {
        logger.debug("Sorted gatewayFilterFactories: " + combined);
    }
    //生成Gateway过滤器链,然后对客户端请求进行处理
    return new DefaultGatewayFilterChain(combined).filter(exchange);
}

首先先看一下FilteringWebHandler在哪被注入的,通过搜索发现在GatewayAutoConfiguration中注入的

1
2
3
4
@Bean
public FilteringWebHandler filteringWebHandler(List globalFilters) {
    return new FilteringWebHandler(globalFilters);
}

通过调试可以看到注入所有的GlobalFilter,默认有10个,并初始化

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public FilteringWebHandler(List globalFilters) {
    //初始化时加载所有全局过滤器,将他们适配为GatewayFilter类型,方便等会做合并
    this.globalFilters = loadFilters(globalFilters);
}
//适配器模式,通过嵌套把GlobalFilter封装成GatewayFilter类型
private static List loadFilters(List filters) {
    return filters.stream().map(filter -> {
         //GatewayFilterAdapter持有GlobalFilter对象
        GatewayFilterAdapter gatewayFilter = new GatewayFilterAdapter(filter);
        if (filter instanceof Ordered) {
              //将后续用来排序的order值传进来
            int order = ((Ordered) filter).getOrder();
              //OrderedGatewayFilter同样持有GatewayFilter对象
            return new OrderedGatewayFilter(gatewayFilter, order);
        }
        return gatewayFilter;
    }).collect(Collectors.toList());
}

至于这里为什么要返回两种不同的对象分别持有GatewayFilter,主要和后面的排序相关

对于实现了Ordered接口的filter会返回OrderedGatewayFilter对象

接着回到前面的handle方法中,其中有一步就是用来排序的

1
AnnotationAwareOrderComparator.sort(combined);

通过调试可以找到具体的实现在OrderComparator

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
@Override
public int compare(@Nullable Object o1, @Nullable Object o2) {
    return doCompare(o1, o2, null);
}
private int doCompare(@Nullable Object o1, @Nullable Object o2, @Nullable OrderSourceProvider sourceProvider) {
    //谁实现了PriorityOrdered接口就代表谁的优先级高
    boolean p1 = (o1 instanceof PriorityOrdered);
    boolean p2 = (o2 instanceof PriorityOrdered);
    if (p1 && !p2) {
        return -1;
    }
    else if (p2 && !p1) {
        return 1;
    }
    int i1 = getOrder(o1, sourceProvider);
    int i2 = getOrder(o2, sourceProvider);
    return Integer.compare(i1, i2);
}

如果都实现了PriorityOrdered接口或者都没有实现,那么通过getOrder方法得到的值来排序

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
private int getOrder(@Nullable Object obj, @Nullable OrderSourceProvider sourceProvider) {
    Integer order = null;
    if (obj != null && sourceProvider != null) {
        Object orderSource = sourceProvider.getOrderSource(obj);
        if (orderSource != null) {
            if (orderSource.getClass().isArray()) {
                for (Object source : ObjectUtils.toObjectArray(orderSource)) {
                    order = findOrder(source);
                    if (order != null) {
                        break;
                    }
                }
            }
            else {
                order = findOrder(orderSource);
            }
        }
    }
    return (order != null ? order : getOrder(obj));
}

传入的sourceProvider为null,最终调用另外一个getOrder方法

1
2
3
4
5
6
7
8
9
protected int getOrder(@Nullable Object obj) {
    if (obj != null) {
        Integer order = findOrder(obj);
        if (order != null) {
            return order;
        }
    }
    return Ordered.LOWEST_PRECEDENCE;
}

进入findOrder方法

1
2
3
4
@Nullable
protected Integer findOrder(Object obj) {
    return (obj instanceof Ordered ? ((Ordered) obj).getOrder() : null);
}

可以看到,如果实现了Ordered接口,则调用重写的getOrder方法,否则返回null,最后会返回

Ordered.LOWEST_PRECEDENCE,代表最低的优先级

1
int LOWEST_PRECEDENCE = Integer.MAX_VALUE;

后面通过Integer.compare方法来比较,值越大的优先级越低

最后总结一下

  • 谁实现了PriorityOrdered接口就代表谁的优先级高
  • 如果都没有实现或者都实现了,那么判断是否实现了Ordered接口
  • 如果实现了Ordered接口,那么返回实现方法中getOrder的值
  • 如果没有实现Ordered接口,那么返回最低的优先级也就是Integer的最大值
  • 最后在比较两个值的大小,值越大代表优先级越小,值越小代表优先级越大

到此这篇关于SpringCloud Gateway DispatcherHandler调用方法详细介绍的文章就介绍到这了,更多相关SpringCloud Gateway DispatcherHandler内容请搜索IT俱乐部以前的文章或继续浏览下面的相关文章希望大家以后多多支持IT俱乐部!

本文收集自网络,不代表IT俱乐部立场,转载请注明出处。https://www.2it.club/code/java/7267.html
上一篇
下一篇
联系我们

联系我们

在线咨询: QQ交谈

邮箱: 1120393934@qq.com

工作时间:周一至周五,9:00-17:30,节假日休息

关注微信
微信扫一扫关注我们

微信扫一扫关注我们

返回顶部