SpringCloud?Gateway?DispatcherHandler調(diào)用方法詳細(xì)介紹
前言
之前幾節(jié)我們分析了請求是如何調(diào)用到HttpWebHandlerAdapter的,然后再調(diào)用到DispatcherHandler中,通過handle方法來處理具體的請求。
DispatcherHandler的注入在自動裝配那一節(jié)已經(jīng)說過了,忘記的同學(xué)可以重新會看一下。
DispatcherHandler類聲明
public class DispatcherHandler implements WebHandler, PreFlightRequestHandler, ApplicationContextAware {
可以看到實(shí)現(xiàn)了ApplicationContextAware接口,并實(shí)現(xiàn)了setApplicationContext方法
@Override
public void setApplicationContext(ApplicationContext applicationContext) {
initStrategies(applicationContext);
}
protected void initStrategies(ApplicationContext context) {
Map<String, HandlerMapping> mappingBeans = BeanFactoryUtils.beansOfTypeIncludingAncestors(
context, HandlerMapping.class, true, false);
ArrayList<HandlerMapping> mappings = new ArrayList<>(mappingBeans.values());
AnnotationAwareOrderComparator.sort(mappings);
this.handlerMappings = Collections.unmodifiableList(mappings);
Map<String, HandlerAdapter> adapterBeans = BeanFactoryUtils.beansOfTypeIncludingAncestors(
context, HandlerAdapter.class, true, false);
this.handlerAdapters = new ArrayList<>(adapterBeans.values());
AnnotationAwareOrderComparator.sort(this.handlerAdapters);
Map<String, HandlerResultHandler> beans = BeanFactoryUtils.beansOfTypeIncludingAncestors(
context, HandlerResultHandler.class, true, false);
this.resultHandlers = new ArrayList<>(beans.values());
AnnotationAwareOrderComparator.sort(this.resultHandlers);
}可以看到,這里初始化了核心的三部分內(nèi)容,具體是handlerMappings,handlerAdapters,resultHandlers
通過名字我們可以猜想它們的具體作用,后面會詳細(xì)解析
- 通過handlerMappings確定具體處理網(wǎng)關(guān)請求的handler
- 通過handlerAdapters確定具體支持處理handler的handlerAdapter,并處理handler。因?yàn)樨?fù)責(zé)處理請求的方式不只一種,可以是注解的方法,也可以是函數(shù)式接口(lambda 表達(dá)式),也就是通過handlerMappings映射返回的對象是不一樣的, 要把它們適配成統(tǒng)一的API。
- 最終由resultHandler生成返回結(jié)果
handle方法
接下來我們來看下最核心的handle方法是如何具體處理請求的
@Override
public Mono<Void> handle(ServerWebExchange exchange) {
if (this.handlerMappings == null) {
return createNotFoundError();
}
if (CorsUtils.isPreFlightRequest(exchange.getRequest())) {
return handlePreFlight(exchange);
}
//循環(huán)遍歷所有的handlerMappings通過getHandler找到具體的handler
return Flux.fromIterable(this.handlerMappings)
.concatMap(mapping -> mapping.getHandler(exchange))
//next方法表示如果循環(huán)遍歷handlerMappings時有多個匹配的handler,通過next方法只取出第一個匹配的handler執(zhí)行下面的調(diào)用方法
.next()
.switchIfEmpty(createNotFoundError())
//處理具體的handler
.flatMap(handler -> invokeHandler(exchange, handler))
//處理結(jié)果
.flatMap(result -> handleResult(exchange, result));
}首先看getHandler方法
AbstractHandlerMapping.java
@Override
public Mono<Object> 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;
});
}其中會調(diào)用getHandlerInternal方法,是一個抽象方法
protected abstract Mono<?> getHandlerInternal(ServerWebExchange exchange);
通過斷點(diǎn)調(diào)試可以看到,其中handlerMappings一共有四個

getHandlerInternal方法具體實(shí)現(xiàn)

