Spring Boot WebFlux 上手教程

Spring Boot WebFlux 上手教程

背景

大家都知道,Spring Framework 是 Java/Spring 应用程序跨平台开发框架,也是 Java EE(Java Enterprise Edition) 轻量级框架,其 Spring 平台为 Java 开发者提供了全面的基础设施支持,虽然 Spring 基础组件的代码是轻量级,但其配置依旧是重量级的。

那是怎么解决了呢?当然是 Spring Boot,Spring Boot 提供了新的编程模式,让开发 Spring 应用变得更加简单方便。本课将会由各个最佳实践工程出发,涉及 Spring Boot 开发相关的各方面,下面先了解下 Spring Boot 框架。

Spring Boot 是什么

Spring Boot(Boot 顾名思义,是引导的意思)框架是用于简化 Spring 应用从搭建到开发的过程。应用开箱即用,只要通过一个指令,包括命令行 java -jar、SpringApplication 应用启动类、Spring Boot Maven 插件等,就可以启动应用了。另外,Spring Boot 强调只需要很少的配置文件,所以在开发生产级 Spring 应用中,让开发变得更加高效和简易。目前,Spring Boot 版本是 2.x 版本。

Spring Boot WebFlux 是什么

可以看到上面的图,WebFlux 相对 MVC 一样重要。大多数场景使用 MVC 都是阻塞式的,WebFlux 使用的场景是异步非阻塞的,那什么是响应式编程(Reactive Programming)?

官方文档这样描述:响应式编程是基于异步和事件驱动的非阻塞程序,只是垂直通过在 JVM 内启动少量线程扩展,而不是水平通过集群扩展。

Spring Boot 2.0 包括一个新的 spring-webflux 模块,该模块包含对响应式 HTTP 和 WebSocket 客户端的支持,以及对 REST、HTML 和 WebSocket 交互等程序的支持。

为什么学习 Spring Boot WebFlux

  • 微服务架构越来越火,Spring Boot 是一大趋势,因为 Spring Cloud 是基于 Spring Boot 的,所以学好 Spring Boot WebFlux 会受益匪浅。
  • 从编程来讲,虽然阻塞式编程是避免不了的,但是 Reactive 编程在大多数场景,能够提高资源利用率。所以,学习 WebFlux,尤其某些 IO 密集型场景很刚需。

本课程可以学到什么

本课程是一个系列基础教程,目标是带领读者上手实战,课程以新版本 Spring Boot 2.0 WebFlux 的核心概念作为主线。围绕 Spring Boot 2.0 WebFlux 技术栈的系列教程,目标是带领读者了解 Spring Boot 2.0 WebFlux 各种特性,并学会使用 Spring Boot 相关技术栈上手开发项目。尤其对于微服务下,如果是 IO 密集型等场景,可以考虑使用 WebFlux 去实现。

主要包含知识点:快速入门、CRUD 、MongoDB Reactive、Thymeleaf、Redis、WebSocket 等,一步一步了解每个组件的使用方式,最后综合演练。

认真学完这个系列文章之后,会对 Spring Boot 2.0 WebFlux 有进一步的了解,具备使用 Spring Boot 2.0 WebFlux 上手进行开发的基本能力。

我早期写的文章可以看我的 GitHub

适合阅读的人群

本 GitChat 课程适合以下人群阅读:

  • Spring Boot 2.0 WebFlux 新版本的初学人员
  • 对 Spring Boot 2.0 WebFlux 开发感兴趣的开发人员
  • 希望了解 Spring Boot 2.0 WebFlux 的研发人员

版本使用 Spring Boot 2.0.1.RELEASE 版本进行开发演示,技术人员需要具备 Maven、Git 基本技能。

开发运行环境:

  • JDK 1.8 + Spring Boot 2.x 要求 JDK 1.8 环境及以上版本。另外,Spring Boot 2.x 只兼容 Spring Framework 5.0 及以上版本。
  • Maven 3.2+ 为 Spring Boot 2.x 提供了相关依赖构建工具是 Maven,版本需要 3.2 及以上版本,使用 Gradle 则需要 1.12 及以上版本。Maven 和 Gradle 大家各自挑选下喜欢的就好。
  • IntelliJ IDEA IntelliJ IDEA (简称 IDEA)是常用的开发工具,也是本书推荐使用的,同样使用 Eclipse IDE 自然也是可以的。

开发使用框架:

  • MongoDB
  • Redis
  • Thymeleaf
  • WebSocket

