工程地址,分支為reactive-stack
。
Web層的Reactive:Spring WebFlux
Spring WebFlux是異步的非阻塞的
傳統的Spring MVC基于Servlet,是阻塞式的,每次請求由一個線程處理;而Spring WebFlux通過事件循環Event Loop
的方式,由單個線程非阻塞的處理事件。當需要處理耗時任務時,Event Loop
綁定的線程會新啟線程來執行,完成后通知Event Loop
。
與Spring MVC的關系
Spring WebFlux
- Spring MVC基于Servlet API,需要運行在Servlet容器中,如Tomcat。
- Spring WebFlux不依賴于Servlet API,可以運行在基于Netty等網絡服務器上。
- 用在
Controller
層的注解,如@Controller
,@RequestMapping
等是通用的。
使用Spring WebFlux
- 引入依賴
spring-boot-starter-webflux
內置的服務器是Netty,而不是Tomcat。
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId>
</dependency>
- 全流程Reactive技術棧
從Controller到Service、Repository層,都采用Reactive模式。每一層的數據都返回Flux
或Mono
類型,框架會自動調用subscribe
方法,以使數據流動。
全流程Reactive
Repository層的Reactive
目前支持Reactive模式的數據存儲只有Redis,MongoDB等,傳統的關系型數據庫和相應的JDBC驅動還不支持。
但是可以將Repository返回的模型或集合轉換為Reactive類型:
- 集合 -> Flux<T> : 通過
fromIterable
等方法 - 模型 -> Mono<T> : 通過
just
方法
List<Person> personList = personRepository.findAll();
Flux<Person> personFlux = Flux.fromIterable(personList);
也可以將Flux或Mono中的數據元素提取出來,即轉換為傳統模型:
- Flux<T> -> 集合 : 通過
toIterable
等方法 - Mono<T> -> 模型 : 通過
block
方法
Iterable<Person> personIterable = personFlux.toIterable();
Person person = personMono.block();
注意:
toIterable()
,block()
等提取數據的方式都是阻塞的。
當然,要實現全流程的Reactive模式,需要MongoDB等文檔數據庫。
上述的類型轉換是在已有傳統關系型數據庫,無法換庫時采用的方案,即在Repository層仍然是非Reactive模式的,在Service層將模型或集合轉換為Reactive類型,這樣在Controller層可以使用。