在瞭解SpringMvc的請求流程源碼以後,理解WebFlux就容易的多,畢竟WebFlux處理流程是模仿Servlet另起爐竈的。前端
下面是spring mvc的請求處理流程java
具體步驟:react
第一步:發起請求到前端控制器(DispatcherServlet)web
第二步:前端控制器請求HandlerMapping查找 Handler (能夠根據xml配置、註解進行查找)
匹配條件包括:請求路徑、請求方法、header信息等spring
第三步:處理器映射器HandlerMapping向前端控制器返回Handler,HandlerMapping會把請求映射爲HandlerExecutionChain對象(包含一個Handler處理器(頁面控制器)對象,多個HandlerInterceptor攔截器對象),經過這種策略模式,很容易添加新的映射策略
HandlerInterceptor是請求路徑上的攔截器,須要本身實現這個接口以攔截請求,作一些對handler的前置和後置處理工做。跨域
第四步:前端控制器調用處理器適配器去執行Handler瀏覽器
第五步:處理器適配器HandlerAdapter將會根據適配的結果去執行Handlerspring-mvc
第六步:Handler執行完成給適配器返回ModelAndViewmvc
第七步:處理器適配器向前端控制器返回ModelAndView (ModelAndView是springmvc框架的一個底層對象,包括 Model和view)app
第八步:前端控制器請求視圖解析器去進行視圖解析 (根據邏輯視圖名解析成真正的視圖(jsp)),經過這種策略很容易更換其餘視圖技術,只須要更改視圖解析器便可
第九步:視圖解析器向前端控制器返回View
第十步:前端控制器進行視圖渲染 (視圖渲染將模型數據(在ModelAndView對象中)填充到request域)
第十一步:前端控制器向用戶響應結果
咱們能夠對比SpringMVC的請求流程圖對比來看
咱們能夠看到,處理流程基本同樣,有如下主要的點不一樣
DispatcherHandler
DispatcherServlet
HandlerResultHandler
HandlerMethodReturnValueHandler
RequestedContentTypeResolverBuilder
ContentNegotiationConfigurer
還有不少就不一一例舉了,想知道核心組件對比結果的同窗,能夠看下圖。注意不少圖上的組件名稱相同,可是包的位置是不一樣的,因此你們要注意區分,不要弄混了。
核心控制器DispatcherHandler,等同於阻塞方式的DispatcherServlet
DispatcherHandler實現ApplicationContextAware,那麼必然會調用setApplicationContext方法
public class DispatcherHandler implements WebHandler, ApplicationContextAware { @Override public void setApplicationContext(ApplicationContext applicationContext) { initStrategies(applicationContext); } }
initStrategies初始化
獲取HandlerMapping,HandlerAdapter,HandlerResultHandler的全部實例
protected void initStrategies(ApplicationContext context) { //獲取HandlerMapping及其子類型的bean //HandlerMapping根據請求request獲取handler執行鏈 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及其子類型的bean Map<String, HandlerAdapter> adapterBeans = BeanFactoryUtils.beansOfTypeIncludingAncestors( context, HandlerAdapter.class, true, false); this.handlerAdapters = new ArrayList<>(adapterBeans.values()); //排序 AnnotationAwareOrderComparator.sort(this.handlerAdapters); //獲取HandlerResultHandler及其子類型的bean Map<String, HandlerResultHandler> beans = BeanFactoryUtils.beansOfTypeIncludingAncestors( context, HandlerResultHandler.class, true, false); this.resultHandlers = new ArrayList<>(beans.values()); AnnotationAwareOrderComparator.sort(this.resultHandlers); }
webflux中引入了一個新的HandlerMapping,即RouterFunctionMapping
RouterFunctionMapping實現了InitializingBean,所以在其實例化的時候,會調用afterPropertiesSet方法
public class RouterFunctionMapping extends AbstractHandlerMapping implements InitializingBean { @Nullable private RouterFunction<?> routerFunction; //省略部分代碼 //afterPropertiesSet()方法 是組件初始化後回調 必須實現InitializingBean接口 // @Override public void afterPropertiesSet() throws Exception { if (CollectionUtils.isEmpty(this.messageReaders)) { ServerCodecConfigurer codecConfigurer = ServerCodecConfigurer.create(); this.messageReaders = codecConfigurer.getReaders(); } //初始化routerFunction if (this.routerFunction == null) { initRouterFunctions(); } } /** * Initialized the router functions by detecting them in the application context. * 從應用上下文中查找他們並初始化路由方法 */ protected void initRouterFunctions() { if (logger.isDebugEnabled()) { logger.debug("Looking for router functions in application context: " + getApplicationContext()); } //查找合併全部路由方法的bean List<RouterFunction<?>> routerFunctions = routerFunctions(); if (!CollectionUtils.isEmpty(routerFunctions) && logger.isInfoEnabled()) { routerFunctions.forEach(routerFunction -> logger.info("Mapped " + routerFunction)); } //將一個請求中含有多個路由請求方法合併成一個方法 this.routerFunction = routerFunctions.stream() .reduce(RouterFunction::andOther) .orElse(null); } //查找併合並全部路由方法 private List<RouterFunction<?>> routerFunctions() { //聲明 SortedRouterFunctionsContainer bean SortedRouterFunctionsContainer container = new SortedRouterFunctionsContainer(); //自動注入到上下文中 obtainApplicationContext().getAutowireCapableBeanFactory().autowireBean(container); //返回路由 return CollectionUtils.isEmpty(container.routerFunctions) ? Collections.emptyList() : container.routerFunctions; } //省略部分代碼 private static class SortedRouterFunctionsContainer { @Nullable private List<RouterFunction<?>> routerFunctions; //由上面的方法 自動注入bean時實現依賴查找,查找全部的 RouterFunction beans //並注入到 List<RouterFunction<?>> 中。這樣就會獲得全部實現路由方法的集合 @Autowired(required = false) public void setRouterFunctions(List<RouterFunction<?>> routerFunctions) { this.routerFunctions = routerFunctions; } } }
webflux中引入了一個新的HandlerAdapter,即HandlerFunctionAdapter
webflux中引入了一個新的HandlerResultHandler,即ServerResponseResultHandler
ServerResponseResultHandler實現了InitializingBean,所以在其實例化的時候,會調用afterPropertiesSet方法
流式處理請求handler()
@Override public Mono<Void> handle(ServerWebExchange exchange) { //handlerMappings在initStrategies()方法中已經構造好了 if (this.handlerMappings == null) { return createNotFoundError(); } //構造Flux,數據源爲handlerMappings集合 return Flux.fromIterable(this.handlerMappings) //獲取Mono<Handler>對象,經過concatMap保證順序和handlerMappings順序一致 //嚴格保證順序是由於在一個系統中可能存在一個Url有多個可以處理的HandlerMapping的狀況 .concatMap(mapping -> mapping.getHandler(exchange)) .next() //若是next()娶不到值則拋出錯誤 .switchIfEmpty(createNotFoundError()) //觸發HandlerApter的handle方法 .flatMap(handler -> invokeHandler(exchange, handler)) //觸發HandlerResultHandler 的handleResult方法 .flatMap(result -> handleResult(exchange, result)); }
觸發HandlerApter的handle方法
private Mono<Void> handleResult(ServerWebExchange exchange, HandlerResult result) { return getResultHandler(result).handleResult(exchange, result) .onErrorResume(ex -> result.applyExceptionHandler(ex).flatMap(exceptionResult -> getResultHandler(exceptionResult).handleResult(exchange, exceptionResult))); } 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()); }
經過上圖,咱們能夠看到,這個處理跟以前的註解驅動請求大有不一樣,可是請求的流程是萬變不離其宗,只是組件有所變化。
接下來咱們就跟着流程圖一步一步的來解讀WebFlux函數端點式請求的源碼。
由上圖咱們能夠看到 RouterFunctionMapping
是由WebFluxConfigurationSupport
建立的,接下來看一下RouterFunctions
是怎麼合併RouterFunction
的而且如何關聯到RouterFunctionMapping
的。
RouterFunctionMapping 的源碼,前面已經介紹了。
請求階段的核心代碼就是 org.springframework.web.reactive.DispatcherHandler#handle
方法,咱們來看一下源碼。
@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); } // 1.HTTP請求進來後執行的流程 return Flux.fromIterable(this.handlerMappings) //2 遍歷handlerMappings定位RouterFunctionMapping .concatMap(mapping -> mapping.getHandler(exchange)) // 3.獲取HandlerFunction .next() .switchIfEmpty(Mono.error(HANDLER_NOT_FOUND_EXCEPTION)) .flatMap(handler -> invokeHandler(exchange, handler)) //4.執行 .flatMap(result -> handleResult(exchange, result)); //5. 處理結果 }
上面的代碼已經把大部分的流程說明清楚了,那麼咱們來看一下lambda表達式中每一個內部方法的具體實現。
首先咱們來看一下步驟3的具體實現 org.springframework.web.reactive.handler.AbstractHandlerMapping#getHandler
@Override public Mono<Object> getHandler(ServerWebExchange exchange) { //調用 getHandlerInternal 方法來肯定HandlerFunction return getHandlerInternal(exchange).map(handler -> { if (CorsUtils.isCorsRequest(exchange.getRequest())) { CorsConfiguration configA = this.globalCorsConfigSource.getCorsConfiguration(exchange); CorsConfiguration configB = getCorsConfiguration(handler, exchange); CorsConfiguration config = (configA != null ? configA.combine(configB) : configB); if (!getCorsProcessor().process(config, exchange) || CorsUtils.isPreFlightRequest(exchange.getRequest())) { return REQUEST_HANDLED_HANDLER; } } return handler; }); }
上面一大段代碼其實主要來獲取handler的方法是 getHandlerInternal(exchange)
剩下的部分是 跨域處理的邏輯。咱們看一下 這個方法。
@Override protected Mono<?> getHandlerInternal(ServerWebExchange exchange) { if (this.routerFunction != null) { ServerRequest request = ServerRequest.create(exchange, this.messageReaders); exchange.getAttributes().put(RouterFunctions.REQUEST_ATTRIBUTE, request); return this.routerFunction.route(request); //經過路由獲取到對應處理的HandlerFunction 也就是執行方法 } else { return Mono.empty(); } }
獲取到對應的HandlerFunction
後咱們就來執行第四步,調用HandlerFunction
。
private Mono<HandlerResult> invokeHandler(ServerWebExchange exchange, Object handler) { if (this.handlerAdapters != null) { for (HandlerAdapter handlerAdapter : this.handlerAdapters) { if (handlerAdapter.supports(handler)) { //判斷HandlerAdapters中是否支持以前獲取到的handler return handlerAdapter.handle(exchange, handler); //執行handler 對應下面handle的方法 } } } return Mono.error(new IllegalStateException("No HandlerAdapter: " + handler)); }
org.springframework.web.reactive.function.server.support.HandlerFunctionAdapter#handle
方法,這個類中的方法就是處理函數式端點請求的Adapter具體實現
@Override public Mono<HandlerResult> handle(ServerWebExchange exchange, Object handler) { HandlerFunction<?> handlerFunction = (HandlerFunction<?>) handler; ServerRequest request = exchange.getRequiredAttribute(RouterFunctions.REQUEST_ATTRIBUTE); return handlerFunction.handle(request) //由lambda模式 (返回值-參數) 無需準確的方法簽名 .map(response -> new HandlerResult(handlerFunction, response, HANDLER_FUNCTION_RETURN_TYPE)); //返回HandlerResult對象 }
這裏的lambda模式比較難理解,主要是看HandlerFunction
這個函數式接口
@FunctionalInterface public interface HandlerFunction<T extends ServerResponse> { /** * Handle the given request. * @param request the request to handle * @return the response */ Mono<T> handle(ServerRequest request); }
咱們只須要知足 入參是ServerRequest
類型 返回值是Mono<T>
就能夠執行。
調用完具體方法以後,咱們就能夠進行返回值解析序列化了。這裏就是步驟5 處理結果。
private Mono<Void> handleResult(ServerWebExchange exchange, HandlerResult result) { //獲取對應的返回結果處理器並處理 return getResultHandler(result).handleResult(exchange, result) //若是出現錯誤或者異常 則選擇對應的異常結果處理器進行處理 .onErrorResume(ex -> result.applyExceptionHandler(ex).flatMap(exceptionResult -> getResultHandler(exceptionResult).handleResult(exchange, exceptionResult))); }
咱們再來看一下getResultHandler
代碼
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()); }
在這裏咱們看一下resultHandlers中都含有哪些返回值處理器
咱們經過截圖能夠看出返回值解析器跟流程圖一一對應。
在匹配到對應的返回值解析器以後進行返回值的封裝和寫會,這裏要注意DataBuffer
是NIO的寫處理,最後寫回到瀏覽器客戶端。