课程目录

  • 《导读:课程概要》
  • 《第01课:WebFlux 快速入门实践》
  • 《第02课:WebFlux Web CRUD 实践》
  • 《第03课:WebFlux 整合 MongoDB》
  • 《第04课:WebFlux 整合 Thymeleaf》
  • 《第05课:WebFlux 中 Thymeleaf 和 MongoDB 实践》
  • 《第06课:WebFlux 整合 Redis》
  • 《第07课:WebFlux 中 Redis 实现缓存》
  • 《第08课:WebFlux 中 WebSocket 实现通信》
  • 《第09课:WebFlux 集成测试及部署》
  • 《第10课:WebFlux 实战图书管理系统》

第01课:WebFlux 快速入门实践

Spring Boot 2.0

spring.io 官网有句醒目的话是:

BUILD ANYTHING WITH SPRING BOOT

Spring Boot (Boot 顾名思义,是引导的意思)框架是用于简化 Spring 应用从搭建到开发的过程。应用开箱即用,只要通过一个指令,包括命令行 java -jar 、SpringApplication 应用启动类 、 Spring Boot Maven 插件等,就可以启动应用了。另外,Spring Boot 强调只需要很少的配置文件,所以在开发生产级 Spring 应用中,让开发变得更加高效和简易。目前,Spring Boot 版本是 2.x 版本。Spring Boot 包括 WebFlux。

Spring Boot 2.0 WebFlux

了解 WebFlux,首先了解下什么是 Reactive Streams。Reactive Streams 是 JVM 中面向流的库标准和规范:

  • 处理可能无限数量的元素
  • 按顺序处理
  • 组件之间异步传递
  • 强制性非阻塞背压(Backpressure)

Backpressure(背压)

背压是一种常用策略,使得发布者拥有无限制的缓冲区存储元素,用于确保发布者发布元素太快时,不会去压制订阅者。

Reactive Streams(响应式流)

一般由以下组成:

  • 发布者:发布元素到订阅者
  • 订阅者:消费元素
  • 订阅:在发布者中,订阅被创建时,将与订阅者共享
  • 处理器:发布者与订阅者之间处理数据

响应式编程

有了 Reactive Streams 这种标准和规范,利用规范可以进行响应式编程。那再了解下什么是 Reactive programming 响应式编程。响应式编程是基于异步和事件驱动的非阻塞程序,只是垂直通过在 JVM 内启动少量线程扩展,而不是水平通过集群扩展。这就是一个编程范例,具体项目中如何体现呢?

响应式项目编程实战中,通过基于 Reactive Streams 规范实现的框架 Reactor 去实战。Reactor 一般提供两种响应式 API :

  • Mono:实现发布者,并返回 0 或 1 个元素
  • Flux:实现发布者,并返回 N 个元素

Spring Webflux

Spring Boot Webflux 就是基于 Reactor 实现的。Spring Boot 2.0 包括一个新的 spring-webflux 模块。该模块包含对响应式 HTTP 和 WebSocket 客户端的支持,以及对 REST,HTML 和 WebSocket 交互等程序的支持。一般来说,Spring MVC 用于同步处理,Spring Webflux 用于异步处理。

Spring Boot Webflux 有两种编程模型实现,一种类似 Spring MVC 注解方式,另一种是使用其功能性端点方式。注解的会在第二篇文章讲到,下面快速入门用 Spring Webflux 功能性方式实现。

Spring Boot 2.0 WebFlux 特性

常用的 Spring Boot 2.0 WebFlux 生产的特性如下:

  • 响应式 API
  • 编程模型
  • 适用性
  • 内嵌容器
  • Starter 组件

还有对日志、Web、消息、测试及扩展等支持。

响应式 API

Reactor 框架是 Spring Boot Webflux 响应库依赖,通过 Reactive Streams 并与其他响应库交互。提供了 两种响应式 API:Mono 和 Flux。一般是将 Publisher 作为输入,在框架内部转换成 Reactor 类型并处理逻辑,然后返回 Flux 或 Mono 作为输出。

适用性

file

一图就很明确了,WebFlux 和 MVC 有交集,方便大家迁移。但是注意:

  • MVC 能满足场景的,就不需要更改为 WebFlux。
  • 要注意容器的支持,可以看看下面内嵌容器的支持。
  • 微服务体系结构,WebFlux 和 MVC 可以混合使用。尤其开发 IO 密集型服务的时候,选择 WebFlux 去实现。

