@Slf4j
// 在单独的WebFlux环境中,需要开启@EnableWebFlux,它会自动导入WebHandler,WebHandler是WebFlux提供处理请求的核心处理类
// 如果没有这个注解,则HandlerMapping,HandlerAdapter,WebHandler等等都需要自己手动注入
// 它不像SpringWebMvc一样,提供了一些默认的处理器
@EnableWebFlux
@Configuration
@ComponentScan("luck.spring.webflux")
public class WebFluxApplication {
public static void main(String[] args) {
// 创建ReactiveWeb的上下文对象
AnnotationConfigReactiveWebApplicationContext context = new AnnotationConfigReactiveWebApplicationContext(WebFluxApplication.class);
/**
* <pre>
* HttpHandler是一个约定,专门用来处理请求和响应的处理器,它主要并且是唯一的目的就是对不同的Http服务器进行最小的抽象
* 说白了就是对不同Http服务器,HttpHandler接口就是Http服务器处理请求响应的处理类
*
* // Netty服务器
* HttpHandler handler = null;
* ReactorHttpHandlerAdapter adapter = new ReactorHttpHandlerAdapter(handler);
* HttpServer.create().host(host).port(port).handle(adapter).bind().block();
*
* // Undertow服务器
* HttpHandler handler = null;
* UndertowHttpHandlerAdapter adapter = new UndertowHttpHandlerAdapter(handler);
* Undertow server = Undertow.builder().addHttpListener(port, host).setHandler(adapter).build();
* server.start();
*
* // Tomcat服务器
* Servlet servlet = new TomcatHttpHandlerAdapter(handler);
* Tomcat server = new Tomcat();
* File base = new File(System.getProperty("java.io.tmpdir"));
* Context rootContext = server.addContext("", base.getAbsolutePath());
* Tomcat.addServlet(rootContext, "main", servlet);
* rootContext.addServletMappingDecoded("/", "main");
* server.setHost(host);
* server.setPort(port);
* server.start();
* </pre>
*
* <pre>
* 在HttpHandler约定之上,Spring还提供了一个通用的WebAPI,通过多个WebExceptionHandler
* 多个WebFilter和一个WebHandler组成一条链来处理请求,这条链可以通过WebHttpHandlerBuilder来构建
* 而WebHttpHandlerBuilder会包含Spring上下文,从容器中扫描WebExceptionHandler,WebFilter和一个WebHandler的Bean
* 最终构建成HttpHandler来适配不同的Http服务器
* </pre>
*/
// 这句话就是将Spring容器中的WebHandler,WebFilter进行整合,最终将它们转换为HttpHandler
HttpHandler handler = WebHttpHandlerBuilder.applicationContext(context).build();
// 启动Web服务器,可以是Netty(默认),可以是Tomcat和Jetty等等,创建对应的适配器就行,由adapter来处理
HttpServer.create().host("localhost").port(8080).handle(new ReactorHttpHandlerAdapter(handler)).bindNow();
log.error("服务器启动:{}", DateUtil.now());
System.in.read();
log.error("服务器关闭:{}", DateUtil.now());
}
}
@Import(DelegatingWebFluxConfiguration.class)
public @interface EnableWebFlux {
}
// 注册WebFlux工作的一些核心Bean
class DelegatingWebFluxConfiguration {
// SpringWebFlux处理请求的核心类,与DispatcherServlet一样
@Bean
public DispatcherHandler webHandler() {
return new DispatcherHandler();
}
// 异常处理器
@Bean
@Order(0)
public WebExceptionHandler responseStatusExceptionHandler() {
return new WebFluxResponseStatusExceptionHandler();
}
// 处理@RequestMapping请求的Handler映射器
@Bean
public RequestMappingHandlerMapping requestMappingHandlerMapping(RequestedContentTypeResolver contentTypeResolver) {
// 创建HandlerMapping对象
RequestMappingHandlerMapping mapping = new RequestMappingHandlerMapping();
return mapping;
}
// 处理使用RouterFunction方式注册的api映射器
@Bean
public RouterFunctionMapping routerFunctionMapping(ServerCodecConfigurer serverCodecConfigurer) {
RouterFunctionMapping mapping = new RouterFunctionMapping();
// 运行在RequestMappingHandlerMapping之前
mapping.setOrder(-1);
// 设置消息转换器
mapping.setMessageReaders(serverCodecConfigurer.getReaders());
return mapping;
}
// 处理资源类型的映射器
@Bean
public HandlerMapping resourceHandlerMapping(ResourceUrlProvider resourceUrlProvider) {
ResourceLoader resourceLoader = this.applicationContext;
ResourceHandlerRegistry registry = new ResourceHandlerRegistry(resourceLoader);
AbstractHandlerMapping handlerMapping = registry.getHandlerMapping();
return handlerMapping;
}
// 执行目标Handler的适配器
@Bean
public RequestMappingHandlerAdapter requestMappingHandlerAdapter(ReactiveAdapterRegistry reactiveAdapterRegistry, ServerCodecConfigurer serverCodecConfigurer, FormattingConversionService conversionService, Validator validator) {
RequestMappingHandlerAdapter adapter = new RequestMappingHandlerAdapter();
// 参数解析器配置
ArgumentResolverConfigurer configurer = new ArgumentResolverConfigurer();
adapter.setArgumentResolverConfigurer(configurer);
return adapter;
}
// 服务端和客户端的编码解码器配置
@Bean
public ServerCodecConfigurer serverCodecConfigurer() {
ServerCodecConfigurer serverCodecConfigurer = ServerCodecConfigurer.create();
return serverCodecConfigurer;
}
// 处理需要处理逻辑的类型为HandlerFunction的适配器
@Bean
public HandlerFunctionAdapter handlerFunctionAdapter() {
return new HandlerFunctionAdapter();
}
// 处理实现了WebHandler接口的处理器器适配器(和SpringMVC中处理实现了Controller类似的作用)
@Bean
public SimpleHandlerAdapter simpleHandlerAdapter() {
return new SimpleHandlerAdapter();
}
// 处理@ResponseBody注解的结果处理器
@Bean
public ResponseBodyResultHandler responseBodyResultHandler(ReactiveAdapterRegistry reactiveAdapterRegistry, ServerCodecConfigurer serverCodecConfigurer, RequestedContentTypeResolver contentTypeResolver) {
return new ResponseBodyResultHandler(serverCodecConfigurer.getWriters(), contentTypeResolver, reactiveAdapterRegistry);
}
// 处理返回ServerResponse的结果处理器
@Bean
public ServerResponseResultHandler serverResponseResultHandler(ServerCodecConfigurer serverCodecConfigurer) {
List<ViewResolver> resolvers = getViewResolverRegistry().getViewResolvers();
ServerResponseResultHandler handler = new ServerResponseResultHandler();
handler.setMessageWriters(serverCodecConfigurer.getWriters());
handler.setViewResolvers(resolvers);
return handler;
}
}
class DispatcherHandler {
// 初始化三大组件,HandlerMapping,HandlerAdapter,HandlerResultHandler
public void setApplicationContext(ApplicationContext applicationContext) {
this.initStrategies(applicationContext);
}
// 初始化三大组件,HandlerMapping,HandlerAdapter,HandlerResultHandler
protected void initStrategies(ApplicationContext context) {
// 从Spring容器中找HandlerMapping
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);
// 从Spring容器中找HandlerAdapter
Map<String, HandlerAdapter> adapterBeans = BeanFactoryUtils.beansOfTypeIncludingAncestors(context, HandlerAdapter.class, true, false);
this.handlerAdapters = new ArrayList<>(adapterBeans.values());
AnnotationAwareOrderComparator.sort(this.handlerAdapters);
// 从Spring容器中找HandlerResultHandler
Map<String, HandlerResultHandler> beans = BeanFactoryUtils.beansOfTypeIncludingAncestors(context, HandlerResultHandler.class, true, false);
this.resultHandlers = new ArrayList<>(beans.values());
AnnotationAwareOrderComparator.sort(this.resultHandlers);
}
// 处理请求的方法,类似于DispatchServlet的doDispatch方法
@Override
public Mono<Void> handle(ServerWebExchange exchange) {
// 如果没有处理器映射器,表示没有路由信息,则直接返回404
if (this.handlerMappings == null) {
// 返回404的异常信息
return this.createNotFoundError();
}
// 判断一个请求是否为CORS预检请求
if (CorsUtils.isPreFlightRequest(exchange.getRequest())) {
// 处理跨域预检请求
return this.handlePreFlight(exchange);
}
// 处理非跨域请求
return Flux.fromIterable(this.handlerMappings)
// 将handlerMappings进行有序的调用getHandler
.concatMap(mapping -> mapping.getHandler(exchange))
// 该方法只会获取第一个不为空的元素
.next()
// 如果没有找到Handler,则创建一个404的异常
.switchIfEmpty(this.createNotFoundError())
// 捕捉异常,执行一个兜底的回调函数来处理异常信息
.onErrorResume(ex -> this.handleDispatchError(exchange, ex))
// 如果没有出现异常,使用handler处理请求
.flatMap(handler -> this.handleRequestWith(exchange, handler));
}
// 处理跨域预检请求
@Override
public Mono<Void> handlePreFlight(ServerWebExchange exchange) {
// 遍历所有的HandlerMapping
return Flux.fromIterable(this.handlerMappings != null ? this.handlerMappings : Collections.emptyList())
// 将handlerMappings进行有序的调用getHandler
.concatMap(mapping -> mapping.getHandler(exchange))
// 如果没有找到Handler,设置响应码为403
.switchIfEmpty(Mono.fromRunnable(() -> exchange.getResponse().setStatusCode(HttpStatus.FORBIDDEN)))
// 获取下一个元素
.next()
.then();
}
// 处理分发请求的异常逻辑
private Mono<Void> handleDispatchError(ServerWebExchange exchange, Throwable ex) {
// 发布一个异常
Mono<HandlerResult> resultMono = Mono.error(ex);
// 如果存在HandlerAdapter
if (this.handlerAdapters != null) {
// 遍历所有的HandlerAdapter
for (HandlerAdapter adapter : this.handlerAdapters) {
// 如果该适配器是异常处理器
if (adapter instanceof DispatchExceptionHandler exceptionHandler) {
// 使用该异常处理器是配置对异常进行处理,返回处理后的结果
resultMono = resultMono.onErrorResume(ex2 -> exceptionHandler.handleError(exchange, ex2));
}
}
}
// 将结果使用结果处理器进行处理,然后返回
return resultMono.flatMap(result -> handleResult(exchange, result));
}
// 使用返回值处理器处理返回结果
private Mono<Void> doHandleResult(ServerWebExchange exchange, HandlerResult handlerResult, String description) {
if (this.resultHandlers != null) {
// 遍历所有的返回值处理器
for (HandlerResultHandler resultHandler : this.resultHandlers) {
// 判断是否执行处理该返回结果
if (resultHandler.supports(handlerResult)) {
description += " [DispatcherHandler]";
// 处理返回结果
return resultHandler.handleResult(exchange, handlerResult).checkpoint(description);
}
}
}
// 如果不存在返回值处理器,抛出异常
return Mono.error(new IllegalStateException("No HandlerResultHandler for " + handlerResult.getReturnValue()));
}
// 处理返回结果
private Mono<Void> handleResult(ServerWebExchange exchange, HandlerResult result) {
// 实际处理返回结果
Mono<Void> resultMono = this.doHandleResult(exchange, result, "Handler " + result.getHandler());
// 如果存在异常解析器
if (result.getExceptionHandler() != null) {
resultMono = resultMono.onErrorResume(ex ->
// 获取异常处理器
DispatchExceptionHandler eh = result.getExceptionHandler();
// 使用异常解析器处理异常
eh.handleError(exchange, ex)
// 将处理后的结果(可能是正常结果,也可以是异常信息)使用返回值处理器进行加工
.flatMap(result2 -> this.doHandleResult(exchange, result2, "Exception handler " + result2.getHandler() + ", error=\"" + ex.getMessage() + "\""));
}
// 返回处理的结果
return resultMono;
}
// 处理请求
private Mono<Void> handleRequestWith(ServerWebExchange exchange, Object handler) {
// 如果是响应码是403,表示CORS被拒绝,不处理
/**
* 再{@link DispatcherHandler#handlePreFlight}中,如果不支持CORS,则会将响应码设置为403
*/
if (ObjectUtils.nullSafeEquals(exchange.getResponse().getStatusCode(), HttpStatus.FORBIDDEN)) {
return Mono.empty();
}
if (this.handlerAdapters != null) {
// 遍历所有的HandlerApdate
for (HandlerAdapter adapter : this.handlerAdapters) {
// 如果该adapter可以处理该handler
if (adapter.supports(handler)) {
// 使用适配器处理请求
return adapter.handle(exchange, handler).flatMap(result -> this.handleResult(exchange, result));
}
}
}
// 如果没有处理器适配器,表示该请求无法处理,抛出异常
return Mono.error(new IllegalStateException("No HandlerAdapter: " + handler));
}
// 创建404的异常信息
private <R> Mono<R> createNotFoundError() {
// 返回一个404的状态异常
// defer只要在函数被调用的时候才会触发内部的回调函数
return Mono.defer(() -> {
Exception ex = new ResponseStatusException(HttpStatus.NOT_FOUND);
// 发布一个异常
return Mono.error(ex);
});
}
}
class CorsUtils {
/**
* 判断一个请求是否为CORS预检请求Preflight Request
* CORS预检请求是指浏览器在发起跨域请求前,会先发送一个OPTIONS请求,以确认服务器是否支持跨域请求
* 当请求为CORS预检请求时,该方法会返回true,否则返回false
* 这个方法通常用于处理跨域请求时的CORS相关逻辑
*/
public static boolean isPreFlightRequest(ServerHttpRequest request) {
HttpHeaders headers = request.getHeaders();
return (request.getMethod() == HttpMethod.OPTIONS
// 请求头存在Origin
&& headers.containsKey(HttpHeaders.ORIGIN)
// 请求头存在Access-Control-Request-Method
&& headers.containsKey(HttpHeaders.ACCESS_CONTROL_REQUEST_METHOD));
}
}
class WebHttpHandlerBuilder {
// 从Spring容器中初始化Reactive的Web组件
public static WebHttpHandlerBuilder applicationContext(ApplicationContext context) {
// 从Spring容器中获取"webHandler"的Bean,请求处理器
WebHttpHandlerBuilder builder = new WebHttpHandlerBuilder(context.getBean(WEB_HANDLER_BEAN_NAME, WebHandler.class), context);
// 从Spring容器中获取WebFilter过滤器
List<WebFilter> webFilters = context.getBeanProvider(WebFilter.class).orderedStream().toList();
builder.filters(filters -> filters.addAll(webFilters));
// 从Spring容器中获取WebExceptionHandler异常处理器
List<WebExceptionHandler> exceptionHandlers = context.getBeanProvider(WebExceptionHandler.class).orderedStream().toList();
builder.exceptionHandlers(handlers -> handlers.addAll(exceptionHandlers));
// 从Spring容器中获取HttpHandlerDecoratorFactory,HttpHandler的装饰器工厂
context.getBeanProvider(HttpHandlerDecoratorFactory.class).orderedStream().forEach(builder::httpHandlerDecorator);
// 从Spring容器中获取WebSessionManager,添加Session管理器
builder.sessionManager(context.getBean(WEB_SESSION_MANAGER_BEAN_NAME, WebSessionManager.class));
// 从Spring容器中获取ServerCodecConfigurer,添加服务端客户端的编码解码器
builder.codecConfigurer(context.getBean(SERVER_CODEC_CONFIGURER_BEAN_NAME, ServerCodecConfigurer.class));
// 从Spring容器中获取LocaleContextResolver,添加国际化的支持
builder.localeContextResolver(context.getBean(LOCALE_CONTEXT_RESOLVER_BEAN_NAME, LocaleContextResolver.class));
// 从Spring容器中获取ForwardedHeaderTransformer,添加处理请求转发的时候,正确的处理请求头
builder.forwardedHeaderTransformer(context.getBean(FORWARDED_HEADER_TRANSFORMER_BEAN_NAME, ForwardedHeaderTransformer.class));
return builder;
}
// 创建HttpHandler处理器
public HttpHandler build() {
// 创建带有过滤器的WebHanlder
WebHandler decorated = new FilteringWebHandler(this.webHandler, this.filters);
// 装饰为可以处理异常的WebHanlder
decorated = new ExceptionHandlingWebHandler(decorated, this.exceptionHandlers);
// 创建WebHandler转HttpHandler适配器
HttpWebHandlerAdapter adapted = new HttpWebHandlerAdapter(decorated);
if (this.sessionManager != null) {
adapted.setSessionManager(this.sessionManager);
}
if (this.codecConfigurer != null) {
adapted.setCodecConfigurer(this.codecConfigurer);
}
if (this.localeContextResolver != null) {
adapted.setLocaleContextResolver(this.localeContextResolver);
}
if (this.forwardedHeaderTransformer != null) {
adapted.setForwardedHeaderTransformer(this.forwardedHeaderTransformer);
}
if (this.applicationContext != null) {
adapted.setApplicationContext(this.applicationContext);
}
// 如果存在装饰器,则进行装饰,否则返回HttpHandler适配器
return (this.httpHandlerDecorator != null ? this.httpHandlerDecorator.apply(adapted) : adapted);
}
}
SpringWebFlux运行原理
最新推荐文章于 2024-05-03 22:57:55 发布