热爱可抵漫长岁月

文章目录

  • 1. 前言
  • 2. Spring-webflux简介
  • 3. 什么是“响应式”
  • 4. Spring-webflux的响应式API
  • 5. Spring MVC 还是 WebFlux?
  • 6. 并发模型
  • 7. webflux使用
  • 8. 测试

1. 前言

Spring 提供了两个并行堆栈。一种是基于带有 Spring MVC 和 Spring Data 结构的 Servlet API。另一个是完全反应式堆栈,它利用了 Spring WebFlux 和 Spring Data 的反应式存储库。在这两种情况下,Spring Security 都提供了对两种堆栈的支持。

反应式宣言

2. Spring-webflux简介

Spring WebFlux 是在 5.0 版中添加的。它是完全无阻塞的,支持 Reactive Streams背压,并且可以在 Netty、Undertow 和 Servlet 3.1+ 容器等服务器上运行。

Spring-webflux官网

3. 什么是“响应式”

所谓响应式,举个例子,当调用一个api获取数据时,无需阻塞等待数据返回,而是当有数据返回时会进行告知。可见响应式是非阻塞的,意味着调用方法后,CPU可以去做别的事情,当接收到数据响应时CPU再回来处理,这种方式提高了系统的吞吐量。

而响应式编程,其实是为这种异步非阻塞的流式编程制定的一套标准。流式编程已不陌生了,Java8提供的stream api就是这种风格。这套标准包括对运行环境(JVM、JavaScript)以及网络协议相关的规范。

和传统的阻塞式servlet容器不一样。响应式容器能进一步提高资源的利用率,避免线程长时间处于等待状态,能以较少的线程处理更多的请求,缺点是整个处理链路必须是异步的,是基于事件响应的,不能阻塞事件线程,不然服务器性能会急剧下降,当然spring webflux并不能完整的替代传统的阻塞式容器,可根据需求进行选型。

应用案例Geteway

所有微服务的请求都会通过网关,如果采用mvc 对于并发量有一定的瓶颈。

4. Spring-webflux的响应式API

Spring-webflux框架是基于Reactor这个开源项目开发的。Reactor框架是跟Spring紧密配合的。

里边提供了两种API类型,分别是MonoFlux

  • Mono表示0 或 1个元素,
  • Flux表示0 至 N个元素,

5. Spring MVC 还是 WebFlux?

这两个web框架分别代表着两种不同类型的编程流派,官方给出了一个图作为对比如下

建议考虑以下具体点:

  • 如果您有一个运行良好的 Spring MVC 应用程序,则无需更改。命令式编程是编写、理解和调试代码的最简单方法。您可以选择最多的库,因为从历史上看,大多数都是阻塞的

  • Spring WebFlux 提供与该领域中其他人相同的执行模型优势,并且还提供服务器选择(Netty、Tomcat、Jetty、Undertow 和 Servlet 3.1+ 容器)、编程模型(带注释的控制器和功能性 Web 端点)的选择,以及反应库(Reactor、RxJava 或其他)的选择。

  • 如果您对用于 Java 8 lambda 或 Kotlin 的轻量级、功能性 Web 框架感兴趣,您可以使用 Spring WebFlux 功能性 Web 端点。对于要求不那么复杂的小型应用程序或微服务来说,这也是一个不错的选择,它们可以从更高的透明度和控制中受益。

  • 在微服务架构中,您可以混合使用带有 Spring MVC 或 Spring WebFlux 控制器或带有 Spring WebFlux 功能端点的应用程序。在两个框架中都支持相同的基于注释的编程模型,可以更轻松地重用知识,同时为正确的工作选择正确的工具。

  • 评估应用程序的一种简单方法是检查其依赖关系。如果您要使用阻塞持久性 API(JPA、JDBC)或网络 API,那么 Spring MVC 至少是常见架构的最佳选择。Reactor 和 RxJava 在单独的线程上执行阻塞调用在技术上是可行的,但您不会充分利用非阻塞 Web 堆栈。

  • 如果您有一个调用远程服务的 Spring MVC 应用程序,请尝试响应式WebClient. 您可以直接从 Spring MVC 控制器方法返回反应类型(Reactor、RxJava或其他)。每个呼叫的延迟或呼叫之间的相互依赖性越大,好处就越显着。Spring MVC 控制器也可以调用其他响应式组件。

  • 如果您有一个大型团队,请记住向非阻塞、函数式和声明式编程转变的陡峭学习曲线。在没有完全开关的情况下启动的一种实用方法是使用 reactive WebClient。除此之外,从小处着手并衡量收益。我们预计,对于广泛的应用,这种转变是不必要的。如果您不确定要寻找什么好处,请先了解非阻塞 I/O 的工作原理(例如,单线程 Node.js 上的并发性)及其影响。

