SpringWebFlux运行原理


@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);
    }
}

  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Spring WebFlux是一个基于响应式编程模型的Web框架,它是Spring Framework 5中新增加的功能。Spring WebFlux旨在提供一种非阻塞、可扩展的方式来构建高性能的Web应用程序。 Spring WebFlux提供了一套完整的编程模型,其中包括了用于处理HTTP请求和响应的注解和类。与传统的基于Servlet的Web框架相比,Spring WebFlux使用了异步非阻塞的方式处理请求,这意味着应用程序可以更有效地利用系统资源,提供更高的并发能力。 Spring WebFlux的中文文档提供了详细的说明和示例,帮助开发人员了解如何使用Spring WebFlux构建应用程序。文档涵盖了各个方面的内容,包括API的使用、配置和部署等。 在文档中,开发人员可以了解到Spring WebFlux的核心概念,例如控制器、路由器和处理器函数等。文档还介绍了与其他Spring组件集成的方法,如Spring Data和Spring Security。开发人员可以学习如何使用这些组件来构建功能强大的Web应用程序。 此外,文档还提供了一系列的示例代码,帮助开发人员更好地理解和掌握Spring WebFlux的使用方法。开发人员可以通过这些示例代码来实践和验证自己的理解,加深对Spring WebFlux的认识和应用。 总之,Spring WebFlux的中文文档是开发人员学习和使用Spring WebFlux的重要参考资料。通过阅读文档,开发人员可以深入了解Spring WebFlux原理和使用方法,从而更好地应用于实际项目中。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值