什么是WebFlux
springWebFlux 是 SpringFrameworlk5.0 添加的新功能,它是完全非阻塞的,支持Reactive Stream及背压,可以运行于Netty、Undertow等服务器,及Servlet 3.1+容器。
webflux主要在如下两方面体现出独有的优势:
1)非阻塞式
其实在servlet3.1提供了非阻塞的API,WebFlux提供了一种比其更完美的解决方案。使用非阻塞的方式可以利用较小的线程或硬件资源来处理并发进而提高其可伸缩性
2) 函数式编程端点
老生常谈的编程方式了,Spring5必须让你使用java8,那么函数式编程就是java8重要的特点之一,而WebFlux支持函数式编程来定义路由端点处理请求。
WebFlux与SpringMVC
区别:
- WebFlux是完全异步非阻塞的,SpringMVC是同步阻塞的。
- WebFlux采用异步响应式编程,SpringMVC采用命令式编程。
- WebFlux由于完全异步,所有操作数据库的框架,以及数据库也都要求是支持异步的,所以目前不支持Mybatis、不支持Oracle数据库。
WebFlux学习步骤
使用WebFlux需要有以下的技术基础,才能快速上手。
- Java8的新特性(Lambda表达式、Stream API、函数式编程)
- Java9(Reactive Stream)
- Project reactor
- WebFlux
怎么用
Java8的新特性
请看这篇博客:Java8新特性
Java9的Reactive Stream
reactive stream就是一个异步stream处理的标准,它的特点就是非阻塞的back pressure。reactive stream需要做哪些事情:
- 能够处理无效数量的消息
- 消息处理是有顺序的
- 可以异步的在组件之间传递消息
- 一定是非阻塞和backpressure的
为了实现这4个功能,reactive stream定义了4个接口,Publisher,Subscriber,Subscription,Processor。这四个接口实际上是一个观察者模式的实现。
JDK中reactive stream的实现:
在JDK中java.util.concurrent.Flow就是reactive stream语义的一种实现。Flow从JDK9就开始有了。我们看下它的结构:
package com.zx.webflux.reactive; import org.junit.Test; import java.util.concurrent.Flow; import java.util.concurrent.SubmissionPublisher; /** * @Description jdk9 reactive stream的使用 * @Author zx * @Date 2021/9/13 9:03 */ public class ReactiveDemo { @Test public void test1(){ //创建发布者 SubmissionPublisher<String> publisher = new SubmissionPublisher<String>(); //创建订阅者 Flow.Subscriber subscriber = new Flow.Subscriber() { private Flow.Subscription subscription; @Override public void onSubscribe(Flow.Subscription subscription) { //subscription 订阅协议 System.out.println("建立订阅关系第一次调用!"); this.subscription = subscription; //可控制请求数量 this.subscription.request(1); } @Override public void onNext(Object item) { System.out.println("接受数据:" +item); this.subscription.request(1); //this.subscription.cancel(); } @Override public void onError(Throwable throwable) { System.out.println("onError"); } @Override public void onComplete() { System.out.println("数据接收完成!"); } }; //建立订阅关系 publisher.subscribe(subscriber); try { //发数据 for (int i = 0; i < 10; i++) { System.out.println("开始发送数据:" + "reactive" + i); publisher.submit("hello reactive" + i); } Thread.currentThread().join(); } catch (Exception e) { e.printStackTrace(); }finally { //结束 publisher.close(); } } } |
Project reactor
Project Reactor是一个运行在JVM上的反应式编程基础库,以“背压”的形式管理数据处理,提供了可组合的异步序列APIFlux和Mono。同时,它也实现了Reactive Streams 规范。
Flux<T>是一个标准的Reactive Streams规范中的Publisher<T>,它代表一个包含了[0…N]个元素的异步序列流。在Reactive Streams规范中,针对流中每个元素,订阅者将会监听这三个事件:onNext、onComplete、onError。
Mono<T>是一个特殊的Flux<T>,它代表一个仅包含1个元素的异步序列流。因为只有一个元素,所以订阅者只需要监听onComplete、onError。
Maven依赖:
<dependency> <groupId>io.projectreactor</groupId> <artifactId>reactor-bom</artifactId> <version>Bismuth-RELEASE</version> <type>pom</type> </dependency> <dependency> <groupId>io.projectreactor</groupId> <artifactId>reactor-core</artifactId> <version>3.3.16.RELEASE</version> </dependency> <dependency> <groupId>io.projectreactor</groupId> <artifactId>reactor-test</artifactId> <version>3.3.16.RELEASE</version> <scope>test</scope> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <version>1.18.12</version> </dependency> |
package com.zx.webflux.reactor; import org.junit.Test; import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; import java.util.Arrays; /** * @Description ReactorDemo * @Author zx * @Date 2021/9/13 9:56 */ public class ReactorDemo { @Test public void test1(){ //发布者 Mono<String> mono = Mono.just("hello mono"); //订阅 mono.subscribe((x) -> System.out.println("1个元素:" + x)); // System.out.println("------------------------------"); // Mono<String> mono1 = Mono.empty(); // mono1.subscribe((x) -> System.out.println("空的元素:" + x)); System.out.println("------------------------------"); //Flux Flux<String> flux1 = Flux.just("hello flux1","hello flux2","hello flux3"); flux1.subscribe((x) -> System.out.println("多个元素:" + x)); System.out.println("------------------------------"); //Flux.fromIterable Flux<String> flux2 = Flux.fromIterable(Arrays.asList("flux1","flux2","flux3")); flux2.subscribe((x) -> System.out.println("多个元素:" + x)); |