文档章节

Spring Boot2.0之WebFlux开发实战(含源码)

 开普勒鑫球
发布于 2018/05/21 18:42
字数 2616
阅读 1.8K
收藏 0

作者|刘海东

编辑|哧溜君、隳天

15分钟和你一起聊一聊2.2万星超热门开源项目Spring Boot 2.0之WebFlux开发,从技术介绍、开发教程、集成案例演示到示例源代码,一网打尽。

 

一、 背景知识

1.1 Spring Boot2.0

北京时间3月1日,Spring Boot 2.0正式发布Release版本。作为Spring生态中重要的开源项目,Spring Boot旨在帮助开发者更容易的创建基于Spring的应用程序和服务。经历了4年的发展,Spring Boot已经拥有了22000多star,16000次Commits,贡献者超过400多名的超热门开源项目。

其中刚发布的2.0版本是自2014年4月1日发布的1.0版本以来第一次重大修订,也是首个提供对Spring Framework 5.0支持的GA稳定版本,2.0带来了很多新的特性

✓基于Spring 5构建的Spring Boot 2.0,通过使用Spring WebFlux 提供了响应式Web编程支持;

✓基于Java 8(最低标准),支持Java 9;

✓支持HTTP/2;

Spring Boot的Web容器选择中Tomcat、Undertow和Jetty均已支持HTTP/2。HTTP/2较HTTP/1.1在性能上有显著提升,页面加载时间降低了50%,详见Java 9和Spring Boot2.0纷纷宣布支持的HTTP/2到底是什么

其余新特性不在此赘述,详见Spring Boot 2.0 Release Notes

1.2 Spring WebFlux

Spring WebFlux是一个非阻塞的函数式Reactive Web框架,可以用来构建异步的、非阻塞的、事件驱动的服务,在伸缩性方面表现非常好。名称中的Flux来源于Reactor中的类Flux。

众所周知Spring MVC是同步阻塞的IO模型,资源浪费相对比较严重,当我们在处理一个耗时的任务时,例如上传一个较大的文件时,服务器的线程一直在等待接收文件,这期间什么也做不了,等到文件接收完毕可能又要写入磁盘,写入的过程线程又只能在那等待,非常浪费资源。而Spring WebFlux是这样做的,线程发现文件还没接收好,先去做其他事情,当文件接收完毕后通知该线程来处理,后续写入磁盘完毕后再通知该线程来处理,通过异步非阻塞机制节省了系统资源,极大的提高了系统的并发量。因此对于微服务下的IO密集型的Service来说,WebFlux是一个不错的选择。

Spring WebFlux与Spring MVC框架对比(一)

 

左边是传统基于Servlet的Spring Web MVC框架,右边是Spring Framework 5.0引入的基于Reactive Streams的Spring WebFlux框架,从上到下依次是Router Functions、WebFlux和Reactive Streams三个新的组件。

● Router Functions:对应@Controller、@RequestMapping等标准的Spring MVC注解,提供了一套函数式编程的API,用于创建Router、Handler和Filter。

● WebFlux:核心组件,用于协调上下游各个组件提供响应式编程的支持。

● Reactive Streams:一种支持Backpressure的异步数据流处理标准,主流实现有RxJava和Reactor,Spring、WebFlux默认集成的是Reactor。Backpressure是一种反馈机制,当数据的发布速度超过处理速度时,消费者需要决定缓存还是丢弃,在响应式编程中,决定权交回给了发布者,消费者只需根据自身处理能力向发布者请求相应数量的数据。

●Web容器:Spring WebFlux既支持Tomcat、Jetty等传统容器(前提是支持Servlet3.1+),又支持Netty、Undertow等异步容器。

只能运行在Servlet 3.1+容器上,是因为3.1规范支持异步处理,该功能主要针对业务处理较耗时的情况,可以减少服务器资源占用,提高并发处理速度。

 

二、 Spring WebFlux实战

2.1 WebFlux工程创建

本文默认开发环境是JDK8,开发工具是IntelliJ IDEA。

下面我们基于Spring Boot 2.0创建一个WebFlux工程,操作步骤非常简单:

1)点击Create New Project,创建一个新的项目;

2)选择Spring Initializr,并配置JDK版本为1.8,Initializr Service UR按默认配置为https://start.spring.io;

3)在metadata页配置工程包名等信息,其中type项目构建方式选择默认值,使用maven进行项目构建;

4)在Dependencies页,我们先将Spring Boot版本设置为2.0.0,可以看到下方有很多选项可以选择,每个选项代表一个组件,这里选择“Web”->“Reactive Web”组件。可以看到下方提示,Reactive Web development with Netty and Spring WebFlux,即通过Reactive Web构建一个WebFlux应用服务;