其次: webflux兼容大部分springmvc的注解,也可以像mvc那样创建controller处理请求。

区别:

  • WebFlux是完全异步非阻塞的,SpringMVC是同步阻塞的。
  • WebFlux采用异步响应式编程,SpringMVC采用命令式编程。
  • WebFlux由于完全异步,所有操作数据库的框架,以及数据库也都要求是支持异步的,所以目前不支持Mybatis、不支持Oracle数据库。

6. 并发模型

尽管webmvcwebflux都支持使用注解来定义一个Controller,但是其实现方式完全不同。

webmvc是一个Servlet应用,实现是阻塞式IO,其维护一个线程池来处理每一个用户请求,也就是当Servlet容器启动时,就会创建比如10个线程出来,因此系统吞吐量的瓶颈在于有限的连接数和阻塞的请求处理过程。

webflux可以基于netty这样的NIO网络框架,它只需要很少的几个工作线程(Event loop worker)就能够处理并响应请求。由于无需阻塞等待方法返回,CPU资源就得到了更好的利用。

webflux并不能让程序运行地更快;而是提高了并发处理请求的能力,即提高系统吞吐量

7. webflux使用

pom依赖:

<dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-webflux</artifactId><version>2.5.9</version></dependency>
</dependencies>

定义对象:

public class Person {private Integer id;private Integer age;private String name;public Person(Integer id, Integer age, String name) {this.id = id;this.age = age;this.name = name;}public Person() {}public Integer getId() {return id;}public void setId(Integer id) {this.id = id;}public Integer getAge() {return age;}public void setAge(Integer age) {this.age = age;}public String getName() {return name;}public void setName(String name) {this.name = name;}@Overridepublic String toString() {return "Person{" +"id=" + id +", age=" + age +", name='" + name + '\'' +'}';}
}

然后定义PersonController,响应式风格中不再使用@RequestMapping声明地址映射,而是通过RouterFunctions.route().GET()方法:

@Configuration
public class PersonRouter {@Resourceprivate PersonHandler personHandler;@Beanpublic 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 {@Resourceprivate IPersonDao personDao;public Mono<ServerResponse> listPeople(ServerRequest request) {Flux<Person> people = personDao.getList();return ServerResponse.ok().contentType(MediaType.APPLICATION_JSON).body(people, Person.class);}public Mono<ServerResponse> createPerson(ServerRequest request) {return request.bodyToMono(Person.class).flatMap(i -> personDao.savePerson(i)).flatMap(p -> ServerResponse.ok().bodyValue(p));}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());}
}

IPersonDao

public interface IPersonDao {/*** 获取所有person* @author: yh* @date: 2022/9/4* @return Flux<Person>*/Flux<Person> getList();/*** 保存对象* @param person person* @author: yh* @date: 2022/9/4* @return Mono<Void>*/Mono<Void> savePerson(Person person);/*** 根据id查询* @param id id* @author: yh* @date: 2022/9/4* @return Mono<Person>*/Mono<Person> getPerson(Integer id);
}

PersonDao

@Component
public class PersonDao implements IPersonDao {private final List<Person> personList = new ArrayList<>();public PersonDao() {this.personList.add(new Person(1, 17, "张三"));this.personList.add(new Person(2, 18, "李四"));}@Overridepublic Flux<Person> getList() {return Flux.fromIterable(personList);}@Overridepublic Mono<Void> savePerson(Person person) {personList.add(person);System.out.println("personList.size = " + personList);return Mono.empty();}@Overridepublic Mono<Person> getPerson(Integer id) {return Mono.justOrEmpty(personList.stream().filter(p -> p.getId().equals(id)).findFirst());}
}
@SpringBootApplication
@EnableWebFlux
public class SpringWebfluxSessionApplication implements WebFluxConfigurer {public static void main(String[] args) {SpringApplication.run(SpringWebfluxSessionApplication.class, args);}
}

8. 测试

通过启动日志可以证实Spring-webflux是默认使用Netty提供HTTP服务

GET请求:http://127.0.0.1:8080/person

POST请求:http://127.0.0.1:8080/person

boyd:

{"id": 9,"age": 17,"name": "张三"
}

控制台输出:

GET请求:http://127.0.0.1:8080/person/9


完整代码已上传 Gitee Spring整合常用组件

到此,本章内容就介绍完啦,如果有帮助到你 欢迎点个赞

