RoutePredicateHandlerMapping#getHandlerInternal

webflux的入口是DispatcherHandler,他这里会调用HandlerMapping的getHandler方法。AbstractHandlerMapping实现了HandlerMapping接口,他有个抽象方法getHandlerInternal需要子类实现。
RoutePredicateHandlerMapping继承了AbstractHandlerMapping,所以我们的重点就是他的getHandlerInternal方法。这里面就是用来处理是否有对应的Route。
这个方法,其实主要调用lookupRoute方法。

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());

    return lookupRoute(exchange)
            // .log("route-predicate-handler-mapping", Level.FINER) //name this
            .flatMap((Function<Route, Mono<?>>) 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);
                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) + "]");
                }
            })));
}

RoutePredicateHandlerMapping#lookupRoute

我们可以看到他有个r.getPredicate().apply这样的代码,他这个apply最终会调用每个Predicate的test方法,返回false或者true。

protected Mono<Route> lookupRoute(ServerWebExchange exchange) {
    return this.routeLocator.getRoutes()
            // individually filter routes so that filterWhen error delaying is not a
            // problem
            .concatMap(route -> Mono.just(route).filterWhen(r -> {
                // add the current route we are testing
                exchange.getAttributes().put(GATEWAY_PREDICATE_ROUTE_ATTR, r.getId());
                return r.getPredicate().apply(exchange);
            })
    // 其他略        
}

DefaultAsyncPredicate#apply

在这里,会把每个Predicate的test方法调用过去。

public Publisher<Boolean> apply(T t) {
    return Mono.just(delegate.test(t));
}

FilteringWebHandler#handle

我们已经从上面的方法中拿到了一个Route(没有就不继续了),那就开始调用Filter。
DispatcherHandler在调用完handlerMappings后,会调用他的invokeHandler方法。

private Mono<HandlerResult> invokeHandler(ServerWebExchange exchange, Object handler) {
    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));
}

然后会调用webHandler.handle方法。

public Mono<HandlerResult> handle(ServerWebExchange exchange, Object handler) {
    WebHandler webHandler = (WebHandler) handler;
    Mono<Void> mono = webHandler.handle(exchange);
    return mono.then(Mono.empty());
}

我们的FilteringWebHandler就是一个WebHandler,我们看看他的handle方法。
他会先获取对应Route的Filters,再和通用的Filters合并排序,最后开始Filters的调用链。

public Mono<Void> handle(ServerWebExchange exchange) {
    // 获取Route
    Route route = exchange.getRequiredAttribute(GATEWAY_ROUTE_ATTR);
    // 取出Filters
    List<GatewayFilter> gatewayFilters = route.getFilters();
    // 加入通用的Filters
    List<GatewayFilter> combined = new ArrayList<>(this.globalFilters);
    combined.addAll(gatewayFilters);
    // TODO: needed or cached?
    // 排序
    AnnotationAwareOrderComparator.sort(combined);

    if (logger.isDebugEnabled()) {
        logger.debug("Sorted gatewayFilterFactories: " + combined);
    }
    // 调用链
    return new DefaultGatewayFilterChain(combined).filter(exchange);
}

整体流程

这边忽略了DispatcherHandler部分
image


大军
847 声望183 粉丝

学而不思则罔,思而不学则殆


« 上一篇
gateway - 启动
下一篇 »
gateway系列