5)最后配置下工程名称和项目路径,即完成了Spring WebFlux应用的创建。

默认的demo工程pom中只包括webflux和reactor等组件依赖。

2.2 Hello World应用开发

下面通过编写Handler和Router Functions来实现hello world程序。

1)编写Hello world handler,该类相当于Spring Web中的Service bean;

2)将Hello world handler注册到路由上,类似于Spring Web中的Controller类的创建。除了新的Router Functions接口,Spring WebFlux同时支持使用老的Spring MVC注解声明Reactive Controller。

3)接着运行DemoApplication的main方法,即完成了服务启动,这里默认采用了Netty作为reactor的底层容器启动。

最后访问http://127.0.0.1:8080/hello,返回hello world即表示服务启动和访问成功。

2.3 注册登录应用开发

需要注意目前支持reactive编程的数据库只有MongoDB,Redis,Cassandra,Couchbase,而JDBC与JPA的事务是基于阻塞IO模型的,并不是自然支持reactive编程风格,需要等待Spring Data Reactive升级IO模型才能支持相关数据库事务的使用。

Spring WebFlux与Spring MVC框架对比(二)

 

这里以Redis作为数据库,实现一个简单的用户注册登录功能。

1)首先配置Spring Data Reactive Redis,默认指向本地6379端口的Redis;

2)编写用户注册登录handler,主要通过RedisConnection进行数据入库和查询操作,并将业务处理结果以Json格式进行返回。

Uri中的参数可以通过ServerRequest.bodyToMono来获取。

返回的类型Mono可以通过ServerResponse来创建,主要包括以下几步:

a) 状态码方法,可以使用现成的也可以自定义,例如成功的状态码:

b) ContentType(MediaType var1)返回的内容类型是MediaType类型;

c) 最后是返回的内容:

一般常用body()来放入返回的内容,如使用BodyInserters的构建方法fromObject()。

3)添加注册登录路由,将url路由给具体的handler来进行处理;

路由关系创建主要通过RouterFunctions来创建route,

     其中RequestPredicate和HandlerFunction都是函数式接口,HandlerFunction接受一个ServerResponse的子类返回Mono,可以把这个对象认为是实际处理逻辑的部分。

下面我们来验证下程序的运行情况:

1)首先运行服务,然后通过postman发送用户注册请求;

 

2)发送注册请求后,除了前台返回{"message":"successful"},同时可以查看Redis中保存的注册信息;

3)接着用刚注册的信息发起登录请求,可以看出返回结果为登录成功。

至此即完成了一个简单的基于Spring WebFlux和Redis的用户注册登录功能开发。

 

三、分析总结

通过以上介绍,可以看出基于SpringBoot进行WebFlux开发即简单又高效。下面对WebFlux中几个关键语法点进行介绍:

首先简单说下Reactor的两个关键概念,Mono和Flux是Reactor中的流数据类型,Mono是一个用来发送0或者单值数据的发布器,Flux可以用来发送0到 N 个值。它们表示在订阅这些发布服务时发送的数值流。

如下图中getUserById()返回一个Mono<User>表示其在数据可用的情况下发送0个或者单个用户,getUsers()返回一个用户列表的Flux实例,表示其发送0到多个用户数据。

上文提到的handler处理类相当于服务bean,一般用来编写业务功能,其中返回的ServerResponse类似Spring Web中的ResponseEntity用来封装响应数据,包括状态码、HTTP头等信息,它包含了ok(),notFound()等方法,用来创建不同类型的响应信息。如上图的UserRepository.getUserById()返回一个Mono<User>,而ServerResponse.ok().body(Mono.just(user), User.class) 将这个Mono<User>转成Mono<ServerResponse>,这代表在ServerResponse可用时候发送响应的流。

ServerResponse.notFound().build()返回一个Mono<ServerResponse>对象,当给定的pathVariable中找不到对应用户信息时返回404的服务器响应信息。

Spring WebFlux除了对响应式http的支持外,还包括服务端推送事件(Server Sent Events,SSE)、WebSocket客户端和服务端的支持。其中服务端推送事件允许服务器不断地推送数据到客户端,它的实现非常简单,只需要返回对象类型配置成Flux<ServerSentEvent>,就会自动按照SSE规范要求的格式发送响应。

在命令式的编程风格中,线程的执行会被堵塞,直到接收到数据。这使得数据在实际返回之前线程必须进行等待。而在Reactive编程中,我们定义了一个流,用来发送数据以及数据返回时所执行的操作。使用这种方法线程不会被堵塞的。当数据返回时框架会选择一个可用的线程进行下一步处理,这就体现出异步非阻塞模式的优势所在。因此响应式编程能带来更快处理速度,更高硬件利用率的未来选择。

 

