基本介绍

https://docs.spring.io/spring/docs/5.0.0.RELEASE/spring-framework-reference/web-reactive.html#webflux-introduction

Spring框架中所包含的最原始的web框架Spring Web MVC,是专门为Servlet API和Servlet容器构建的。而The reactive stack, web framework, Spring WebFlux是在后来Spring5.0版本中添加的,它是完全非阻塞的,支持Reactive Stream及背压,可以运行于Netty、Undertow等服务器,及Servlet 3.1+容器。

 

Spring WebFlux是一套全新的Reactive Web技术栈,实现完全非阻塞,支持Reactive Streams背压等特性,并且运行环境不限于Servlet容器(Tomcat、Jetty、Undertow),如Netty等。

 

https://docs.spring.io/spring/docs/5.0.0.RELEASE/spring-framework-reference/web-reactive.html#webflux-introduction

这两个Web框架都反映了它们的源模块spring-webmvc和spring-webflux的名称,并在Spring Framework中并存。

 

Spring WebFlux与Spring MVC可以共存,在SpringBoot中,Spring MVC优先级更高。

 

动机

https://docs.spring.io/spring/docs/5.0.0.RELEASE/spring-framework-reference/web-reactive.html#webflux-new-framework

 

部分原因是需要一种非阻塞式的Web技术栈,以少量线程处理并发,并使用更少的硬件资源进行伸缩。Servlet 3.1确实提供了用于非阻塞I/O的API。但是,仍然有部分Severlet API存在同步(如Filter,Servlet)或者阻塞(getParameter,getPart)的情况。这是促使新的通用API成为所有非阻塞运行时的基础的动机。而Netty之类的服务器已经以异步,非阻塞的方式很好的运行。(这部分观点不太严谨,tomcat及servlet3.0已支持非阻塞方式)

 

另一部分原因是函数式编程。就像在Java 5中新增的注释功能为开发提供了更多的可能性,而现在带注释的REST控制器或单元测试,以及在Java 8中增加的lambda表达式则为Java中的函数式api创造了基础。

这对于非阻塞应用程序,和由CompletableFuture和ReactiveX推广的api来说是一个福音,可以以声明的方式构成异步逻辑。在编程模型级别上,Java8支持Spring WebFlux提供functional web ednpoints以及带注解的控制器。(这部分观点依然不太严谨,vert.x早就实现了reactive编程,函数式编程)

 

实际动机

从Spring MVC注解驱动的时代开始,Spring官方有意识的去Servlet化,不过在Spring MVC的时代,Spring扔摆脱不了Servlet容器的依赖,然而Spring借助Reactive Programming的势头,WebFlux将Serverlet容器从必须项变为可选项,并且默认采用Netty Web Server作为基础,从而逐渐的形成Spring全新的技术体系,包括数据存储等技术栈。

 

编程模型

注解驱动(Annotated Controllers)

https://docs.spring.io/spring/docs/5.2.8.RELEASE/spring-framework-reference/web-reactive.html#webflux-controller

与spring mvc相同

Spring WebFlux提供了一个基于注解的编程模型,@Controller和@RestController组件使用注解来表示请求映射、请求输入、处理异常等等。

带注释的控制器具有灵活的方法签名,无需扩展基类或实现特定的接口。

 

定义

特性

Spring Web MVC

SpringWebFlux

应用控制器注解声明

@Controller

相同

应用REST控制器注解声明

@RestController

相同

映射

特性

Spring Web MVC

SpringWebFlux

请求映射注解声明

@RequestMapping

相同

GET方法映射

@GetMapping

相同

POST方法映射

@PostMapping

相同

PUT方法映射

@PutMapping

相同

DELETE方法映射

@DeleteMapping

相同

PATCH方法映射

@PatchMapping

相同

请求

特性Spring Web MVCSpringWebFlux

获取请求参数

@RequestParam

相同

获取请求头

@RequestHeader

相同

获取Cookie值

@CookieValue

相同

获取完整请求主体内容

@RequestBody

相同

