添加链接
link管理
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接

一、前言

本文主要介绍基于SpringBoot如何快速上手使用SpringFlux框架开发WEB网站,同时稍微深入地了解以下SpringBoot启动SpringFlux框架的过程。

Spring 5.0在原有的Spring MVC Stack(又称Servlet Stack)以外,又引入了新的WEB开发技术栈——Spring Flux Stack(又称Reactive Stack),以满足不同的应用程序及开发团队的需求。

开发者一直在寻找最适合他们的应用程序的运行时、编程框架及架构。比如,有些用例最适合采用基于同步阻塞IO架构的技术栈,而 另一些用例 可能更适合于基于 Reactive Streams 响应式编程原则构建的异步的、非阻塞的技术栈。

后续将有系列文章深入介绍SpringFlux所采用的响应式编程原则及其代表实现ProjectReactor,希望通过系列文章的介绍,让广大读者能够在逐步使用SpringFlux的过程中,理解响应式编程原理及实现,进而能够对项目应该选择SpringMVC还是SpringWebFlux形成自己的判断标准。

  • 关于非阻塞IO: 《从时间碎片角度理解阻塞IO模型及非阻塞模型》
  • 关于SpringFlux新手入门: 《快速上手Spring Flux框架》 本文
  • 为什么Spring要引入SpringFlux框架 尚未完成
  • Spring Flux中Request与HandlerMapping关系的形成过程
  • Spring Flux中执行HandlerMapping的过程 尚未完成
  • Spring Flux中是如何处理HandlerResult的 尚未完成
  • Spring Flux与WEB服务器之Servlet 3.1+ 尚未完成
  • Spring Flux与WEB服务器之Netty 尚未完成
  • 二、快速上手

    1、创建项目

    打开 http://start.spring.io ,来初始化一个Spring WebFlux项目吧。左侧一列是Project Metadata,填上你的group名(我们使用net.yesdata吧),还有Artifact名(默认是demo);然后右侧一列是Dependencies(依赖),我们输入”reactive web”,在得到的下拉框中选择”Reacive Web”,然后下方”Selected Dependencies”处会显示我们选中的”Reactive Web”。然后点击”Generate Project”,浏览器会下载创建好的Spring Boot项目。加压后用你喜欢的IDE(Eclipse或者IntelliJ IDEA等)。

    2、增加一个Controller

    如果你熟悉Spring MVC,你一定对@Controller注解不陌生。即使不熟悉也没关系,我会简单介绍一下。
    Spring WebFlux带有两种特征,一种是函数式的(Functional),另一种是基于注解的(annotation-based)。函数式编程不太适合快速上手,我们先选择基于注解。类似于Spring MVC模型,Spring WebFlux模型也使用@Controller注解,以及@RestController注解。

    用IDE打开项目后,追加一个类:SampleController
    然后增加如下代码:

    @RestController
    @RequestMapping("/")
    public class SampleController {
        @GetMapping("/hello")
        public String hello(){
            return "hello";
    

    运行后,用浏览器访问: http://localhost:8080/hello ,将会在浏览器上看到”hello”字样。

    怎么样,是不是很简单。

    3、增加一个WebFilter

    增加一个Filter试试看。在Spring WebFlux框架下,增加Filter是通过实现WebFilter接口实现的。

    @Component
    public class FirstWebFilter implements WebFilter {
        @Override
        public Mono<Void> filter(ServerWebExchange serverWebExchange, WebFilterChain webFilterChain) {
            serverWebExchange.getAttributes().put("User", "jerry");
            return webFilterChain.filter(serverWebExchange);
    

    三、深入了解一下SpringBoot启动Spring WebFlux的过程

    对于已经笔记熟悉Spring MVC框架的开发人员来说,快速上手无法满足欲望。必须了解其背后的机制原理等,方能有知己知彼的感觉。接下来稍微探讨以下SpringBoot启动Spring WebFlux的过程。尚不太熟悉Spring MVC框架的开发人员也可以阅读一下本章内容,或许对更好地使用Spring WebFlux框架有帮助。

    1、准备工作

    你需要从Gitub https://github.com/spring-projects/spring-framework 下载Spring WebFlux的源码,以便进行后续分析。

    2、@EnableWebFlux

    回顾一下通过 http://start.spring.io 创建项目中,DemoApplication启动类的注解中,有一个注解是:@EnableWebFlux。SpringBoot就是通过这个注解,来启动Spring WebFlux的。

    @EnableWebFlux
    @SpringBootApplication
    public class DemoApplication {
        public static void main(String[] args) {
            SpringApplication.run(DemoApplication.class, args);
    

    再看一下EnableWebFlux的定义(可以到SpringWebFlux源码中找到),如下,我们注意到它引入了DelegatingWebFluxConfiguration类。看来秘密会藏在DelegatingWebFluxConfiguration类里呢。

    @Retention(RetentionPolicy.RUNTIME)
    @Target(ElementType.TYPE)
    @Documented
    @Import(DelegatingWebFluxConfiguration.class)
    public @interface EnableWebFlux {
    

    打开DelegatingWebFluxConfiguration.java文件(可以到SpringWebFlux源码中找到),然后你我们发现它的父类是WebFluxConfigurationSupport类。我们先来看看这个父类。

    @Configuration
    public class DelegatingWebFluxConfiguration extends WebFluxConfigurationSupport {
    ......
    

    下面是父类WebFluxConfigurationSupport实现的代码片段。我们注意到,它向Spring Bean容器中,注入了两个Bean:webHandler和requestMappingHandlerMapping(实际上还注入了其它若干个Bean,不过我们暂时只关注这两个吧)。

    名为”webHandler”的Bean的类型是DispatcherHandler,顾名思义是分发器,分发请求给各个处理单元。
    名为”requestMappingHandlerMapping”的Bean的类型是RequestMappingHandlerMapping,它的根本是实现了HandlerMapping接口。HandlerMapping的作用是将请求映射到Handler上,比如把某个请求路径映射到某个Controller上。

    关于DispatcherHandler和HandlerMapping,后面章节继续深入讲解。

    public class WebFluxConfigurationSupport implements ApplicationContextAware {
        @Bean
        public DispatcherHandler webHandler() {
            return new DispatcherHandler();
        @Bean
        public RequestMappingHandlerMapping requestMappingHandlerMapping() {
            RequestMappingHandlerMapping mapping = createRequestMappingHandlerMapping();
            mapping.setOrder(0);
            mapping.setContentTypeResolver(webFluxContentTypeResolver());
            mapping.setCorsConfigurations(getCorsConfigurations());
            PathMatchConfigurer configurer = getPathMatchConfigurer();
            Boolean useTrailingSlashMatch = configurer.isUseTrailingSlashMatch();
            if (useTrailingSlashMatch != null) {
                mapping.setUseTrailingSlashMatch(useTrailingSlashMatch);
            Boolean useCaseSensitiveMatch = configurer.isUseCaseSensitiveMatch();
            if (useCaseSensitiveMatch != null) {
                mapping.setUseCaseSensitiveMatch(useCaseSensitiveMatch);
            Map<String, Predicate<Class<?>>> pathPrefixes = configurer.getPathPrefixes();
            if (pathPrefixes != null) {
                mapping.setPathPrefixes(pathPrefixes);
            return mapping;
    

    2、DispatcherHandler

    DispatcherHandler将自身作为Bean注册到Spring的Bean容器中,它与WebFilter、WebExceptionHandler等一起,组成处理链。

    DispatcherHandler会从Spring Configuration中探寻到它需要的组件,主要是以下三类:

    public class DispatcherHandler implements WebHandler, ApplicationContextAware {
        private List<HandlerMapping> handlerMappings;
        private List<HandlerAdapter> handlerAdapters;
        private List<HandlerResultHandler> resultHandlers;
    
  • HandlerMapping
  •