微信公众号回复【webflux】获取示例代码,欢迎和作者一起交流,尤其欢迎女神!

 

参考资料

  • https://docs.spring.io/spring/docs/current/spring-framework-reference/web-reactive.html#webflux-fn-handler-functions

  • https://coyee.com/article/12086-spring-5-reactive-web

  • https://zhuanlan.zhihu.com/p/30813274

  • https://github.com/hantsy/spring-reactive-sample#spring-data-redis

  • https://www.ibm.com/developerworks/cn/java/spring5-webflux-reactive/index.html

作者介绍

刘海东,供职于开鑫金服,任移动端架构师、销售平台技术专家,主要方向是Java Web、Android、shell和C++,精力充沛,爱好广泛。

 

大神看这里 ↓↓↓↓

 

1、【招聘】青春还在,梦想要快,大神请接招!

2、答题送开年福利,就这么任性!!!

 

 

本文转载自:https://mp.weixin.qq.com/s/BguLsuzPGimlo0kM_PrCPA

粉丝 1
博文 31
码字总数 0
作品 0
南京
私信 提问
关于Spring Boot 2.x 自定义ErrorAttributes 不起作用的问题解决

关于Spring Boot 2.x 自定义 ErrorAttributes 不起作用的问题解决 简介 的出现极大的简化了开发流程,封装了很多实用的工具;今天要说的是版本中的异常处理,在中其实已经给我们实现好了异常...

zerokb-小浪
2019/01/30
154
0
新书一周销量破千,这本Spring图书为何如此受Java程序员追捧

适读人群 :超强实战技术升级指南,囊括源码、设计思想、架构思维、实战案例、开发经验,Java架构师成长必备;本书基于Spring 5开发的架构师实战指南,几乎涵盖在Spring应用中可能遇到的所有...

Java架构
2019/07/31
0
0
第7课:Java Spring Boot 2.0安全机制、漏洞与MVC身份验证实战

《阿里巴巴Java Spring Boot 2.0开发实战课程》07课 本期分享专家:徐雷—阿里巴巴特邀Java讲师,MongoDB讲师 本期分享主题:Java Spring Boot2.0实战MyBatis与优化 (Java面试题) Java Spri...

徐雷frank
2018/12/12
0
0
Spring Boot 2.0 WebFlux 上手系列课程:快速入门(一)

02:WebFlux 快速入门实践 ## Spring Boot 2.0 spring.io 官网有句醒目的话是: BUILD ANYTHING WITH SPRING BOOT Spring Boot (Boot 顾名思义,是引导的意思)框架是用于简化 Spring 应用从...

泥沙砖瓦浆木匠
2018/04/15
0
0
spring-boot2.0 单元测试JUnit4

spring-boot2.0 单元测试JUnit4 简单在spring-boot2.0版本中使用junit 源码如下: @SpringBootTest(classes = DemoT002Application.class) 只要加上这个就能使用DemoT002Application.class是......

btmaxyyq
2018/06/04
0
0

没有更多内容

加载失败,请刷新页面

加载更多

Go Web 编程之 数据库

概述 数据库用来存储数据。只要不是玩具项目,每个项目都需要用到数据库。现在用的最多的还是 MySQL,PostgreSQL的使用也在快速增长中。 在 Web 开发中,数据库也是必须的。本文将介绍如何在...

darjunlee
今天
51
0
spring-boot-maven-plugin not found的解决方案。

通过IDE创建一个springboot项目, <plugin> <groupId>org.springframework.boot</groupId>//这行红色 <artifactId>spring-boot-maven-plugin</artifactId>//这行红色</plugin> 提示sprin......

一片云里的天空
今天
84
0
OSChina 周三乱弹 —— 我可能是个憨憨

Osc乱弹歌单(2020)请戳(这里) 【今日歌曲】 @宇辰OSC :分享Hare Je的单曲《Alan Walker-Faded(Hare Je remix)》: #今日歌曲推荐# 可以放松大脑的一首纯音乐 《Alan Walker-Faded(Har...

小小编辑
今天
280
3
搞定SpringBoot多数据源(3):参数化变更源

春节将至,今天放假了,在此祝小伙伴们新春大吉,身体健康,思路清晰,永远无BUG! 一句话概括:参数化变更源意思是根据参数动态添加数据源以及切换数据源,解决不确定数据源的问题。 1. 引言...

mason技术记录
昨天
99
0
sql 基础知识

sql 基础知识 不要极至最求一条sql语句搞定一切,可合理拆分为多条语句 1. sql 变量定义与赋值 Sql 语句中,直接在SELECT使用@定义一个变量,如:[@a](https://my.oschina.net/a8856225a)。 ...

DrChenXX
昨天
57
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部