点击上方“Java基基”,选择“设为星标”
做积极的人,而不是积极废人!
每天 14:00 更新文章,每天掉亿点点头发...
源码精品专栏
Spring-webflux简介
spring-webflux
是spring在5.0版本后提供的一套响应式编程风格的web开发框架。
这个框架包含了spring-framework
和spring mvc,它可以运行在Netty、Undertow以及3.1版本以上的Serlvet容器上。
你可以在项目中同时使用spring-webmvc
和spring-webflux
,或者只用其中一个来开发web应用。
基于 Spring Boot + MyBatis Plus + Vue & Element 实现的后台管理系统 + 用户小程序,支持 RBAC 动态权限、多租户、数据权限、工作流、三方登录、支付、短信、商城等功能
项目地址:https://gitee.com/zhijiantianya/ruoyi-vue-pro
视频教程:https://doc.iocoder.cn/video/
什么是“响应式”
所谓响应式,举个例子,当调用一个api获取数据时,无需阻塞等待数据返回,而是当有数据返回时会进行告知。可见响应式是非阻塞的,意味着调用方法后,CPU可以去做别的事情,当接收到数据响应时CPU再回来处理,这种方式提高了系统的吞吐量。
而响应式编程,其实是为这种异步非阻塞的流式编程制定的一套标准。流式编程已不陌生了,Java8提供的stream api就是这种风格。这套标准包括对运行环境(JVM、JavaScript)以及网络协议相关的规范。
基于 Spring Cloud Alibaba + Gateway + Nacos + RocketMQ + Vue & Element 实现的后台管理系统 + 用户小程序,支持 RBAC 动态权限、多租户、数据权限、工作流、三方登录、支付、短信、商城等功能
项目地址:https://gitee.com/zhijiantianya/yudao-cloud
视频教程:https://doc.iocoder.cn/video/
Spring-webflux的响应式API
Spring-webflux
框架是基于Reactor这个开源项目开发的。Reactor框架是跟Spring紧密配合的。
它提供了两种API类型,分别是Mono和Flux;
// Mono一般作用于单个对象
Mono<Person> person = personDao.getPerson(personId);
// Flux一般作用于多个对象
Flux<Person> people = personDao.listAllPeople();
尽管webflux框架基于Reactor,它也能与其他的响应式框架同时使用,比如RxJava。
选择Spring-webmvc还是Spring-webflux呢
这两个web框架分别代表着两种不同类型的编程流派,官方给出了一个图作为对比如下
![ff52f571e2f82723114518c4c227f0f9.png](https://i-blog.csdnimg.cn/blog_migrate/7b0ccf357e34abaf65298d58c6751714.png)
根据官方的建议有以下几点可以作为参考:
如果你已经使用了
**Spring-webmvc**
进行开发,并且项目运行良好,就无需更改了;何况现在大多数的三方库都是阻塞的,并不能发挥出非阻塞的优势。**webflux**
提供了相当多的选择;在服务层,可以使用(Netty, Tomcat, Jetty, Undertow, 和3.1版本以上的Servlet容器)作为web服务;在应用层,可以选择用**@Controller**
定义还是使用函数编程定义;在编程风格上,可以选择用Reactor、RxJava或其他。如果你钟爱Java8提供的lambda表达式这种轻量级、函数式的编程风格,那么建议选择用webflux;同时对于一些轻量级应用,或者复杂度比较低的微服务,建议使用webflux以便更好的进行控制。
在微服务架构中,可以将webmvc和webflux项目混合使用。两个框架都可以使用
**@Controller**
这种注解的方式,使得项目的重用更加容易。评估一个项目是否应该选择webflux的最简单的方式是,依据项目中是否会使用很多的阻塞API,比如JDBC或者一些阻塞式的API就不适用与webflux项目。
如果一个webmvc项目中有很多的外部系统调用,可以试试响应式的
**WebClient**
,它能直接从**Controller**
的方法中返回响应式结果。响应式编程的学习路线是比较陡峭的,所以如果你身在一个大型的团队中,要考虑投入的成本;不过可以用用
**WebClient**
来体验下响应式编程。
Spring-webflux
不仅可以支持在Tomcat、Jetty以及3.1版本以上的Servlet容器上,还能够运行在非Servlet的服务器之上,比如Netty、Undertow等。
使用Springboot构建一个webflux应用,默认就是使用Netty,因为Netty本身就是非阻塞式的实现。
并发模型
尽管webmvc和webflux都支持使用注解来定义一个Controller,但是其实现方式完全不同。
webmvc是一个Servlet应用,实现是阻塞式IO,其维护一个线程池来处理每一个用户请求,也就是当Servlet容器启动时,就会创建比如10个线程出来,因此系统吞吐量的瓶颈在于有限的连接数和阻塞的请求处理过程。
webflux可以基于netty这样的NIO网络框架,它只需要很少的几个工作线程(Event loop worker)就能够处理并响应请求。由于无需阻塞等待方法返回,CPU资源就得到了更好的利用。
webflux并不能让程序运行地更快;而是提高了并发处理请求的能力,即提高了系统吞吐量。
webflux代码示例
Talk is cheap, show me the code
下面让我们来看一下webflux的示例,总的来说使用上是非常便捷的。
我们用Springboot构建一个webflux应用非常简单,仅仅需要加入这么一个依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId>
</dependency>
首先定义一个对象
public class Person {
private Integer id;
private Integer age;
private String name;
}
然后定义“PersonController
”,响应式风格中不再使用@RequestMapping
声明地址映射了,而是通过RouterFunctions.route().GET()
方法
@Configuration
public class PersonRouter {
@Resource
private PersonHandler personHandler;
@Bean
public RouterFunction<ServerResponse> personRoutes() {
return RouterFunctions.route()
.GET("/person/{id}", RequestPredicates.accept(MediaType.APPLICATION_JSON), personHandler::getPerson)
.GET("/person", RequestPredicates.accept(MediaType.APPLICATION_JSON), personHandler::listPeople)
.POST("/person", personHandler::createPerson)
.build();
}
}
在PersonHandler
中处理对应的HTTP请求,等同于MVC架构中的Service层
@Component
public class PersonHandler {
@Resource
private PersonRepository personDao;
public Mono<ServerResponse> listPeople(ServerRequest request) {
Flux<Person> people = personDao.listAllPeople();
return ServerResponse.ok()
.contentType(MediaType.APPLICATION_JSON)
.body(people, Person.class);
}
public Mono<ServerResponse> createPerson(ServerRequest request) {
Mono<Person> person = request.bodyToMono(Person.class);
return ServerResponse.ok()
.build(personDao.savePerson(person));
}
public Mono<ServerResponse> getPerson(ServerRequest request) {
int personId = Integer.parseInt(request.pathVariable("id"));
return personDao.getPerson(personId)
.flatMap(person -> ServerResponse.ok().contentType(MediaType.APPLICATION_JSON).bodyValue(person))
.switchIfEmpty(ServerResponse.notFound().build());
}
}
通过启动日志可以证实Spring-webflux
是默认使用Netty提供HTTP服务
![b59f5d09fdf312ed7971ac1a5b31070b.png](https://i-blog.csdnimg.cn/blog_migrate/2c270b235b7266afbb782c9ff48d4861.png)
项目启动之后浏览器访问http://localhost:8080/person/1
就能发现,你的Spring-webflux项目已经正常工作了。
欢迎加入我的知识星球,一起探讨架构,交流源码。加入方式,长按下方二维码噢:
已在知识星球更新源码解析如下:
最近更新《芋道 SpringBoot 2.X 入门》系列,已经 101 余篇,覆盖了 MyBatis、Redis、MongoDB、ES、分库分表、读写分离、SpringMVC、Webflux、权限、WebSocket、Dubbo、RabbitMQ、RocketMQ、Kafka、性能测试等等内容。
提供近 3W 行代码的 SpringBoot 示例,以及超 6W 行代码的电商微服务项目。
获取方式:点“在看”,关注公众号并回复 666 领取,更多内容陆续奉上。
文章有帮助的话,在看,转发吧。
谢谢支持哟 (*^__^*)