SpringCloud Gateway自動(dòng)裝配實(shí)現(xiàn)流程詳解
啟動(dòng)依賴
找到gateway的依賴,spring-cloud-starter-gateway
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-gateway</artifactId> </dependency>
點(diǎn)進(jìn)去之后找到它的依賴
<dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter</artifactId> <version>3.1.1</version> <scope>compile</scope> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-gateway-server</artifactId> <version>3.1.1</version> <scope>compile</scope> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-webflux</artifactId> <version>2.6.3</version> <scope>compile</scope> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-loadbalancer</artifactId> <version>3.1.1</version> <scope>compile</scope> <optional>true</optional> </dependency> </dependencies>
從名稱上可以判斷spring-cloud-gateway-server是gateway的核心依賴,找到依賴包,看到如下結(jié)構(gòu)
spring.factories是一些自動(dòng)裝配的類,如下可以看到
# Auto Configure
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.springframework.cloud.gateway.config.GatewayClassPathWarningAutoConfiguration,\
org.springframework.cloud.gateway.config.GatewayAutoConfiguration,\
org.springframework.cloud.gateway.config.GatewayResilience4JCircuitBreakerAutoConfiguration,\
org.springframework.cloud.gateway.config.GatewayNoLoadBalancerClientAutoConfiguration,\
org.springframework.cloud.gateway.config.GatewayMetricsAutoConfiguration,\
org.springframework.cloud.gateway.config.GatewayRedisAutoConfiguration,\
org.springframework.cloud.gateway.discovery.GatewayDiscoveryClientAutoConfiguration,\
org.springframework.cloud.gateway.config.SimpleUrlHandlerMappingGlobalCorsAutoConfiguration,\
org.springframework.cloud.gateway.config.GatewayReactiveLoadBalancerClientAutoConfiguration,\
org.springframework.cloud.gateway.config.GatewayReactiveOAuth2AutoConfigurationorg.springframework.boot.env.EnvironmentPostProcessor=\
org.springframework.cloud.gateway.config.GatewayEnvironmentPostProcessor# Failure Analyzers
org.springframework.boot.diagnostics.FailureAnalyzer=\
org.springframework.cloud.gateway.support.MvcFoundOnClasspathFailureAnalyzer
其中比較重要的是GatewayAutoConfiguration,負(fù)責(zé)很多bean的初始化,類聲明如下:
@Configuration(proxyBeanMethods = false) @ConditionalOnProperty(name = "spring.cloud.gateway.enabled", matchIfMissing = true) @EnableConfigurationProperties @AutoConfigureBefore({ HttpHandlerAutoConfiguration.class, WebFluxAutoConfiguration.class }) @AutoConfigureAfter({ GatewayReactiveLoadBalancerClientAutoConfiguration.class, GatewayClassPathWarningAutoConfiguration.class }) @ConditionalOnClass(DispatcherHandler.class) public class GatewayAutoConfiguration {
@AutoConfigureBefore
和@AutoConfigureAfter
分別是在之前和之后加載
其中HttpHandlerAutoConfiguration
和WebFluxAutoConfiguration
算是比較重要的裝配類
WebFluxAutoConfiguration
先看WebFluxAutoConfiguration,類聲明如下:
@Configuration(proxyBeanMethods = false) @ConditionalOnWebApplication(type = ConditionalOnWebApplication.Type.REACTIVE) @ConditionalOnClass(WebFluxConfigurer.class) @ConditionalOnMissingBean({ WebFluxConfigurationSupport.class }) @AutoConfigureAfter({ ReactiveWebServerFactoryAutoConfiguration.class, CodecsAutoConfiguration.class, ReactiveMultipartAutoConfiguration.class, ValidationAutoConfiguration.class, WebSessionIdResolverAutoConfiguration.class }) @AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE + 10) public class WebFluxAutoConfiguration {
其中部分代碼如下:
@Configuration(proxyBeanMethods = false) @EnableConfigurationProperties({ WebProperties.class, WebFluxProperties.class }) @Import({ EnableWebFluxConfiguration.class }) @Order(0) public static class WebFluxConfig implements WebFluxConfigurer {
可以看到通過(guò)WebFluxAutoConfiguration 通過(guò) WebFluxConfig 導(dǎo)入了 EnableWebFluxConfiguration
@Configuration(proxyBeanMethods = false) @EnableConfigurationProperties({ WebProperties.class, ServerProperties.class }) public static class EnableWebFluxConfiguration extends DelegatingWebFluxConfiguration {
EnableWebFluxConfiguration繼承于DelegatingWebFluxConfiguration
@Configuration(proxyBeanMethods = false) public class DelegatingWebFluxConfiguration extends WebFluxConfigurationSupport {
DelegatingWebFluxConfiguration又繼承于WebFluxConfigurationSupport
在WebFluxConfigurationSupport中可以看到很熟悉的東西
@Bean public DispatcherHandler webHandler() { //BeanName為webHandler return new DispatcherHandler(); }
有點(diǎn)聯(lián)想到DispatcherSerlvet
,類似前端控制器
public class DispatcherHandler implements WebHandler, PreFlightRequestHandler, ApplicationContextAware {<!--{cke_protected}{C}%3C!%2D%2D%20%2D%2D%3E-->
可以看到DispatcherHandler
實(shí)現(xiàn)了WebHandler接口并實(shí)現(xiàn)了其中的handle
方法
public interface WebHandler { /** * Handle the web server exchange. * @param exchange the current server exchange * @return {@code Mono<Void>} to indicate when request handling is complete */ Mono<Void> handle(ServerWebExchange exchange); }
可以猜到handle
應(yīng)該就是核心的處理方法,此時(shí)又有疑問(wèn),該方法什么時(shí)候被調(diào)用,被誰(shuí)調(diào)用的
官方文檔上提到WebHandler
上面還有一個(gè)關(guān)鍵的 API HttpHandler
For server request processing there are two levels of support.
HttpHandler: Basic contract for HTTP request handling with non-blocking I/O and Reactive Streams back pressure, along with adapters for Reactor Netty, Undertow, Tomcat, Jetty, and any Servlet 3.1+ container.
WebHandler API: Slightly higher level, general-purpose web API for request handling, on top of which concrete programming models such as annotated controllers and functional endpoints are built.
從上面的英文可以看到 HttpHandler
是比 WebHandler
更加底層的一個(gè) API,也就是說(shuō)很可能是由 HttpHandler 來(lái)調(diào)用 WebHandler (請(qǐng)求由下往上),那DispatcherHandler
作為 WebHandler
的一個(gè)實(shí)現(xiàn),也很有可能會(huì)被HttpHandler
的具體實(shí)現(xiàn)所持有。
通過(guò)HttpHandler
的實(shí)現(xiàn)類不難找到HttpWebHandlerAdapter
就是我們要找的,并且持有一個(gè)WebHandher
對(duì)象,當(dāng)然也可以通過(guò)斷點(diǎn)調(diào)試找到。
public class HttpWebHandlerAdapter extends WebHandlerDecorator implements HttpHandler {<!--{cke_protected}{C}%3C!%2D%2D%20%2D%2D%3E-->
HttpWebHandlerAdapter
繼承于WebHandlerDecorator
public class WebHandlerDecorator implements WebHandler { private final WebHandler delegate; /** * Return the wrapped delegate. */ public WebHandler getDelegate() { return this.delegate; }
可以看到WebHandlerDecorator持有WebHandler對(duì)象
總之,我們找到了調(diào)用 DispatcherHandher 的地方了,那下一步我們要找 HttpWebHandlerAdapter 是在哪里被裝配的,并且webHandler 是是什么時(shí)候被注入的,注入的 webHandler 是否就是 DispatcherHandler?
HttpHandlerAutoConfiguration
前面說(shuō)過(guò)的另外一個(gè)裝配類HttpHandlerAutoConfiguration
@Configuration(proxyBeanMethods = false) @ConditionalOnClass({ DispatcherHandler.class, HttpHandler.class }) @ConditionalOnWebApplication(type = ConditionalOnWebApplication.Type.REACTIVE) @ConditionalOnMissingBean(HttpHandler.class) @AutoConfigureAfter({ WebFluxAutoConfiguration.class }) @AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE + 10) public class HttpHandlerAutoConfiguration { @Configuration(proxyBeanMethods = false) public static class AnnotationConfig { private final ApplicationContext applicationContext; public AnnotationConfig(ApplicationContext applicationContext) { this.applicationContext = applicationContext; } @Bean public HttpHandler httpHandler(ObjectProvider<WebFluxProperties> propsProvider) { HttpHandler httpHandler = WebHttpHandlerBuilder.applicationContext(this.applicationContext).build(); WebFluxProperties properties = propsProvider.getIfAvailable(); if (properties != null && StringUtils.hasText(properties.getBasePath())) { Map<String, HttpHandler> handlersMap = Collections.singletonMap(properties.getBasePath(), httpHandler); return new ContextPathCompositeHandler(handlersMap); } return httpHandler; } } }
可以看到這里注入了一個(gè)HttpHandler
對(duì)象,難道就是HttpWebHandlerAdapter
,繼續(xù)往下看
首先調(diào)用了WebHttpHandlerBuilder.applicationContext(this.applicationContext)方法,點(diǎn)進(jìn)去看
public static WebHttpHandlerBuilder applicationContext(ApplicationContext context) { WebHttpHandlerBuilder builder = new WebHttpHandlerBuilder( context.getBean(WEB_HANDLER_BEAN_NAME, WebHandler.class), context); ...... return builder;
可以看到通過(guò)context上下文對(duì)象通過(guò)beanName獲取bean來(lái)作為參數(shù)初始化WebHttpHandlerBuilder對(duì)象
/** Well-known name for the target WebHandler in the bean factory. */ public static final String WEB_HANDLER_BEAN_NAME = "webHandler";
而這個(gè)beanName正式前面說(shuō)過(guò)的DispatcherHandler
對(duì)象
private WebHttpHandlerBuilder(WebHandler webHandler, @Nullable ApplicationContext applicationContext) { Assert.notNull(webHandler, "WebHandler must not be null"); this.webHandler = webHandler; this.applicationContext = applicationContext; }
將WebHttpHandlerBuilder
中的webHandler
屬性賦值為DispatcherHandler
對(duì)象
接著進(jìn)入build()方法,整體可以看到返回的HttpHandler對(duì)象就是HttpWebHandlerAdapter
public HttpHandler build() { WebHandler decorated = new FilteringWebHandler(this.webHandler, this.filters); decorated = new ExceptionHandlingWebHandler(decorated, this.exceptionHandlers); HttpWebHandlerAdapter adapted = new HttpWebHandlerAdapter(decorated); if (this.sessionManager != null) { adapted.setSessionManager(this.sessionManager); } if (this.codecConfigurer != null) { adapted.setCodecConfigurer(this.codecConfigurer); } if (this.localeContextResolver != null) { adapted.setLocaleContextResolver(this.localeContextResolver); } if (this.forwardedHeaderTransformer != null) { adapted.setForwardedHeaderTransformer(this.forwardedHeaderTransformer); } if (this.applicationContext != null) { adapted.setApplicationContext(this.applicationContext); } adapted.afterPropertiesSet(); return (this.httpHandlerDecorator != null ? this.httpHandlerDecorator.apply(adapted) : adapted); }
首先看第一行
//這里的webHandler就是DispatcherHandler對(duì)象 WebHandler decorated = new FilteringWebHandler(this.webHandler, this.filters);
public FilteringWebHandler(WebHandler handler, List<WebFilter> filters) { super(handler); this.chain = new DefaultWebFilterChain(handler, filters); }
調(diào)用父類的構(gòu)造方法
private final WebHandler delegate; public WebHandlerDecorator(WebHandler delegate) { Assert.notNull(delegate, "'delegate' must not be null"); this.delegate = delegate; }
此時(shí)將delegate賦值為DispatcherHandler對(duì)象
接著第二行
//此時(shí)入?yún)⒅械膁ecorated是FilteringWebHandler對(duì)象 decorated = new ExceptionHandlingWebHandler(decorated, this.exceptionHandlers);
public ExceptionHandlingWebHandler(WebHandler delegate, List<WebExceptionHandler> handlers) { super(delegate); List<WebExceptionHandler> handlersToUse = new ArrayList<>(); handlersToUse.add(new CheckpointInsertingHandler()); handlersToUse.addAll(handlers); this.exceptionHandlers = Collections.unmodifiableList(handlersToUse); }
再次調(diào)用父類的構(gòu)造方法將此對(duì)象的父類中delegate屬性賦值為FilteringWebHandler對(duì)象
接著第三行
HttpWebHandlerAdapter adapted = new HttpWebHandlerAdapter(decorated);
public HttpWebHandlerAdapter(WebHandler delegate) { super(delegate); }
一樣的道理將父類中delegate屬性賦值為ExceptionHandlingWebHandler對(duì)象
總結(jié)一下
HttpWebHandlerAdapter
中delegate保存的是ExceptionHandlingWebHandler
ExceptionHandlingWebHandler
中的delegate保存的是FilteringWebHandler
FilteringWebHandler
中的delegate保存的是DispatcherHandler
到此這篇關(guān)于SpringCloud Gateway自動(dòng)裝配實(shí)現(xiàn)流程詳解的文章就介紹到這了,更多相關(guān)SpringCloud Gateway內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- SpringCloud Gateway動(dòng)態(tài)路由配置詳解
- SpringCloud Gateway路由組件詳解
- SpringCloud Gateway的路由,過(guò)濾器和限流解讀
- SpringCloud Gateway網(wǎng)關(guān)功能介紹與使用
- SpringCloud Gateway實(shí)現(xiàn)限流功能詳解
- SpringCloud服務(wù)網(wǎng)關(guān)Gateway的使用教程詳解
- SpringCloud中Gateway的使用教程詳解
- SpringCloud超詳細(xì)講解微服務(wù)網(wǎng)關(guān)Gateway
- SpringCloud Gateway動(dòng)態(tài)轉(zhuǎn)發(fā)后端服務(wù)實(shí)現(xiàn)過(guò)程講解
相關(guān)文章
java 靜態(tài)鏈表實(shí)現(xiàn)示例詳解
這篇文章主要為大家介紹了java 靜態(tài)鏈表實(shí)現(xiàn)示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-06-06Java Socket實(shí)現(xiàn)單線程通信的方法示例
這篇文章主要介紹了Java Socket實(shí)現(xiàn)單線程通信的方法,結(jié)合具體實(shí)例形式分析了java socket單線程通信的原理與客戶端、服務(wù)器端相關(guān)實(shí)現(xiàn)技巧,需要的朋友可以參考下2017-06-06Java8 Collectors求和功能的自定義擴(kuò)展操作
這篇文章主要介紹了Java8 Collectors求和功能的自定義擴(kuò)展操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2021-02-02Android讀取本地或網(wǎng)絡(luò)圖片并轉(zhuǎn)換為Bitmap
這篇文章主要為大家詳細(xì)介紹了Android讀取本地或網(wǎng)絡(luò)圖片,并轉(zhuǎn)換為Bitmap,感興趣的小伙伴們可以參考一下2016-08-08在Spring Boot中處理文件上傳功能實(shí)現(xiàn)
這篇文章主要介紹了如何在Spring Boot中處理文件上傳,通過(guò)配置文件上傳屬性、創(chuàng)建控制器來(lái)處理上傳的文件,并通過(guò)異常處理器來(lái)管理錯(cuò)誤情況,可以快速實(shí)現(xiàn)文件上傳功能,需要的朋友可以參考下2024-06-06SpringBoot+WebSocket實(shí)現(xiàn)IM及時(shí)通訊的代碼示例
項(xiàng)目中碰到需要及時(shí)通訊的場(chǎng)景,使用springboot集成websocket,即可實(shí)現(xiàn)簡(jiǎn)單的及時(shí)通訊,本文介紹springboot如何集成websocket、IM及時(shí)通訊需要哪些模塊、開(kāi)發(fā)和部署過(guò)程中遇到的問(wèn)題、以及實(shí)現(xiàn)小型IM及時(shí)通訊的代碼,需要的朋友可以參考下2023-10-10如何利用Spring?Boot?監(jiān)控?SQL?運(yùn)行情況
這篇文章主要介紹了如何利用Spring?Boot監(jiān)控SQL運(yùn)行情況,文章圍繞主題展開(kāi)詳細(xì)的內(nèi)容介紹,具有一定的參考價(jià)值,需要的小伙伴可以參考一下2022-07-07