Spring WebFlux是随Spring 5推出的响应式Web框架。
1)服务端技术栈
Spring提供了完整的支持响应式的服务端技术栈。
如上图所示,左侧为基于spring-webmvc的技术栈,右侧为基于spring-webflux的技术栈,
Spring WebFlux是基于响应式流的,因此可以用来建立异步的、非阻塞的、事件驱动的服务。它采用Reactor作为首选的响应式流的实现库,不过也提供了对RxJava的支持。
由于响应式编程的特性,Spring WebFlux和Reactor底层需要支持异步的运行环境,比如Netty和Undertow;也可以运行在支持异步I/O的Servlet 3.1的容器之上,比如Tomcat(8.0.23及以上)和Jetty(9.0.4及以上)。
从图的纵向上看,spring-webflux上层支持两种开发模式:
类似于Spring WebMVC的基于注解(@Controller、@RequestMapping)的开发模式;
Java 8 lambda 风格的函数式开发模式。
Spring WebFlux也支持响应式的Websocket服务端开发。
2)响应式Http客户端
此外,Spring WebFlux也提供了一个响应式的Http客户端API WebClient。它可以用函数式的方式异步非阻塞地发起Http请求并处理响应。其底层也是由Netty提供的异步支持。
我们可以把WebClient看做是响应式的RestTemplate,与后者相比,前者:
是非阻塞的,可以基于少量的线程处理更高的并发;
可以使用Java 8 lambda表达式;
支持异步的同时也可以支持同步的使用方式;
可以通过数据流的方式与服务端进行双向通信。
当然,与服务端对应的,Spring WebFlux也提供了响应式的Websocket客户端API。
我们通过以下几个例子来了解它:
先介绍一下使用Spring WebMVC风格的基于注解的方式如何编写响应式的Web服务,这几乎没有学习成本,非常赞。虽然这种方式在开发上与Spring WebMVC变化不大,但是框架底层已经是完全的响应式技术栈了;
再进一步介绍函数式的开发模式;
简单几行代码实现服务端推送(Server Send Event,SSE);
然后我们再加入响应式数据库的支持(使用Reactive Spring Data for MongoDB);
使用WebClient与前几步做好的服务端进行通信;
最后我们看一下如何通过“流”的方式在Http上进行通信。
Spring Boot 2是基于Spring 5的,其中一个比较大的更新就在于支持包括spring-webflux和响应式的spring-data在内的响应式模块。
基于WebMVC注解的方式
我们首先用Spring WebMVC开发一个只有Controller层的简单的Web服务,然后仅仅做一点点调整就可切换为基于Spring WebFlux的具有同样功能的Web服务。
基于Spring Initializr创建项目
本节的例子很简单,不涉及Service层和Dao层,因此只选择spring-webmvc即可,也就是“Web”的starter;
也可以自行在pom上加上依赖:
<code><
dependency
><
groupId
>org.springframework.bootgroupId
><
artifactId
>spring-boot-starter-webartifactId
>dependency
>/<code>
创建Controller和Endpoint
创建Controller类HelloController,仅提供一个Endpoint:/hello:
<code>@RestController/<code>
<code>public
class
HelloController
{/<code>
<code> /<code>
<code>public
Stringhello
()
{/<code>
<code>return
"Welcome to reactive world ~"
;/<code>
<code> }/<code>
<code> }/<code>
启动应用
一个简单的基于Spring WebMVC的Web服务。我们新增了HelloController.java,修改了application.properties。
使用IDE启动应用,或使用maven命令:mvn spring-boot:run
测试Endpoint。在浏览器中访问http://localhost:8080/hello
基于Spring WebFlux的项目与上边的步骤一致,仅有两点不同。我们这次偷个懒,就不从新建项目了,修改一下上边的项目:
依赖“Reactive Web”的starter而不是“Web”
修改pom:
<code>/<code>
<code><
groupId
>org.springframework.bootgroupId
>/<code>
<code><
artifactId
>spring-boot-starter-webfluxartifactId
> /<code>
<code> /<code>
Controller中处理请求的返回类型采用响应式类型
<code>@RestController/<code>
<code>public
class
HelloController
{/<code>
<code> /<code>
<code>public
Monohello
() { /<code>
<code>return
Mono.just("Welcome to reactive world ~"
); /<code>
<code> }/<code>
<code> }/<code>
仅需要上边两步就改完了,是不是很简单,同样的方法启动应用。启动后发现应用运行于Netty上:
访问http://localhost:8080/hello,结果与Spring WebMVC的相同。
从上边这个非常非常简单的例子中可以看出,Spring真是用心良苦,WebFlux提供了与之前WebMVC相同的一套注解来定义请求的处理,使得Spring使用者迁移到响应式开发方式的过程变得异常轻松。
虽然我们只修改了少量的代码,但是其实这个简单的项目已经脱胎换骨了。整个技术栈从命令式的、同步阻塞的【spring-webmvc + servlet + Tomcat】变成了响应式的、异步非阻塞的【spring-webflux + Reactor + Netty】。
Netty是一套异步的、事件驱动的网络应用程序框架和工具,能够开发高性能、高可靠性的网络服务器和客户端程序,因此与同样是异步的、事件驱动的响应式编程范式一拍即合。