Spring Boot之WebFlux开发应用

Spring Boot之WebFlux开发应用

之前给介绍了Spring Boot相关知识,包括定义、特性,相比Spring MVC做的简化配置,以及与redis,dubbo和elasticsearch等组件集成演示,本次主要介绍基于刚发布的Spring Boot 2.0进行WebFlux开发应用,内容包括相关知识介绍和集成案例演示。

1. 背景知识

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带来了很多新的特性:

  • 基于Java 8(最低标准),支持Java 9;
  • 基于Spring 5构建的Spring Boot 2.0,通过使用Spring WebFlux提供了响应式Web编程支持;
  • 支持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规范支持异步处理,该功能主要针对业务处理较耗时的情况,可以减少服务器资源占用,提高并发处理速度。

2. Spring WebFlux实战

2.1 WebFlux工程创建

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

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

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

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

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

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

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

2.2 Hello World应用开发

    下面通过编写Handler和Router Functions来实现hello world程序。
  1. 1)编写Hello world handler,该类相当于Spring Web中的Service bean;

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

  3. 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. 1)首先配置Spring Data Reactive Redis,默认指向本地6379端口的Redis;

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

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

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

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

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

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

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

3. 分析总结

通过以上介绍,可以看出基于Spring Boot进行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&lt;User&gt;,而ServerResponse.ok().body(Mono.just(user), User.class) 将这个Mono&lt;User&gt;转成Mono&lt;ServerResponse&gt;,这代表在ServerResponse可用时候发送响应的流。

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

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

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

参考资料

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值