在了解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的写处理,最后写回到浏览器客户端。