首页 > 其他分享 >响应式的 WebFlux 框架更优雅,性能更强!

响应式的 WebFlux 框架更优雅,性能更强!

时间:2024-02-01 23:32:31浏览次数:22  
标签:更强 响应 WebFlux 编程 webflux 阻塞 优雅 person Spring

spring-webflux是spring在5.0版本后提供的一套响应式编程风格的web开发框架。

这个框架包含了spring-framework和spring mvc,它可以运行在Netty、Undertow以及3.1版本以上的Serlvet容器上。

你可以在项目中同时使用spring-webmvcspring-webflux,或者只用其中一个来开发web应用。

所谓响应式,举个例子,当调用一个api获取数据时,无需阻塞等待数据返回,而是当有数据返回时会进行告知。

可见响应式是非阻塞的,意味着调用方法后,CPU可以去做别的事情,当接收到数据响应时CPU再回来处理,这种方式提高了系统的吞吐量。

而响应式编程,其实是为这种异步非阻塞的流式编程制定的一套标准。





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框架分别代表着两种不同类型的编程流派,官方给出了一个图作为对比如下

响应式的 WebFlux 框架更优雅,性能更强!_mvc


根据官方的建议有以下几点可以作为参考:

  • 如果你已经使用了 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服务

响应式的 WebFlux 框架更优雅,性能更强!_mvc_02

项目启动之后浏览器访问http://localhost:8080/person/1就能发现,你的Spring-webflux项目已经正常工作了。


最后说一句(求关注!别白嫖!)

如果这篇文章对您有所帮助,或者有所启发的话,求一键三连:点赞、转发、在看。

关注公众号:woniuxgg,在公众号中回复:笔记  就可以获得蜗牛为你精心准备的java实战语雀笔记,回复面试、开发手册、有超赞的粉丝福利!

标签:更强,响应,WebFlux,编程,webflux,阻塞,优雅,person,Spring
From: https://blog.51cto.com/u_16502039/9537582

相关文章

  • const copyStories = [...stories] 和 let storiesToDisplay = stories.slice(); 两
    constcopyStories=[...stories]和letstoriesToDisplay=stories.slice();两种复制数组的方式,哪种更优雅?在JavaScript中,constcopyStories=[...stories](使用扩展运算符)和letstoriesToDisplay=stories.slice()都可以用来复制数组,并且都能生成一个新的数组。这两种......
  • Java连接kubernates集群最优雅的两种方式
    创建maven工程,pom.xml中引入连接k8s的客户端jar包:<properties><maven.compiler.source>8</maven.compiler.source><maven.compiler.target>8</maven.compiler.target><fabric.io.version>6.10.0</fabric.io.version></properties......
  • 优雅的实现接口防刷,最强方案来了~!
    1前言本文为描述通过Interceptor以及Redis实现接口访问防刷Demo这里会通过逐步找问题,逐步去完善的形式展示2原理通过ip地址+uri拼接用以作为访问者访问接口区分通过在Interceptor中拦截请求,从Redis中统计用户访问接口次数从而达到接口防刷目的如下图所示3工程其中,Interceptor处代码......
  • 新来的一个同事,把SpringBoot参数校验玩的那叫一个优雅
    介绍在开发现代应用程序时,数据验证是确保用户输入的正确性和应用程序数据完整性的关键方面。SpringBoot提供了强大的数据验证机制,使开发者能够轻松地执行验证操作。本文将深入介绍SpringBoot中的Validation,以及如何在应用程序中正确使用它。为什么使用数据验证?1.用户输......
  • Python设计模式:你的代码真的够优雅吗?
    当涉及到代码优化时,Python作为一种高级编程语言,具有广泛的应用领域和强大的功能。在软件开发中,设计模式是一种被广泛采用的解决问题的方案,它提供了一种在特定情境中重复使用的可行方案。在Python中,有许多设计模式可以用来优化代码。其中两种常见的设计模式是单例模式和工厂模式。......
  • Spark Streaming程序优雅关闭
    流式任务需要7*24小时执行,但是有时涉及到升级代码需要主动停止程序,但是分布式程序,没办法做到一个个进程去杀死,所有配置优雅的关闭就显得至关重要了。使用外部文件系统来控制内部程序关闭。其实就是单独起一个线程专门去专门查找程序是否停止的标志importjava.net.URIimport......
  • 如何在word中优雅地插入代码
    如何在word中优雅地插入代码呢?网上的方法大致有这么几种:利用notepad++来实现(操作路径有点长,比较麻烦)自己在word做模版(这个模版折腾下来倒是可以一劳永逸,但是不支持不同语言的高亮)利用word的宏来实现,但需要写宏脚本(比较麻烦)国外的 www.planetb.ca 网站进去太慢了,体验很不......
  • springboot中优雅的个性定制化错误页面+源码解析
    boot项目的优点就是帮助我们简化了配置,并且为我们提供了一系列的扩展点供我们使用,其中不乏错误页面的个性化开发。理解错误响应流程我们来到org.springframework.boot.autoconfigure.web.servlet.error下的ErrorMvcAutoConfiguration这里面配置了错误响应的规则。主要介绍里面注册......
  • SpringBoot引入SpEL,优雅控制复杂权限!
    对于在Springboot中,利用自定义注解+切面来实现接口权限的控制这个大家应该都很熟悉,整体来说思路如下:自定义一个权限校验的注解,包含参数value配置在对应的接口上定义一个切面类,指定切点在切入的方法体里写上权限判断的逻辑然而,在实际的开发中,对于权限校验的需求场景是很多的,比如:傻眼......
  • 教你如何优雅地解决.sync语法糖不支持的问题!
    在Vue3中,.sync修饰符已经被移除。在Vue2中,.sync修饰符是一个语法糖,用于简化子组件和父组件之间的双向数据绑定。在Vue3中,推荐使用v-model或是自定义事件来实现类似的功能。以下是如何在Vue3中替代.sync的两种方法:使用v-model在Vue3中,v-model可以在自定义组......