可以分別去每個實(shí)現(xiàn)方法中斷點(diǎn)查看不難找到RoutePredicateHandlerMapping就是我們需要的,通過名字可以猜到就是用來處理路由轉(zhuǎn)發(fā)的
找到它的getHandlerInternal實(shí)現(xiàn)方法
@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方法將根據(jù)配置文件中指定的predicates斷言器和請求路徑做匹配,如果匹配成功就會返回FilteringWebHandler
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);
//上面定義的,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關(guān)于路由相關(guān)的以后單獨(dú)再講,現(xiàn)在知道了返回的handler就是FilteringWebHandler
下面關(guān)注invokeHandler方法
private Mono<HandlerResult> invokeHandler(ServerWebExchange exchange, Object handler) {
if (ObjectUtils.nullSafeEquals(exchange.getResponse().getStatusCode(), HttpStatus.FORBIDDEN)) {
return Mono.empty(); // CORS rejection
}
//遍歷所有的handlerAdapters找到能夠支持當(dāng)前handler的handlerAdapter,并執(zhí)行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方法具體有四個實(shí)現(xiàn)
@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,也就是會執(zhí)行SimpleHandlerAdapter中的handle方法
@Override
public Mono<HandlerResult> handle(ServerWebExchange exchange, Object handler) {
//FilteringWebHandler
WebHandler webHandler = (WebHandler) handler;
Mono<Void> mono = webHandler.handle(exchange);
return mono.then(Mono.empty());
}之后會執(zhí)行FilteringWebHandler的handle方法
@Override
public Mono<Void> handle(ServerWebExchange exchange) {
//找到該請求對應(yīng)的路由
Route route = exchange.getRequiredAttribute(GATEWAY_ROUTE_ATTR);
//找到該路由對應(yīng)的GatewayFilter
List<GatewayFilter> gatewayFilters = route.getFilters();
//得到全局的的GatewayFilter
List<GatewayFilter> combined = new ArrayList<>(this.globalFilters);
combined.addAll(gatewayFilters);
// TODO: needed or cached?
//對全局過濾器和配置文件指定的路由局部過濾器統(tǒng)一排序
AnnotationAwareOrderComparator.sort(combined);
if (logger.isDebugEnabled()) {
logger.debug("Sorted gatewayFilterFactories: " + combined);
}
//生成Gateway過濾器鏈,然后對客戶端請求進(jìn)行處理
return new DefaultGatewayFilterChain(combined).filter(exchange);
}首先先看一下FilteringWebHandler在哪被注入的,通過搜索發(fā)現(xiàn)在GatewayAutoConfiguration中注入的
@Bean
public FilteringWebHandler filteringWebHandler(List<GlobalFilter> globalFilters) {
return new FilteringWebHandler(globalFilters);
}通過調(diào)試可以看到注入所有的GlobalFilter,默認(rèn)有10個,并初始化


public FilteringWebHandler(List<GlobalFilter> globalFilters) {
//初始化時加載所有全局過濾器,將他們適配為GatewayFilter類型,方便等會做合并
this.globalFilters = loadFilters(globalFilters);
}
//適配器模式,通過嵌套把GlobalFilter封裝成GatewayFilter類型
private static List<GatewayFilter> loadFilters(List<GlobalFilter> filters) {
return filters.stream().map(filter -> {
//GatewayFilterAdapter持有GlobalFilter對象
GatewayFilterAdapter gatewayFilter = new GatewayFilterAdapter(filter);
if (filter instanceof Ordered) {
//將后續(xù)用來排序的order值傳進(jìn)來
int order = ((Ordered) filter).getOrder();
//OrderedGatewayFilter同樣持有GatewayFilter對象
return new OrderedGatewayFilter(gatewayFilter, order);
}
return gatewayFilter;
}).collect(Collectors.toList());
}至于這里為什么要返回兩種不同的對象分別持有GatewayFilter,主要和后面的排序相關(guān)
對于實(shí)現(xiàn)了Ordered接口的filter會返回OrderedGatewayFilter對象
接著回到前面的handle方法中,其中有一步就是用來排序的
AnnotationAwareOrderComparator.sort(combined);
通過調(diào)試可以找到具體的實(shí)現(xiàn)在OrderComparator中
@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) {
//誰實(shí)現(xiàn)了PriorityOrdered接口就代表誰的優(yōu)先級高
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);
}如果都實(shí)現(xiàn)了PriorityOrdered接口或者都沒有實(shí)現(xiàn),那么通過getOrder方法得到的值來排序
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,最終調(diào)用另外一個getOrder方法
protected int getOrder(@Nullable Object obj) {
if (obj != null) {
Integer order = findOrder(obj);
if (order != null) {
return order;
}
}
return Ordered.LOWEST_PRECEDENCE;
}進(jìn)入findOrder方法
@Nullable
protected Integer findOrder(Object obj) {
return (obj instanceof Ordered ? ((Ordered) obj).getOrder() : null);
}可以看到,如果實(shí)現(xiàn)了Ordered接口,則調(diào)用重寫的getOrder方法,否則返回null,最后會返回
Ordered.LOWEST_PRECEDENCE,代表最低的優(yōu)先級
int LOWEST_PRECEDENCE = Integer.MAX_VALUE;
后面通過Integer.compare方法來比較,值越大的優(yōu)先級越低
最后總結(jié)一下
- 誰實(shí)現(xiàn)了
PriorityOrdered接口就代表誰的優(yōu)先級高 - 如果都沒有實(shí)現(xiàn)或者都實(shí)現(xiàn)了,那么判斷是否實(shí)現(xiàn)了
Ordered接口 - 如果實(shí)現(xiàn)了
Ordered接口,那么返回實(shí)現(xiàn)方法中g(shù)etOrder的值 - 如果沒有實(shí)現(xiàn)
Ordered接口,那么返回最低的優(yōu)先級也就是Integer的最大值 - 最后在比較兩個值的大小,值越大代表優(yōu)先級越小,值越小代表優(yōu)先級越大
到此這篇關(guān)于SpringCloud Gateway DispatcherHandler調(diào)用方法詳細(xì)介紹的文章就介紹到這了,更多相關(guān)SpringCloud Gateway DispatcherHandler內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
json序列化時忽略值為null的字段2種方式實(shí)例
這篇文章主要給大家介紹了關(guān)于json序列化時忽略值為null的字段的2種方式,當(dāng)對象中某個字段為null時,我們希望將對象轉(zhuǎn)換成json時為null的字段不會被轉(zhuǎn)換到j(luò)son字符串,里面需要的朋友可以參考下2023-10-10
解析SpringSecurity+JWT認(rèn)證流程實(shí)現(xiàn)
這篇文章主要介紹了解析SpringSecurity+JWT認(rèn)證流程實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-07-07
WebUploader客戶端批量上傳圖片 后臺使用springMVC
這篇文章主要為大家詳細(xì)介紹了WebUploader客戶端批量上傳圖片,后臺使用springMVC接收實(shí)例,具有一定的參考價值,感興趣的小伙伴們可以參考一下2018-09-09
Java8 CompletableFuture 異步執(zhí)行操作
CompletableFuture是java8提供的基于異步操作的封裝,日常開發(fā)中經(jīng)常會用到,接下來通過本文給大家介紹Java8 CompletableFuture 異步執(zhí)行操作,感興趣的朋友一起看看吧2021-06-06

