环境:SpringBoot2.4.12 请先阅读: Spring WebFlux使用函数式编程之HandlerFunction(1) Spring WebFlux使用函数式编程之RouterFunction(2) Spring WebFlux请求处理流程 一文带你彻底理解Spring WebFlux的工作原理 Reactor响应式编程(Flux、Mono)基本用法 概述 与Spring MVC类似,Spring WebFlux是围绕前端控制器模式设计的,其中核心处理程序 WebHandler 的实现 DispatcherHandler 为请求处理提供共享算法,而实际工作由可配置的委托组件执行。该模型非常灵活,支持多种工作流。 DispatcherHandler 从Spring配置中发现所需的委托组件。它本身也被设计为bean,并实现ApplicationContextAware 以访问它运行的上下文。如果DispatcherHandler 是用webHandler的bean名称声明的,那么WebHttpHandlerBuilder 会发现它,它会将请求处理链组合在一起,如webHandler API中所述。 WebFlux应用程序中的Spring配置通常包含:bean名称为webHandler的DispatcherHandler WebFilter 和WebExceptionHandler DispatcherHandler 特殊bean其它 配置被提供给WebHttpHandlerBuilder 以构建处理链,如下例所示:public class HttpHandlerAutoConfiguration { @Configuration(proxyBeanMethods = false) public static class AnnotationConfig { @Bean public HttpHandler httpHandler(ObjectProviderpropsProvider) { // applicationContext方法中会收集容器中WebFilter和WebExceptionHandler // build方法中构建了HttpWebHandlerAdapter(实现了HttpHandler),该对象中 // 包装了WebFilter和WebExceptionHandler集合 HttpHandler httpHandler = WebHttpHandlerBuilder.applicationContext(this.applicationContext).build(); WebFluxProperties properties = propsProvider.getIfAvailable(); if (properties != null && StringUtils.hasText(properties.getBasePath())) { Map handlersMap = Collections.singletonMap(properties.getBasePath(), httpHandler); return new ContextPathCompositeHandler(handlersMap); } return httpHandler; } } }特殊一样的Bean DispatcherHandler 委托特殊bean处理请求并呈现适当的响应。所谓"特殊bean",是指实现WebFlux框架规定的Spring管理的对象实例。一般都内置这些Bean,不过你可以自定义、扩展或替换它们的属性。 HandlerMapping 将请求映射到处理程序。映射基于一些标准,这些标准的细节因HandlerMapping 实现的不同而不同——注释控制器、简单URL模式映射等等。如:@RequestMapping 注解的Controller或RouterFunction 类型的Bean他们都是由不同的HandlerMapping 来处理。HandlerAdapter 帮助DispatcherHandler 调用映射到请求的处理程序,而不管该处理程序实际是如何调用的。例如,调用带注释的控制器需要解析注释。HandlerAdapter 的主要目的是保护DispatcherHandler 不受这些细节的影响。简单说就是不同的HandlerAdapter 处理由不同HandlerMapping 返回的不同的Handler对象,比如:RequestMappingHandlerMapping 返回的HandlerMethod ,RouterFunctionMapping 返回的HandlerFunction 。HandlerResultHandler 处理处理程序调用的结果并完成响应。WebFlux配置 应用程序可以声明处理请求所需的基础bean(列在Web Handler API和DispatcherHandler下面)。但是,在大多数情况下,WebFlux配置是最好的起点。它声明所需的bean,并提供更高级别的配置回调API来自定义它。请求处理 DispatcherHandler 处理请求的方式如下:每个HandlerMapping 被要求找到一个匹配的处理程序,并使用第一个匹配。如果找到处理程序,则通过适当的HandlerAdapter 运行它,它将从执行中返回的值公开为HandlerResult 。HandlerResult 被提供给适当的HandlerResultHandler ,以通过直接写入响应或使用视图进行渲染来完成处理。结果处理 调用处理程序的返回值通过HandlerAdapter 被包装为HandlerResult ,以及一些附加的上下文,并传递给声称支持它的第一个HandlerResultHandler 。下表列出可用的HandlerResultHandler 实现,所有这些实现都在WebFlux Config中声明:ResponseEntityResultHandler 返回值:ResponseEntity , 通常来自 @Controller 实例。 ServerResponseResultHandler 返回值:ServerResponse ,通常来自功能端点。ResponseBodyResultHandler 返回值:处理来自@ResponseBody 方法或@RestController 类的返回值。ViewResolutionResultHandler 返回值:CharSequence、视图、模型、映射、渲染或任何其他对象都被视为模型属性。异常处理 从HandlerAdapter 返回的HandlerResult 可以基于某些特定于处理程序的机制公开用于错误处理的函数。在以下情况下调用此错误函数:处理程序(例如,@Controller)调用失败。通过HandlerResultHandler 处理处理程序返回值失败。 只要错误信号发生在从处理程序返回的响应类型产生任何数据项之前,error函数就可以更改响应(例如,更改为错误状态)。 这就是如何支持@Controller类中的@ExceptionHandler方法。相比之下,Spring MVC中的支持也是建立在 HandlerExceptionResolver 上的。注意:在WebFlux中,不能使用 @ControllerAdvice 来处理在选择处理程序之前发生的异常。 @RestControllerAdvice public class PackControllerAdvice { @ExceptionHandler public ResponseEntity handle(Exception ex) { ex.printStackTrace(); return ResponseEntity.ok(ex.getMessage() + ", Advice"); } } 注意:这个不能处理调用处理程序之前的任何异常,处理程序之前的异常应该由WebExceptionHandler 来处理 下面的异常处理句柄将会处理,由WebFilter 实例链和目标WebHandle 的异常。@Component @Order(Ordered.HIGHEST_PRECEDENCE) public class CustomWebExceptionHandler implements WebExceptionHandler { @Override public Mono handle(ServerWebExchange exchange, Throwable ex) { System.out.println("异常了: " + ex.getMessage()) ; // 将错误传递下去,后面的onErrorResume还可以继续执行;如果传递,那么下一个处理器将会是DefaultErrorWebExceptionHandler // return Mono.error(ex) ; // exchange.getResponse() // return Mono.error(ex) ; // 下面不传递异常了,直接输出错误信息 ServerHttpResponse response = exchange.getResponse() ; response.setStatusCode(HttpStatus.INTERNAL_SERVER_ERROR) ; response.getHeaders().add("ContentType", "text/html;charset=utf8"); return response.writeWith(Mono.just(exchange.getResponse().bufferFactory().wrap("ERROR".getBytes(Charset.forName("UTF-8"))))) ; } } 完毕!!! Spring中Aware接口实现原理解析 Spring Cloud Nacos 开启权限验证 Spring Cloud Nacos配置中心实现原理 Spring IOC容器对Bean实例化的过程详解源码分析 使用Spring Boot Admin实时监控你的系统 Spring注解@Qualifier这种用法你知道吗? Spring AOP切入点类型及系统提供的非常常用的切入点 Spring Cloud Gateway应用详解1之谓词