最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

SpringCloud?Gateway?DispatcherHandler調(diào)用方法詳細介紹

 更新時間:2022年10月21日 11:20:31   作者:Polarisy丶  
我們第一個關(guān)注的類就是DispatcherHandler,這個類提供的handle()方法,封裝了我們之后所有的handlerMappings,這個DispatcherHandler有點想SpringMVC的DispatchServlet,里面也是封裝了請求和對應(yīng)的處理方法的關(guān)系

前言

之前幾節(jié)我們分析了請求是如何調(diào)用到HttpWebHandlerAdapter的,然后再調(diào)用到DispatcherHandler中,通過handle方法來處理具體的請求。

DispatcherHandler的注入在自動裝配那一節(jié)已經(jīng)說過了,忘記的同學(xué)可以重新會看一下。

DispatcherHandler類聲明

public class DispatcherHandler implements WebHandler, PreFlightRequestHandler, ApplicationContextAware {

可以看到實現(xiàn)了ApplicationContextAware接口,并實現(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,handlerAdaptersresultHandlers

通過名字我們可以猜想它們的具體作用,后面會詳細解析

  • 通過handlerMappings確定具體處理網(wǎng)關(guān)請求的handler
  • 通過handlerAdapters確定具體支持處理handler的handlerAdapter,并處理handler。因為負責處理請求的方式不只一種,可以是注解的方法,也可以是函數(shù)式接口(lambda 表達式),也就是通過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ào)試可以看到,其中handlerMappings一共有四個

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

可以分別去每個實現(xiàn)方法中斷點查看不難找到RoutePredicateHandlerMapping就是我們需要的,通過名字可以猜到就是用來處理路由轉(zhuǎn)發(fā)的

找到它的getHandlerInternal實現(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)的以后單獨再講,現(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找到能夠支持當前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方法具體有四個實現(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過濾器鏈,然后對客戶端請求進行處理
		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,默認有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值傳進來
				int order = ((Ordered) filter).getOrder();
                  //OrderedGatewayFilter同樣持有GatewayFilter對象
				return new OrderedGatewayFilter(gatewayFilter, order);
			}
			return gatewayFilter;
		}).collect(Collectors.toList());
	}

至于這里為什么要返回兩種不同的對象分別持有GatewayFilter,主要和后面的排序相關(guān)

對于實現(xiàn)了Ordered接口的filter會返回OrderedGatewayFilter對象

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

AnnotationAwareOrderComparator.sort(combined);

通過調(diào)試可以找到具體的實現(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) {
        //誰實現(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);
	}

如果都實現(xiàn)了PriorityOrdered接口或者都沒有實現(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;
	}

進入findOrder方法

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

可以看到,如果實現(xiàn)了Ordered接口,則調(diào)用重寫的getOrder方法,否則返回null,最后會返回

Ordered.LOWEST_PRECEDENCE,代表最低的優(yōu)先級

int LOWEST_PRECEDENCE = Integer.MAX_VALUE;

后面通過Integer.compare方法來比較,值越大的優(yōu)先級越低

最后總結(jié)一下

  • 誰實現(xiàn)了PriorityOrdered接口就代表誰的優(yōu)先級高
  • 如果都沒有實現(xiàn)或者都實現(xiàn)了,那么判斷是否實現(xiàn)了Ordered接口
  • 如果實現(xiàn)了Ordered接口,那么返回實現(xiàn)方法中g(shù)etOrder的值
  • 如果沒有實現(xiàn)Ordered接口,那么返回最低的優(yōu)先級也就是Integer的最大值
  • 最后在比較兩個值的大小,值越大代表優(yōu)先級越小,值越小代表優(yōu)先級越大

