前面的文章给大家介绍了 SpringBoot
的应用 web
类型推断,并且结合了 Reactive web
类型给大家分析了一下 SpringBoot
是如何进行 web
类型推断和创建内置 web
服务器的。
有小伙伴在后台留言就问了 Servlet web
我们天天使用很熟悉,那什么是 Reactive web
呢?两者的区别是啥?今天阿粉就给大家介绍一下。
打开 Spring
的官方文档我们在 Reactive
一栏中可以看到下面的架构图,其中可以很明显的看到 Reactive
的技术栈跟 Servlet
技术栈是完全并行的。意思是说我们日常开发的 Servlet web
类型只是一半的内容,还有另外一半世界就是 Reactive
,两者对应的依赖如下所示。
<!--Servlet web 依赖-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!--Reactive web 依赖-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId>
</dependency>
servlet-reactive
通过架构图我们可以知道常用的 Servlet web
就是我们经常说的 Spring MVC
,底层的技术栈支持 JDBC
等,而 Reactive web
就是 Spring WebFlux
底层的持久层支持 Mongo
等但是不支持 JDBC
。
由上图我们看到 Spring WebFlux
是一个异步非阻塞式的 Web
框架,它能够充分利用多核 CPU
的硬件资源去处理大量的并发请求。相对于 Spring MVC
来说的话,Spring MVC
构建于 Servlet API
之上,使用的是同步阻塞式 I/O
模型。
由于 Spring WebFlux
底层是使用响应式编程,基于事件的异步驱动,所以可以在很大程度上提升系统的吞吐量。但是要知道这并不会缩短请求的响应时间,只是提升吞吐量。
而且根据上面的架构图我们可以发现,Spring WebFlux
底层的持久层是不支持 JDBC
的,也就是说不支持 MySQL
等事务性数据库,
前面说了这么多那 Spring WebFlux
到底是怎么开发的呢?下来通过一个简单的 case
来给大家演示一下。在演示之前通过官方文档我们可以发现,Spring WebFlux
和 Spring MVC
是可以共用很多组件的,比如 @Controller
,Tomcat
等,但是也会存在很多差异。
Spring
官方 Reactive
地址为:https://docs.spring.io/spring-framework/docs/current/reference/html/web-reactive.html
springmvc-springwebflux
基于我们之前的 demo-reactive
项目的代码,或者小伙伴也可以在 starter.spring.io
上面下载一个 SpringBoot
的项目代码,增加上 spring-boot-starter-webflux
依赖即可。
定义 DTO
package com.example.reactive.demoreactive.dto;
public class User {
private String name;
private int age;
//省略 getter setter
}
定义 Controller
package com.example.reactive.demoreactive.controller;
import com.example.reactive.demoreactive.dto.User;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
import java.util.ArrayList;
import java.util.List;
@RestController
public class UserController {
@GetMapping("/hello")
public String sayHello() {
return "hello";
}
@GetMapping("/user/get")
public Mono<User> getUser() {
User user = new User();
user.setName("Java极客技术");
user.setAge(18);
return Mono.just(user);
}
@GetMapping("/user/list")
public Flux<List<User>> getAllUser() {
User user = new User();
user.setName("Java极客技术");
user.setAge(18);
List<User> list = new ArrayList<>();
list.add(user);
return Flux.just(list);
}
}
随后启动我们的服务,再通过浏览器访问我们的接口就可以了。
上面三个接口的访问结果如下
hello
user-get
user-list
可以看到我们在浏览器可以正常获取到数据,上面的代码跟我们平时写 SpringMVC
的代码很相似,不太一样的地方是有两个类 Mono
和 FLux
。
关于 Mono 和 Flux 是反应式编程的概念,Mono 是返回 0 或 1 个元素,Flux 是返回 0 - N 个元素,更详细的内容大家可以通过官方文档 https://projectreactor.io/docs/core/release/api/ 来查看
虽然从上面的写法来看,Spring WebFlux
的写法与 SpringMVC
的写法没有很大的区别,但是两者的底层机制是完全不一样的,而且技术栈也不完全相同,所以大家在日常技术选型的时候需要根据实际情况去选择。
阿粉这里给出的建议就是,如果当下的项目就是 SpringMVC
的,那么不要想着换成 Spring WebFlux
架构,因为没必要,如果说要新开发一个项目,需要高吞吐量而且底层也不依赖事务性数据库的话,那么可以尝试使用一下 Spring WebFlux
。