目录
- 前言
- DispatcherHandler - WebFlux调度器
- 1. DispatcherHandler 初始化
- 2. DispatcherHandler 请求处理
前言
接上篇,上篇提到在HttpServerHandle.onStateChange()中会监听请求状态变化,进而对请求进行处理,目前已分析到FilteringWebHandler.filter(),上篇中对WebFilter链表已经做了介绍,后面就是DispatcherHandler.handle(),直到这里,是WebFlux真正的业务相关处理器,包括对请求参数及响应处理等。到这里,WebFlux在使用方式上会分两种,一种是沿用SpringMVC语法,WebFlux能够实现无缝衔接,另一种就是router functions,我们后面将会以router functions为例。
DispatcherHandler - WebFlux调度器
DispatcherHandler是WebFlux的调度器,核心业务流程是通过对请求地址进行解析,执行相应的处理器方法,并进行响应处理。下面我们会从两个部分对DispatcherHandler进行解析,包括初始化和请求处理。
1. DispatcherHandler 初始化
DispatcherHandler 初始化在WebFlux启动时已执行,属于spring注册、不在启动核心流程,所以第一篇里面并未提及。初始化主要是对内部其内部属性进行赋值,包括:
1)List<HandlerMapping> handlerMappings
:处理器路径映射,即请求路径与业务处理器的对应关系,通过对请求路径的解析获取对应的处理器。
2)List<HandlerAdapter> handlerAdapters
:处理器适配器,对不同类型的业务处理器进行相应的前置准备,如请求封装等。
3)List<HandlerResultHandler> resultHandlers
:结果处理器,对业务处理器返回的数据结果进行处理。
初始化代码如下:
package org.springframework.web.reactive;
import ...
public class DispatcherHandler implements WebHandler, PreFlightRequestHandler, ApplicationContextAware {
@Nullable
private List<HandlerMapping> handlerMappings;
@Nullable
private List<HandlerAdapter> handlerAdapters;
@Nullable
private List<HandlerResultHandler> resultHandlers;
/**
* 空构造,Spring注册时调用的即是空构造
*/
public DispatcherHandler() {
}
/**
* 带参构造,直接调用初始化方法
*/
public DispatcherHandler(ApplicationContext applicationContext) {
initStrategies(applicationContext);
}
/**
* 实现ApplicationContextAware接口,注册完成后会自动执行,调用初始化方法
* WebFlux默认注册时调用的是空构造,注册完成后执行initStrategies()方法
*/
@Override
public void setApplicationContext(ApplicationContext applicationContext) {
initStrategies(applicationContext);
}
protected void initStrategies(ApplicationContext context) {
// 获取HandlerMapping,详见1.1
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);
// 获取HandlerAdapter,详见1.2
Map<String, HandlerAdapter> adapterBeans = BeanFactoryUtils.beansOfTypeIncludingAncestors(
context, HandlerAdapter.class, true, false);
this.handlerAdapters = new ArrayList<>(adapterBeans.values());
AnnotationAwareOrderComparator.sort(this.handlerAdapters);
// 获取HandlerResultHandler,详见1.3
Map<String, HandlerResultHandler> beans = BeanFactoryUtils.beansOfTypeIncludingAncestors(
context, HandlerResultHandler.class, true, false);
this.resultHandlers = new ArrayList<>(beans.values());
AnnotationAwareOrderComparator.sort(this.resultHandlers);
}
}
1.1 HandlerMapping
HandlerMapping
:处理器与访问路径的映射关系。WebFlux自动声明了三个实现类,分别为:
1、RequestMappingHandlerMapping
:MVC语法模式下使用@RequestMapping注解注入。
2、RouterFunctionMapping
:RouterFunctions语法模式下声明注入。
3、SimpleUrlHandlerMapping
:URL直接对应Handler,WebFlux默认注入两个匹配路径:
1) /webjars/** -> ResourceWebHandler [classpath [META-INF/resources/webjars/]]
2) /** -> ResourceWebHandler [classpath [META-INF/resources/], classpath [resources/], classpath [static/], classpath [public/]]
这里我们只分析RouterFunctions语法下的情况,即RouterFunctionMapping
的获取,在WebFlux中RouterFunctionMapping
的获取包括注册和初始化两个过程。
1.1.1 RouterFunctionMapping 注册
RouterFunctionMapping
的注册在WebFluxConfigurationSupport中,属于WebFlux自动装配。
package org.springframework.web.reactive.config;
import ...
public class WebFluxConfigurationSupport implements ApplicationContextAware {
...
@Bean
public RouterFunctionMapping routerFunctionMapping(ServerCodecConfigurer serverCodecConfigurer) {
RouterFunctionMapping mapping = createRouterFunctionMapping();
// 设定排序,在RequestMappingHandlerMapping之前
mapping.setOrder(-1);
// 设定消息读取器,会另开一篇专门介绍消息读取器和消息写入器
mapping.setMessageReaders(serverCodecConfigurer.getReaders());
// 配置Mapping跨域及Mapping路径匹配(下划线及大小写转换支持),这里一般都不设定,不做展开
configureAbstractHandlerMapping(mapping, getPathMatchConfigurer());
return mapping;
}
protected RouterFunctionMapping createRouterFunctionMapping() {
return new RouterFunctionMapping();
}
}
1.1.2 RouterFunctionMapping 初始化
在RouterFunctionMapping
类中实现InitializingBean接口的afterPropertiesSet()方法,在Spring注册完成后进行内部属性的初始化,为内部属性赋值,代码如下:
package org.springframework.web.reactive.function.server.support;
import ...
public class RouterFunctionMapping extends AbstractHandlerMapping implements InitializingBean {
@Nullable
private RouterFunction<?> routerFunction;
private List<HttpMessageReader<?>> messageReaders = Collections.emptyList();
@Override
public void afterPropertiesSet() throws Exception {
/**
* 设置messageReaders属性,这里在Sring注入时已经赋值,if内部不再执行。
* HttpMessageReader解释见1.1.2.1
*/
if (CollectionUtils.isEmpty(this.messageReaders)) {
ServerCodecConfigurer codecConfigurer = ServerCodecConfigurer.create();
this.messageReaders = codecConfigurer.getReaders();
}
/**
* 初始化routerFunction属性,详细内容见下方方法
* RouterFunction解释见1.1.2.2
*/
if (this.routerFunction == null) {
initRouterFunctions();
}
if (this.routerFunction != null) {
// 通配路径转换,暂不展开
RouterFunctions.changeParser(this.routerFunction, getPathPatternParser());
}
}
protected void initRouterFunctions() {
// 获取RouterFunction列表
List<RouterFunction<?>> routerFunctions = routerFunctions();
// 累加构建并赋值,即RouterFunction对象嵌套,这里不做展开
this.routerFunction = routerFunctions.stream()
.reduce(RouterFunction::andOther).orElse(null);
// 日志记录
logRouterFunctions(routerFunctions);
}
private List<RouterFunction<?>> routerFunctions() {
// 从Spring中获取RouterFunction,即WebFlux使用时声明的RouterFunction,示例见1.1.2.3
return obtainApplicationContext()
.getBeanProvider(RouterFunction.class)
.orderedStream()
.map(router -> (RouterFunction<?>) router)
.collect(Collectors.toList());
}
}
1.1.2.1 属性类型解析:HttpMessageReader
HttpMessageReader:
消息读取器,即定义读取器支持的媒体类型以及如何读取请求参数或请求体数据。核心代码如下:
package org.springframework.http.codec;
import ...
public interface HttpMessageReader<T> {
/**
* 设定消息读取器支持的媒体类型
*/
List<MediaType> getReadableMediaTypes();
/**
* 是否可读取
* elementType:数据对象类型
* mediaType:请求媒体类型
*/
boolean canRead(ResolvableType elementType, @Nullable MediaType mediaType);
/**
* getReadableMediaTypes() 方法重载,默认实现
* 先判定当前数据类型是否支持,支持则调用子类getReadableMediaTypes(),不支持则返回空集合
*/
default List<MediaType> getReadableMediaTypes(ResolvableType elementType) {
return (canRead(elementType, null) ? getReadableMediaTypes() : Collections.emptyList());
}
/**
* 从ReactiveHttpInputMessage中读取并解析为Flux对象
*/
Flux<T> read(ResolvableType elementType, ReactiveHttpInputMessage message, Map<String, Object> hints);
/**
* 从ReactiveHttpInputMessage中读取并解析为Mono对象
*/
Mono<T> readMono(ResolvableType elementType, ReactiveHttpInputMessage message, Map<String, Object> hints);
/**
* 方法重载 - Flux读取
* ServerHttpRequest 继承 ReactiveHttpInputMessage
*/
default Flux<T> read(ResolvableType actualType, ResolvableType elementType, ServerHttpRequest request,
ServerHttpResponse response, Map<String, Object> hints) {
return read(elementType, request, hints);
}
/**
* 方法重载 - Mono读取
* ServerHttpRequest 继承 ReactiveHttpInputMessage
*/
default Mono<T> readMono(ResolvableType actualType, ResolvableType elementType, ServerHttpRequest request,
ServerHttpResponse response, Map<String, Object> hints) {
return readMono(elementType, request, hints);
}
}
1.1.2.2 属性类型解析:RouterFunction
函数式接口,表示获取请求路径所对应的处理器方法对象,即:HandlerFunction。
RouterFunction定义route()方法,子类通过实现route()方法来获取请求路径所对应的处理器方法对象。同时,RouterFunction中也定义了一些默认方法,实现对RouterFunction组合操作。具体RouterFunction的组合会再开一篇进行具体分析。RouterFunction核心代码如下:
package org.springframework.web.reactive.function.server;
import ...
@FunctionalInterface
public interface RouterFunction<T extends ServerResponse> {
// 获取请求路径所对应的处理器方法对象
Mono<HandlerFunction<T>> route(ServerRequest request);
...
}
1.1.2.3 声明RouterFunction示例
@Configuration
public class UserRouting {
private final UserHandler userHandler;
@Autowired
public UserRouting(UserHandler userHandler) {
this.userHandler = userHandler;
}
@Bean
public RouterFunction<ServerResponse> userRouter() {