到此這篇關(guān)于SpringCloud Gateway DispatcherHandler調(diào)用方法詳細介紹的文章就介紹到這了,更多相關(guān)SpringCloud Gateway DispatcherHandler內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • SpringBoot整合kaptcha驗證碼過程(復(fù)制粘貼即可用)

    SpringBoot整合kaptcha驗證碼過程(復(fù)制粘貼即可用)

    本文介紹了如何在Spring Boot項目中整合Kaptcha驗證碼實現(xiàn),通過配置和編寫相應(yīng)的Controller、工具類以及前端頁面,可以生成和驗證驗證碼,文中指出了在項目結(jié)構(gòu)上的注意事項,避免因包結(jié)構(gòu)問題導(dǎo)致驗證碼無法顯示
    2025-01-01
  • SpringBoot中定位切點的兩種常用方法

    SpringBoot中定位切點的兩種常用方法

    有時候,我們使用AOP來進行放的增強,編寫切面類的時候,需要定位在哪個方法上試用該切面進行增強,本片文章主要講解兩種在SpringBoot中定位切點的方法,感興趣的可以了解一下
    2021-06-06
  • Spring Boot中l(wèi)ombok的安裝與使用詳解

    Spring Boot中l(wèi)ombok的安裝與使用詳解

    這篇文章主要給大家介紹了關(guān)于Spring Boot中l(wèi)ombok安裝與使用的相關(guān)資料,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習或者工作具有一定的參考學(xué)習價值,需要的朋友們下面隨著小編來一起學(xué)習學(xué)習吧。
    2017-09-09
  • Java中Thread類基本用法詳解

    Java中Thread類基本用法詳解

    Java中的Thread類是用于創(chuàng)建和管理線程的類,Thread類提供了許多方法來管理線程,包括啟動線程、中斷線程、暫停線程等,下面這篇文章主要給大家介紹了關(guān)于Java中Thread類基本用法的相關(guān)資料,需要的朋友可以參考下
    2023-06-06
  • springboot開啟Bean數(shù)據(jù)校驗功能

    springboot開啟Bean數(shù)據(jù)校驗功能

    這篇文章主要介紹了springboot開啟Bean數(shù)據(jù)校驗功能,通過啟用Bean屬性校驗導(dǎo)入JSR303與Hibernate校驗框架坐標,使用@Validated注解啟用校驗功能,需要的朋友可以參考下
    2023-10-10
  • springboot2.x 接入阿里云市場短信發(fā)送的實現(xiàn)

    springboot2.x 接入阿里云市場短信發(fā)送的實現(xiàn)

    本文主要介紹了springboot2.x 接入阿里云市場短信發(fā)送的實現(xiàn),文中通過示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2021-11-11
  • java多線程數(shù)據(jù)分頁處理實例講解

    java多線程數(shù)據(jù)分頁處理實例講解

    在本篇內(nèi)容里小編給大家分享了一篇關(guān)于java多線程數(shù)據(jù)分頁處理實例講解內(nèi)容,有興趣的朋友們可以學(xué)習下。
    2021-01-01
  • Hibernate 與 Mybatis 的共存問題,打破你的認知!(兩個ORM框架)

    Hibernate 與 Mybatis 的共存問題,打破你的認知!(兩個ORM框架)

    這篇文章主要介紹了Hibernate 與 Mybatis 如何共存?本文給大家介紹的非常詳細,對大家的學(xué)習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2020-08-08
  • Java實現(xiàn)在線考試系統(tǒng)與設(shè)計(學(xué)生功能)

    Java實現(xiàn)在線考試系統(tǒng)與設(shè)計(學(xué)生功能)

    這篇文章主要介紹了Java實現(xiàn)在線考試系統(tǒng)與設(shè)計(學(xué)生功能),本文通過實例代碼給大家介紹的非常詳細,具有一定的參考借鑒價值,需要的朋友可以參考下
    2020-02-02
  • java如何自定義注解

    java如何自定義注解

    這篇文章主要介紹了java如何自定義注解問題,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2024-02-02

最新評論

剑川县| 许昌市| 买车| 高唐县| 永吉县| 聂拉木县| 阜康市| 浦东新区| 乌恰县| 民丰县| 清水河县| 辉县市| 辉县市| 宣化县| 赞皇县| 宣汉县| 泽普县| 乌审旗| 曲水县| 广东省| 肃宁县| 年辖:市辖区| 潼南县| 盱眙县| 广安市| 梁平县| 普兰县| 双辽市| 育儿| 原平市| 卫辉市| 无锡市| 武乡县| 灌阳县| 济宁市| 渝北区| 四川省| 永丰县| 闸北区| 文化| 竹北市|