Spring-webflux 响应式编程相关推荐

  1. Spring Webflux 响应式编程 (二) - WebFlux编程实战

    第一章 Reactive Stream 第1节 jdk9的响应式流 就是reactive stream,也就是flow.其实和jdk8的stream没有一点关系.说白了就一个发布-订阅模式,一共只有4 ...

  2. Spring WebFlux 响应式编程学习笔记(一)

    各位Javaer们,大家都在用SpringMVC吧?当我们不亦乐乎的用着SpringMVC框架的时候,Spring5.x又悄(da)无(zhang)声(qi)息(gu)的推出了Spring WebFl ...

  3. Spring web-flux 响应式编程

    1.基于传统的结构 Demo (仅仅作为快速了解,生产环境不会用这种) 请求处理类 Controller 类 package com.yootk.webflux.handler; import org ...

  4. Spring:Webflux响应式编程

    目录 简介 响应式编程 Reactor 信号 操作符 SpringWebflux 执行流程和API 注解实现SpringWebflux 说明:基于atguigu学习笔记. 简介 Webflux是 Sp ...

  5. Spring WebFlux – SpringReact式编程

    Spring WebFlux is the new module introduced in Spring 5. Spring WebFlux is the first step towards re ...

  6. WebFlux响应式编程

    文章目录 概要 入门WebFlux WebClient 概要 在SpringMvc框架下,http的请求是同步的,在某些场景下为了提供性能,可以采用异步的方式来进行优化.WebFlux便是提供了异步的 ...

  7. WebFlux响应式编程基础之 4 reactive stream 响应式流

    reactive stream 响应式流 - 简而言之,就是多了一个沟通的渠道 发布订阅者 背压 交流 Reactive Stream主要接口 java.util.concurrent.Flow 源码 ...

  8. WebFlux响应式编程基础之 2 函数式编程 工具jclasslib bytecode viewer

    函数式编程:告诉他的功能是什么,而不是告诉他怎么做 命令式编程:怎么去做 函数式编程:不需要关注细节,利用系统已经有的API 使用jdk8自带函数接口的好处 函数接口减少接口定义 函数式接口链式操作 ...

  9. WebFlux响应式编程基础之 5 webflux服务端开发讲解

    https://blog.csdn.net/qq_27093465/article/details/64124330 debug技巧 第5章 webflux服务端开发讲解 Spring5 非组塞的开发 ...

  10. flux服务器推消息,在Spring WebFlux响应式处理程序中发送JMS消息:它是否阻塞?

    这是反应性处理的正确方法吗?我看到2个线程一个反应性的nio,直到并包括flatMap(fareRepo :: save).另一个线程是计算线程,它从发送消息开始,一直持续到ServerRespons ...

最新文章

  1. Attribute在拦截机制上的应用
  2. 吴裕雄 Bootstrap 前端框架开发——Bootstrap 辅助类:表格单元格使用了 bg-primary 类...
  3. 如何在vue中使用图形验证码
  4. 静态变量(static)
  5. 常用作业定义的T-SQL模板.sql
  6. 用户ID生成唯一邀请码的几种方法
  7. pcl之编译VTK时CMAKE中找不到Qt5X11Extras
  8. C语言程序设计实践 4.4车牌号
  9. 微服务下蓝绿发布、滚动发布、灰度发布等方案,必须懂!
  10. android如何设置qq邮箱格式,邮件客户端和手机设置QQ邮箱IMAP服务
  11. React Suspense lazy
  12. 大学生笔记本购买指南——扫盲版(2019)
  13. 蚁群算法(ant system,AS)
  14. 技术博客1鸿蒙系统和安卓的区别有哪些
  15. Docker安装部署及使用
  16. 百度APP核心技术:Android多子view嵌套最佳通用解决方案
  17. 《Photoshop Lab修色圣典(修订版)》目录—导读
  18. Volatile重排序规则的一些理解
  19. 图像的采样与量化像素的空间关系图像文件的类型—数字图像处理
  20. PLM是做题家吗?一文速览预训练语言模型数学推理能力新进展

热门文章

  1. 锐捷校园网登录---Linux
  2. 穿越鸿蒙电视剧,7部“爆款”穿越甜宠剧,你若一部都没看过,那是真落伍了!...
  3. Graphql Instrumentation
  4. 聊聊互联网产品的分类
  5. Unified Functional Testing(UFT)15.0.2入门保姆级教程(一),图文详解。QTP
  6. 最大熵阈值python_【6】python-opencv3教程:阈值分割(全阈值分割,局部阈值分割,直方图技术法,熵算法,自适应算法,Otsu算法)...
  7. 安卓设备远程管理软件
  8. C语言打开记事本文件,并向记事本写入字符串,跨程序向cmd命令行窗口写入字符串执行命令
  9. MySQL添加用户及用户权限管理
  10. 【概率论与数理统计】第三章知识点复习与习题