关于java:一直在用SpringMVC不妨认识下SpringWebflux

30次阅读

共计 3590 个字符,预计需要花费 9 分钟才能阅读完成。

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> person = personDao.getPerson(personId);
// Flux 个别作用于多个对象
Flux<Person> people = personDao.listAllPeople();

只管 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

上面让咱们来看一下 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 服务

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

正文完
 0