编程模型

Spring 5 web 模块包含了 Spring WebFlux 的 HTTP 抽象。类似 Servlet API , WebFlux 提供了 WebHandler API 去定义非阻塞 API 抽象接口。可以选择以下两种编程模型实现:

  • 注解控制层。和 MVC 保持一致,WebFlux 也支持响应性 @RequestBody 注解。
  • 功能性端点。基于 lambda 轻量级编程模型,用来路由和处理请求的小工具。和上面最大的区别就是,这种模型,全程控制了请求 - 响应的生命流程

内嵌容器

跟 Spring Boot 大框架一样启动应用,但 WebFlux 默认是通过 Netty 启动,并且自动设置了默认端口为 8080。另外还提供了对 Jetty、Undertow 等容器的支持。开发者自行在添加对应的容器 Starter 组件依赖,即可配置并使用对应内嵌容器实例。

但是要注意,必须是 Servlet 3.1+ 容器,如 Tomcat、Jetty;或者非 Servlet 容器,如 Netty 和 Undertow。

Starter 组件

跟 Spring Boot 大框架一样,Spring Boot Webflux 提供了很多 “开箱即用” 的 Starter 组件。Starter 组件是可被加载在应用中的 Maven 依赖项。只需要在 Maven 配置中添加对应的依赖配置,即可使用对应的 Starter 组件。例如,添加 spring-boot-starter-webflux 依赖,就可用于构建响应式 API 服务,其包含了 Web Flux 和 Tomcat 内嵌容器等。

开发中,很多功能是通过添加 Starter 组件的方式来进行实现。那么,Spring Boot 2.x 常用的 Starter 组件有哪些呢?

Spring Boot 2.0 WebFlux 组件

Spring Boot WebFlux 官方提供了很多 Starter 组件,每个模块会有多种技术实现选型支持,来实现各种复杂的业务需求:

  • Web:Spring WebFlux
  • 模板引擎:Thymeleaf
  • 存储:Redis、MongoDB、Cassandra,不支持 MySQL
  • 内嵌容器:Tomcat、Jetty、Undertow

Spring Initializr 快速构建项目骨架

Spring Boot Maven 工程,就是普通的 Maven 工程,加入了对应的 Spring Boot 依赖即可。Spring Initializr 则是像代码生成器一样,自动就给你出来了一个 Spring Boot Maven 工程。Spring Initializr 有两种方式可以得到 Spring Boot Maven 骨架工程:

start.spring.io 在线生成

Spring 官方提供了名为 Spring Initializr 的网站,去引导你快速生成 Spring Boot 应用。网站地址,详见这里,操作步骤如下:

第一步,选择 Maven 或者 Gradle 构建工具,开发语言 Java 、Kotlin 或者 Groovy,最后确定 Spring Boot 版本号。这里默认选择 Maven 构建工具、Java 开发语言和 Spring Boot 2.1.5。

第二步,输入 Maven 工程信息,即项目组 groupId 和名字 artifactId,这里对应 Maven 信息为:

  • groupId:springboot
  • artifactId:sspringboot-webflux-1-quickstart

这里默认版本号 version 为 0.0.1-SNAPSHOT,三个属性在 Maven 依赖仓库是唯一标识的。

第三步,选择工程需要的 Starter 组件和其他依赖,最后单击“生成”按钮,即可获得骨架工程压缩包,这里快速入门,只要选择 Reactive Web 即可,如图所示。

配置 POM 依赖

检查工程 POM 文件中,是否配置了 spring-boot-starter-webflux 依赖。如果是上面自动生成的,配置如下:

  <dependencies>    <dependency>      <groupId>org.springframework.boot</groupId>      <artifactId>spring-boot-starter-webflux</artifactId>    </dependency>    <dependency>      <groupId>org.springframework.boot</groupId>      <artifactId>spring-boot-starter-test</artifactId>      <scope>test</scope>    </dependency>    <dependency>      <groupId>io.projectreactor</groupId>      <artifactId>reactor-test</artifactId>      <scope>test</scope>    </dependency>  </dependencies>  <build>    <plugins>      <plugin>        <groupId>org.springframework.boot</groupId>        <artifactId>spring-boot-maven-plugin</artifactId>      </plugin>    </plugins>  </build>

spring-boot-starter-webflux 依赖,是我们核心需要学习 webflux 的包,里面默认包含了 spring-boot-starter-reactor-netty 、spring 5 webflux 包,也就是说默认是通过 netty 启动的。

