Spring-webflux 源码阅读
org.springframework.web.reactive (包名)
介绍
Spring-webflux
模块的顶级软件包包含DispatcherHandler
,它是WebFlux服务器端点处理的主要入口点,包括用于将请求映射到处理程序的关键协议,调用它们并处理结果。
该模块为反应式服务器端点提供两种编程模型。一个基于注释@Controller
,另一个基于功能路由和处理。该模块还包含一个功能性,反应性WebClient
以及客户端和服务器,反应式WebSocket
支持。
几张diagram:
(Interface)
HandlerAdapter
将DispatcherHandler
与调用处理程序的细节相分离的协议,使得它可以支持任何处理程序类型。
supports
boolean supports(Object handler);
这个HandlerAdapter
是否支持给定的handler
。
Mono<HandlerResult> handle(ServerWebExchange exchange, Object handler);
用给定的handler 来处理请求
鼓励实现处理因调用处理程序而导致的异常,并且必要时返回表示错误响应的替代结果。
此外,由于异步HandlerResult
可能会在结果处理过程中产生错误,因此还鼓励在HandlerResult
中设置异常处理程序,以便稍后在结果处理后也可以应用异常处理程序。
exchange
当前的服务器交换
返回值:reactor.core.publisher.Mono<HandlerResult>
, 这将返回Mono
,一个单独的HandlerResult
或没有,
如果请求已完全处理,不需要进一步处理。
All Known Implementing Classes 所有已知实施类:
HandlerFunctionAdapter
, RequestMappingHandlerAdapter
, SimpleHandlerAdapter
, WebSocketHandlerAdapter
HandlerMapping
All Known Implementing Classes 所有已知实施类:
AbstractHandlerMapping
,AbstractHandlerMethodMapping
, AbstractUrlHandlerMapping
,RequestMappingHandlerMapping
, RequestMappingInfoHandlerMapping
, RouterFunctionMapping
, SimpleUrlHandlerMapping
由定义请求和处理程序对象之间的映射的对象实现的接口。
BEST_MATCHING_HANDLER_ATTRIBUTE
包含最佳匹配模式的映射处理程序的属性名称。
BEST_MATCHING_PATTERN_ATTRIBUTE
在处理程序映射中包含最佳匹配模式的属性的名称。
MATRIX_VARIABLES_ATTRIBUTE
包含具有URI变量名称的映射的属性的名称以及每个URI变量的相应MultiValueMap。
PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE
包含处理程序映射中的路径的属性的名称,在匹配的情况下,例如“/ static / **”或完全相关的URI。
PRODUCIBLE_MEDIA_TYPES_ATTRIBUTE
包含适用于映射处理程序的可生产的MediaType集合的属性的名称。
URI_TEMPLATE_VARIABLES_ATTRIBUTE
包含URI模板的属性的名称将变量名称映射到值。
Mono<Object> getHandler(ServerWebExchange exchange);
返回此请求的处理程序(handler)。
返回Mono<Object>
:一个发出一个值的Mono,如果请求无法解析到一个处理程序,那么它就没有
HandlerResultHandler
All Known Implementing Classes 所有已知实施类:
ResponseBodyResultHandler
, ResponseEntityResultHandler
, ServerResponseResultHandler
, ViewResolutionResultHandler
处理HandlerResult
,通常由HandlerAdapter
返回。
supports
boolean supports(HandlerResult result);;
该对象是否可以使用给定的HandlerResult
Mono<Void> handleResult(ServerWebExchange exchange, HandlerResult result);
处理给定的结果修改响应标头and/or将数据写入响应。
result
- 处理的结果
Mono <Void>
来指示请求处理完成。
用给定的handler 来处理请求
鼓励实现处理因调用处理程序而导致的异常,并且必要时返回表示错误响应的替代结果。
Class
BindingContext
帮助将请求数据绑定到对象上并提供对具有控制器特定属性的共享模型的访问的上下文。
提供为特定目标创建WebExchangeDataBinder
的方法,命令对象将数据绑定和验证应用,或者没有目标对象用于从请求值进行简单类型转换。用于请求的默认模型的容器。
Constructors 构造器
BindingContext()
创建一个新的BindingContext。
BindingContext(WebBindingInitializer initializer)
使用给定的初始化程序创建一个新的BindingContext。
初始化程序 - 要应用的绑定初始化程序(可能为null)
Method
public Model getModel()
返回一个对象
public WebExchangeDataBinder createDataBinder(ServerWebExchange exchange,
@Nullable
java.lang.Object target,
java.lang.String name)
创建一个WebExchangeDataBinder,以在目标命令对象上应用数据绑定和验证。
protected WebExchangeDataBinder initDataBinder(WebExchangeDataBinder binder,
ServerWebExchange exchange)
始化给定交换的数据绑定实例。
public WebExchangeDataBinder createDataBinder(ServerWebExchange exchange,
java.lang.String name)
创建一个没有目标对象的WebExchangeDataBinder,将请求值的类型转换为简单类型。
HandlerResult
表示调用处理程序或处理程序方法的结果。
public HandlerResult(java.lang.Object handler,
@Nullable
java.lang.Object returnValue,
MethodParameter returnType)
创建一个新的HandlerResult
- handler - the handler that handled the request
- returnValue - the return value from the handler possibly null
- returnType - the return value type
public java.lang.Object getHandler()
返回处理请求的处理程序。
@Nullable
public java.lang.Object getReturnValue()
返回从处理程序返回的值(如果有)。
public ResolvableType getReturnType()
返回从处理程序返回的值的类型 - 例如在控制器方法的签名上声明的返回类型。另请参见getReturnTypeSource()来获取返回类型的底层MethodParameter。
public BindingContext getBindingContext()
返回用于请求处理的BindingContext。
DispatcherHandler(程序入口 , 核心)
All Implemented Interfaces 所有实现的接口:
Aware
, ApplicationContextAware
, WebHandler
HTTP请求处理程序/控制器的中央调度程序
分发已经注册的处理程序来处理请求,提供方便的映射方式
DispatcherHandler从Spring配置中发现需要的代理组件。它在应用程序上下文中检测到以下内容:
- HandlerMapping -- map requests to handler objects(将请求映射到处理对象)
- HandlerAdapter -- for using any handler interface(使用相应的处理程序接口)
- HandlerResultHandler -- process handler return values(流程处理程序返回值)
DispatcherHandler
也设计为一个Spring bean
本身,并实现了ApplicationContextAware
以访问其运行的上下文。如果DispatcherHandler
被声明为bean名称“webHandler”,那么它将被WebHttpHandlerBuilder.applicationContext
(org.springframework.context.ApplicationContext
)发现,与WebFilter
,WebExceptionHandler
等一起创建一个处理链。
@EnableWebFlux
配置中包含DispatcherHandler
beande声明。
构造器
DispatcherHandler()
创建一个新的DispatcherHandler
,它需要通过setApplicationContext(org.springframework.context.ApplicationContext)
配置一个ApplicationContext
DispatcherHandler(ApplicationContext applicationContext)
为给定的ApplicationContext创建一个新的DispatcherHandler。
方法摘要
@Nullable
public final java.util.List<HandlerMapping> getHandlerMappings()
返回在注入的上下文中类型检测到的所有HandlerMapping
bean,并排序。
注意:如果在setApplicationContext(ApplicationContext)之前调用,此方法可能返回null。返回的是具有配置的映射的不可变列表或空值
public void setApplicationContext(ApplicationContext applicationContext)
设置此对象运行的ApplicationContext。通常,此调用将用于初始化对象。
在普通bean属性的采集之后但是在初始化回调之前调用,例如InitializingBean.afterPropertiesSet()或自定义init方法。在ResourceLoaderAware.setResourceLoader(org.springframework.core.io.ResourceLoader),ApplicationEventPublisherAware.setApplicationEventPublisher(org.springframework.context.ApplicationEventPublisher)和MessageSourceAware(如果适用)后调用。
覆盖了接口ApplicationContextAware中的setApplicationContext
applicationContext - 该对象要使用的ApplicationContext对象
protected void initStrategies(ApplicationContext context)
** 初始化环境 **
public reactor.core.publisher.Mono<java.lang.Void> handle(ServerWebExchange exchange)
处理Web服务器交换。
在接口WebHandler中定义了handle方法,在这里来实现
Mono <Void>
来指示请求处理完成
下面让我们来看看这个调度器是怎么实现的。
@Nullable
private List<HandlerMapping> handlerMappings;
@Nullable
private List<HandlerAdapter> handlerAdapters;
@Nullable
private List<HandlerResultHandler> resultHandlers;
首先定义了可以为空的三个List列表,分别是handlerMappings
,handlerAdapters
,resultHandlers
public DispatcherHandler(ApplicationContext applicationContext) {
initStrategies(applicationContext);
}
@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);
}
在实例化DispatcherHandler之后,开始调用initStrategies(applicationContext)
,这个方法,beansOfTypeIncludingAncestors
这个方法来通过解析和反射等方法来收集context
中所有的bean(可以通过注解或者xml配置Spring Bean,Springboot都是注解一般),来创建ioc容器, 上面代码中的mappingBeans
adapterBeans
beans
都是如此,创建好之后来让之前最初创建的三个List变量集合引用,并且对他们进行排序。
到现在为止,初始化已经完成了,接下来我们来看这个入口类的核心方法:
@Override
public Mono<Void> handle(ServerWebExchange exchange) {
if (logger.isDebugEnabled()) {
ServerHttpRequest request = exchange.getRequest();
logger.debug("Processing " + request.getMethodValue() + " request for [" + request.getURI() + "]");
}
if (this.handlerMappings == null) {
return Mono.error(HANDLER_NOT_FOUND_EXCEPTION);
}
return Flux.fromIterable(this.handlerMappings)
.concatMap(mapping -> mapping.getHandler(exchange))
.next()
.switchIfEmpty(Mono.error(HANDLER_NOT_FOUND_EXCEPTION))
.flatMap(handler -> invokeHandler(exchange, handler))
.flatMap(result -> handleResult(exchange, result));
}
package org.springframework.web.server;
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方法是实现了package org.springframework.web.server
中的WebHandler
中的接口,这里可以看到先拿到了请求中的request
,然后接下来就是Flux
开始遍历我们的handlerMappings
,从ServerWebExchange
中获得相应的Handle
,会调用invokeHandler(exchange, handler)
来匹配真正要使用的那个handlerAdapter
,来执行handle方法处理请求逻辑,return handlerAdapter.handle(exchange, handler);
,这个过程中,别的类已经处理完了,并且返回了结果(还没看到哪些类),返回一个Mono<HandlerResult>
,代码如下:
private Mono<HandlerResult> invokeHandler(ServerWebExchange exchange, Object handler) {
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));
}
最后就是调用handleResult(exchange, result)
这个方法,代码如下:
private HandlerResultHandler getResultHandler(HandlerResult handlerResult) {
if (this.resultHandlers != null) {
for (HandlerResultHandler resultHandler : this.resultHandlers) {
if (resultHandler.supports(handlerResult)) {
return resultHandler;
}
}
}
throw new IllegalStateException("No HandlerResultHandler for " + handlerResult.getReturnValue());
}
同理,也是要遍历来匹配真正的resultHandler
,然后获得这个,调用handlerResult.getReturnValue());
来返回结果。今天先看到这,还有点懵。不过可以感受到这个异步非阻塞IO框架的强大之处。