文章目录
- 1. 概览
- 2. handle方法回顾
- 3.handlerMappings获取
- 4.HandlerMapping初始化
- 4.1 WebFluxEndpointHandlerMapping 初始化
- 4.1.1 WebFluxEndpointManagementContextConfiguration
- 4.2 ControllerEndpointHandlerMapping
- 4.3 RouterFuntionMapping 初始化
- 4.4 RequestMappingHandlerMapping初始化
- 4.5 RoutePredicateHandlerMapping 初始化
- 4.6 SimpleUrlHandlerMapping的初始化
- 4.6.1 WebMvcAutoConfiguration
- 5. 总结
1. 概览
上一节分享到了gateway的入口DispatcherHandler.handle()方法,本节分享handle方法的实现原理。由于handle方法步骤较多,本节只分享handlerMappings的获取。
2. handle方法回顾
为了方便分享,我再把handle方法的源码展示如下:
@Override
public Mono<Void> handle(ServerWebExchange exchange) {
if (this.handlerMappings == null) {
return createNotFoundError();
}
return Flux.fromIterable(this.handlerMappings)
.concatMap(mapping -> mapping.getHandler(exchange))
.next()
.switchIfEmpty(createNotFoundError())
.flatMap(handler -> invokeHandler(exchange, handler))
.flatMap(result -> handleResult(exchange, result));
}
handle方法处理请求总共分为四部分,首先通过handlerMappings找到请求对应的handlerMapping,第二步通过handlerMappings找到对应的handler方法,第三步调用handler方法获取到结果,最后通过handleResult方法处理结果。本节主要分享handlerMapping是如何组织的。
3.handlerMappings获取
handlerMappings是在initStrategies方法中初始化的,通过BeanFactoryUtils获取到所有HandlerMapping类型的Bean,代码如下:
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);
}
那都获得了那些handlerMappings呢,在我的项目中,我通过debug发现,handlerMappings List里一共有6个对象,分别是
1. WebFluxEndpointHandlerMapping
2. ControllerEndpointHandlerMapping
3. RouterFunctionMapping
4. RequestMappingHandlerMapping
5. RoutePredicateHandlerMapping
6. SimpleUrlHandlerMapping
他们有什么作用,以及是何时被初始化的呢,接下来我们一个一个探索一下。
4.HandlerMapping初始化
4.1 WebFluxEndpointHandlerMapping 初始化
WebFluxEndpointHandlerMapping的初始化在WebFluxEndpointManagementContextConfiguration类中,类声明如下:
@ManagementContextConfiguration(proxyBeanMethods = false)
@ConditionalOnWebApplication(type = Type.REACTIVE)
@ConditionalOnClass({ DispatcherHandler.class, HttpHandler.class })
@ConditionalOnBean(WebEndpointsSupplier.class)
@EnableConfigurationProperties(CorsEndpointProperties.class)
public class WebFluxEndpointManagementContextConfiguration {
WebFluxEndpointHandlerMapping注册bean代码如下
@Bean
@ConditionalOnMissingBean
public WebFluxEndpointHandlerMapping webEndpointReactiveHandlerMapping(WebEndpointsSupplier webEndpointsSupplier,
ControllerEndpointsSupplier controllerEndpointsSupplier, EndpointMediaTypes endpointMediaTypes,
CorsEndpointProperties corsProperties, WebEndpointProperties webEndpointProperties,
Environment environment) {
String basePath = webEndpointProperties.getBasePath();
EndpointMapping endpointMapping = new EndpointMapping(basePath);
Collection<ExposableWebEndpoint> endpoints = webEndpointsSupplier.getEndpoints();
List<ExposableEndpoint<?>> allEndpoints = new ArrayList<>();
allEndpoints.addAll(endpoints);
allEndpoints.addAll(controllerEndpointsSupplier.getEndpoints());
return new WebFluxEndpointHandlerMapping(endpointMapping, endpoints, endpointMediaTypes,
corsProperties.toCorsConfiguration(), new EndpointLinksResolver(allEndpoints, basePath),
shouldRegisterLinksMapping(environment, basePath));
}
4.1.1 WebFluxEndpointManagementContextConfiguration
WebFluxEndpointManagementContextConfiguration这个类不在spring-cloud-gateway-server包中,它在spring-boot-actuator-autoconfigure包中,是spring.factories文件指定的自动装配类
4.2 ControllerEndpointHandlerMapping
ControllerEndpointHandlerMapping类的初始化也在WebFluxEndpointManagementContextConfiguration类中,代码如下:
@Bean
@ConditionalOnMissingBean
public ControllerEndpointHandlerMapping controllerEndpointHandlerMapping(
ControllerEndpointsSupplier controllerEndpointsSupplier, CorsEndpointProperties corsProperties,
WebEndpointProperties webEndpointProperties) {
EndpointMapping endpointMapping = new EndpointMapping(webEndpointProperties.getBasePath());
return new ControllerEndpointHandlerMapping(endpointMapping, controllerEndpointsSupplier.getEndpoints(),
corsProperties.toCorsConfiguration());
}
4.3 RouterFuntionMapping 初始化
RouterFuntionMapping的初始化在WebFluxAutoConfiguration的内部类WelcomePageConfiguration里
WebFluxAutoConfiguration在GatewayAutoConfiguration里触发加载,代码如下
@AutoConfigureBefore({ HttpHandlerAutoConfiguration.class,
WebFluxAutoConfiguration.class })
WebFluxAutoConfiguration类声明如下:
@Configuration(proxyBeanMethods = false)
@ConditionalOnWebApplication(type = ConditionalOnWebApplication.Type.REACTIVE)
@ConditionalOnClass(WebFluxConfigurer.class)
@ConditionalOnMissingBean({ WebFluxConfigurationSupport.class })
@AutoConfigureAfter({ ReactiveWebServerFactoryAutoConfiguration.class, CodecsAutoConfiguration.class,
ValidationAutoConfiguration.class })
@AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE + 10)
public class WebFluxAutoConfiguration {
RouterFunctionMapping 加载代码如下:
@Configuration(proxyBeanMethods = false)
public static class WelcomePageConfiguration {
@Bean
public RouterFunctionMapping welcomePageRouterFunctionMapping(ApplicationContext applicationContext,
WebFluxProperties webFluxProperties, ResourceProperties resourceProperties) {
WelcomePageRouterFunctionFactory factory = new WelcomePageRouterFunctionFactory(
new TemplateAvailabilityProviders(applicationContext), applicationContext,
resourceProperties.getStaticLocations(), webFluxProperties.getStaticPathPattern());
RouterFunction<ServerResponse> routerFunction = factory.createRouterFunction();
if (routerFunction != null) {
RouterFunctionMapping routerFunctionMapping = new RouterFunctionMapping(routerFunction);
routerFunctionMapping.setOrder(1);
return routerFunctionMapping;
}
return null;
}
}
除了RouterFunctionMapping,WebFluxAutoConfiguration还加载了另外两个重要的配置ResourceProperties 和 WebFluxProperties 用来加载WebFlux配置使用。
@Configuration(proxyBeanMethods = false)
@EnableConfigurationProperties({ ResourceProperties.class, WebFluxProperties.class })
@Import({ EnableWebFluxConfiguration.class })
public static class WebFluxConfig implements WebFluxConfigurer {
4.4 RequestMappingHandlerMapping初始化
RequestMappingHandlerMapping 在 WebFluxConfigurationSupport中被实例化,代码如下:
@Bean
public RequestMappingHandlerMapping requestMappingHandlerMapping(
@Qualifier("webFluxContentTypeResolver") RequestedContentTypeResolver contentTypeResolver) {
RequestMappingHandlerMapping mapping = createRequestMappingHandlerMapping();
mapping.setOrder(0);
mapping.setContentTypeResolver(contentTypeResolver);
mapping.setCorsConfigurations(getCorsConfigurations());
PathMatchConfigurer configurer = getPathMatchConfigurer();
Boolean useTrailingSlashMatch = configurer.isUseTrailingSlashMatch();
if (useTrailingSlashMatch != null) {
mapping.setUseTrailingSlashMatch(useTrailingSlashMatch);
}
Boolean useCaseSensitiveMatch = configurer.isUseCaseSensitiveMatch();
if (useCaseSensitiveMatch != null) {
mapping.setUseCaseSensitiveMatch(useCaseSensitiveMatch);
}
Map<String, Predicate<Class<?>>> pathPrefixes = configurer.getPathPrefixes();
if (pathPrefixes != null) {
mapping.setPathPrefixes(pathPrefixes);
}
return mapping;
}
WebFluxConfigurationSupport 在GatewayAutoConfiguration类中,由注解
@AutoConfigureBefore({ HttpHandlerAutoConfiguration.class,
WebFluxAutoConfiguration.class })
注入到spring中.
4.5 RoutePredicateHandlerMapping 初始化
RoutePredicateHandlerMapping 是在GatewayAutoConfiguration类中初始化。
RoutePredicateHandlerMapping声明的代码如下:
@Bean
public RoutePredicateHandlerMapping routePredicateHandlerMapping(
FilteringWebHandler webHandler, RouteLocator routeLocator,
GlobalCorsProperties globalCorsProperties, Environment environment) {
return new RoutePredicateHandlerMapping(webHandler, routeLocator,
globalCorsProperties, environment);
}
从RoutePredicateHandlerMapping初始化的类我判断handle方法使用的mapping应该是它。
4.6 SimpleUrlHandlerMapping的初始化
SimpleUrlHandlerMapping的初始化在WebMvcAutoConfiguration类中,我们先来看一下这个类,类上面声明了好多的注解,其中@ConditionalOnClass({ Servlet.class, DispatcherServlet.class, WebMvcConfigurer.class }) 可以看到,它是用来处理mvc请求的。
@Configuration(proxyBeanMethods = false)
@ConditionalOnWebApplication(type = Type.SERVLET)
@ConditionalOnClass({ Servlet.class, DispatcherServlet.class, WebMvcConfigurer.class })
@ConditionalOnMissingBean(WebMvcConfigurationSupport.class)
@AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE + 10)
@AutoConfigureAfter({ DispatcherServletAutoConfiguration.class, TaskExecutionAutoConfiguration.class,
ValidationAutoConfiguration.class })
public class WebMvcAutoConfiguration {
具体实例化的代码如下所示,在第14行调用registry.getHandlerMapping()获得了一个mapping,这个mapping就是SimpleUrlHandlerMapping
@Bean
@Override
public HandlerMapping resourceHandlerMapping(@Qualifier("mvcUrlPathHelper") UrlPathHelper urlPathHelper,
@Qualifier("mvcPathMatcher") PathMatcher pathMatcher,
@Qualifier("mvcContentNegotiationManager") ContentNegotiationManager contentNegotiationManager,
@Qualifier("mvcConversionService") FormattingConversionService conversionService,
@Qualifier("mvcResourceUrlProvider") ResourceUrlProvider resourceUrlProvider) {
Assert.state(getApplicationContext() != null, "No ApplicationContext set");
Assert.state(getServletContext() != null, "No ServletContext set");
AutoConfigurationResourceHandlerRegistry registry = new AutoConfigurationResourceHandlerRegistry(
getApplicationContext(), getServletContext(), contentNegotiationManager, urlPathHelper,
this.mvcProperties);
addResourceHandlers(registry); //增加了registry
AbstractHandlerMapping mapping = registry.getHandlerMapping(); //
if (mapping == null) {
return null;
}
mapping.setPathMatcher(pathMatcher);
mapping.setUrlPathHelper(urlPathHelper);
mapping.setInterceptors(getInterceptors(conversionService, resourceUrlProvider));
mapping.setCorsConfigurations(getCorsConfigurations());
return mapping;
}
registry.getHandlerMapping()方法如下所示
@Override
protected AbstractHandlerMapping getHandlerMapping() {
SimpleUrlHandlerMapping mapping = (SimpleUrlHandlerMapping) super.getHandlerMapping();
reconfigure(mapping);
return mapping;
}
4.6.1 WebMvcAutoConfiguration
WebMvcAutoConfiguration类也不在spring-cloud-gateway-server中,它在spring-boot-autoconfigure包中,它是这个包中spring.factories文件中指定的自动装配类
5. 总结
最后我们总结一下这些handlerMappings的初始化时机。