• 求求你别在用SpringMVC了,太Low了,Spring又官宣了一个更牛逼的替代框架


    Spring-webflux简介

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

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

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

    什么是“响应式”

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

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

    Spring-webflux的响应式API

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

    它提供了两种API类型,分别是Mono和Flux;

    // Mono一般作用于单个对象
    Mono person = personDao.getPerson(personId);
    // Flux一般作用于多个对象
    Flux people = personDao.listAllPeople();
    
    • 1
    • 2
    • 3
    • 4

    尽管webflux框架基于Reactor,它也能与其他的响应式框架同时使用,比如RxJava。

    选择Spring-webmvc还是Spring-webflux呢

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

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

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

    下面让我们来看一下webflux的示例,总的来说使用上是非常便捷的。

    我们用Springboot构建一个webflux应用非常简单,仅仅需要加入这么一个依赖

    
     org.springframework.boot
     spring-boot-starter-webflux
    
    
    • 1
    • 2
    • 3
    • 4

    首先定义一个对象

    public class Person {
        private Integer id;
        private Integer age;
        private String name;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5

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

    @Configuration
    public class PersonRouter {
        @Resource
        private PersonHandler personHandler;
        @Bean
        public RouterFunction 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();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    PersonHandler 中处理对应的HTTP请求,等同于MVC架构中的Service层

    @Component
    public class  PersonHandler {
    
        @Resource
        private PersonRepository personDao;
    
        public Mono listPeople(ServerRequest request) {
            Flux people = personDao.listAllPeople();
            return ServerResponse.ok()
                    .contentType(MediaType.APPLICATION_JSON)
                    .body(people, Person.class);
        }
    
        public Mono createPerson(ServerRequest request) {
            Mono person = request.bodyToMono(Person.class);
            return ServerResponse.ok()
                    .build(personDao.savePerson(person));
        }
    
        public Mono 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());
        }
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27

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

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

  • 相关阅读:
    springboot供应商管理系统毕业设计源码121518
    java毕业设计个人博客系统mybatis+源码+调试部署+系统+数据库+lw
    [JS]每个月多少天
    Day34|贪心算法|分发糖果
    徒手撸设计模式-观察者模式
    Symbol基本数据类型
    基于分布式光纤侦听技术的岛礁近岸防卫监测
    FreeRTOS教程2 任务管理
    专访句子互动CMO张佳:私域运营是一种更高效的用户触达渠道
    uboot源码分析(基于S5PV210)之启动第一阶段
  • 原文地址:https://blog.csdn.net/band_mmbx/article/details/126364922