reactor-test、spring-boot-starter-test 两个依赖搭配是用于单元测试。

spring-boot-maven-plugin 是 Spring Boot Maven 插件,可以运行、编译等调用。

编写处理器类 Handler

新建包 org.spring.springboot.handler,作为编写功能处理类。新建城市(City)例子的处理类 CityHandler,代码如下:

import org.springframework.http.MediaType;import org.springframework.stereotype.Component;import org.springframework.web.reactive.function.BodyInserters;import org.springframework.web.reactive.function.server.ServerRequest;import org.springframework.web.reactive.function.server.ServerResponse;import reactor.core.publisher.Mono;@Componentpublic class CityHandler {    public Mono<ServerResponse> helloCity(ServerRequest request) {        return ServerResponse.ok().contentType(MediaType.TEXT_PLAIN)                .body(BodyInserters.fromObject("Hello, City!"));    }}

ServerResponse 是对响应的封装,可以设置响应状态、响应头、响应正文。比如 ok 代表的是 200 响应码、MediaType 枚举是代表这文本内容类型、返回的是 String 的对象。

这里用 Mono 作为返回对象,是因为返回包含了一个 ServerResponse 对象,而不是多个元素。

编写路由器类 Router

新建 org.spring.springboot.router 包,作为编写路由器类。新建城市(City)例子的路由类 CityRouter,代码如下:

import org.spring.springboot.handler.CityHandler;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;import org.springframework.http.MediaType;import org.springframework.web.reactive.function.server.RequestPredicates;import org.springframework.web.reactive.function.server.RouterFunction;import org.springframework.web.reactive.function.server.RouterFunctions;import org.springframework.web.reactive.function.server.ServerResponse;@Configurationpublic class CityRouter {    @Bean    public RouterFunction<ServerResponse> routeCity(CityHandler cityHandler) {        return RouterFunctions                .route(RequestPredicates.GET("/hello")                                .and(RequestPredicates.accept(MediaType.TEXT_PLAIN)),                        cityHandler::helloCity);    }}

RouterFunctions 对请求路由处理类,即将请求路由到处理器,这里将一个 GET 请求 /hello 路由到处理器 cityHandler 的 helloCity 方法上。跟 Spring MVC 模式下的 HandleMapping 的作用类似。

RouterFunctions.route(RequestPredicate, HandlerFunction) 方法,对应的入参是请求参数和处理函数,如果请求匹配,就调用对应的处理器函数。

到这里一个简单的服务就写好了,下面怎么运行该服务。

启动运行项目

一个简单的 Spring Boot Webflux 工程就开发完毕了,下面运行工程验证下。使用 IDEA 右侧工具栏,点击 Maven Project Tab ,点击使用下 Maven 插件的 install 命令,或者使用命令行的形式,在工程根目录下,执行 Maven 清理和安装工程的指令:

cd springboot-webflux-1-quickstartmvn clean install

在控制台中看到成功的输出:

... 省略[INFO] ------------------------------------------------------------------------[INFO] BUILD SUCCESS[INFO] ------------------------------------------------------------------------[INFO] Total time: 01:30 min[INFO] Finished at: 2017-10-15T10:00:54+08:00[INFO] Final Memory: 31M/174M[INFO] ------------------------------------------------------------------------

运行工程

在 IDEA 中执行 Application 类启动,任意正常模式或者 Debug 模式,可以在控制台看到成功运行的输出:

... 省略2018-04-10 08:43:39.932  INFO 2052 --- [ctor-http-nio-1] r.ipc.netty.tcp.BlockingNettyContext     : Started HttpServer on /0:0:0:0:0:0:0:0:80802018-04-10 08:43:39.935  INFO 2052 --- [           main] o.s.b.web.embedded.netty.NettyWebServer  : Netty started on port(s): 80802018-04-10 08:43:39.960  INFO 2052 --- [           main] org.spring.springboot.Application        : Started Application in 6.547 seconds (JVM running for 9.851)

一看,确实是 Netty 启动的。

打开浏览器,访问 /hello 地址,会看到如图所示的返回结果:

file

总结

本文主要讲了 Spring Boot 2.0 WebFlux 背景和快速入门使用,用的是基于功能性端点去创建一个服务,但这个有点代码偏多。下一课一个 CRUD 我们使用注解控制层,让开发更方便。

猜你喜欢

转载自blog.csdn.net/zhangbijun1230/article/details/91353764