获取请求路径变量

@PathVariable

相同

获取请求内容(包括请求主体和请求头)

RequestEntity

相同

响应

特性Spring Web MVC

SpringWebFlux

响应主体注解声明

@ResponseBody

相同

响应内容(包括响应主体和响应头)

ResponseEntity

相同

响应Cookie内容

ResponseCookie

相同

拦截

特性Spring Web MVCSpringWebFlux

@Controller注解切面通知

@ControllerAdvice

相同

@ResetController注解切面通知

@RestControlerAdvice

相同

跨域

特性

Spring Web MVCSpringWebFlux

资源跨域声明注解

@CrossOrigin

相同

资源跨域拦截器

CorsFilter

CorsWebFilter

注册资源跨域信息

WebMvcConfigurer#addCorsMappings

WebFluxConfigurer#addCorsMappings

 

函数式端点(Functional Endpoints)

映射路由接口 - RouterFunction

函数映射

RouterFunction<ServerResponse> route = route()
    .GET("/person/{id}", accept(APPLICATION_JSON), handler::getPerson)
    .GET("/person", accept(APPLICATION_JSON), handler::listPeople)
    .POST("/person", handler::createPerson)
    .build();

函数处理接口

public class PersonHandler {

    // ...

    public Mono<ServerResponse> listPeople(ServerRequest request) {
        // ...
    }

    public Mono<ServerResponse> createPerson(ServerRequest request) {
        // ...
    }

    public Mono<ServerResponse> getPerson(ServerRequest request) {
        // ...
    }
}

示例

@SpringBootApplication
public class WebFluxApplication {
    public static void main(String[] args) {
        SpringApplication.run(WebFluxApplication.class, args);
    }

    @Bean
    public RouterFunction<ServerResponse> routerFunction() {

        // mode 1
        return route()
                .GET("/hello-world", accept(MediaType.APPLICATION_JSON)
                        , request -> ServerResponse.status(HttpStatus.OK).body(Mono.just("Hello world"), String.class))
                .build();

        // mode 2
        return route(request -> {
                    URI uri = request.uri();
                    return "/hello-world".equals(uri.getPath());
                },
                request -> ServerResponse.status(HttpStatus.OK).body(Mono.just("Hello,World."), String.class));
    }
}

 

并发模型

 

核心组件

HttpHandler API

HttpHandler是一种带有处理HTTP请求和响应方法的简单契约。

 

接口定义:

public interface HttpHandler {

    /**
     * Handle the given request and write to the response.
     * @param request current request
     * @param response current response
     * @return indicates completion of request handling
     */
    Mono<Void> handle(ServerHttpRequest request, ServerHttpResponse response);

}

 

WebHandler API

Bean nameBean typeCountDescription

<any>

WebExceptionHandler

0..N

Provide handling for exceptions from the chain of WebFilter instances and the target WebHandler. For more details, see Exceptions.

<any>

WebFilter

0..N

Apply interception style logic to before and after the rest of the filter chain and the target WebHandler. For more details, see Filters.

webHandler

WebHandler

1

The handler for the request.

webSessionManager

WebSessionManager

0..1

The manager for WebSession instances exposed through a method on ServerWebExchange. DefaultWebSessionManager by default.

serverCodecConfigurer

ServerCodecConfigurer

0..1

For access to HttpMessageReader instances for parsing form data and multipart data that is then exposed through methods on ServerWebExchange. ServerCodecConfigurer.create() by default.

localeContextResolver

LocaleContextResolver

0..1

The resolver for LocaleContext exposed through a method on ServerWebExchange. AcceptHeaderLocaleContextResolver by default.

forwardedHeaderTransformer

ForwardedHeaderTransformer

0..1

For processing forwarded type headers, either by extracting and removing them or by removing them only. Not used by default.

Web MVC vs WebFlux

执行流程

 

注解驱动(Annotated Controllers)组件请求处理流程

 

1.png

 

2.png

 

Logo

权威|前沿|技术|干货|国内首个API全生命周期开发者社区

更多推荐