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全新的技术体系,包括数据存储等技术栈。
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 MVC | SpringWebFlux |
获取请求参数 |
@RequestParam |
相同 |
获取请求头 |
@RequestHeader |
相同 |
获取Cookie值 |
@CookieValue |
相同 |
获取完整请求主体内容 |
@RequestBody |
相同 |
获取请求路径变量 |
@PathVariable |
相同 |
获取请求内容(包括请求主体和请求头) |
RequestEntity |
相同 |
响应
特性 | Spring Web MVC | SpringWebFlux |
响应主体注解声明 |
@ResponseBody |
相同 |
响应内容(包括响应主体和响应头) |
ResponseEntity |
相同 |
响应Cookie内容 |
ResponseCookie |
相同 |
拦截
特性 | Spring Web MVC | SpringWebFlux |
@Controller注解切面通知 |
@ControllerAdvice |
相同 |
@ResetController注解切面通知 |
@RestControlerAdvice |
相同 |
跨域
特性 |
Spring Web MVC | SpringWebFlux |
资源跨域声明注解 |
@CrossOrigin |
相同 |
资源跨域拦截器 |
CorsFilter |
CorsWebFilter |
注册资源跨域信息 |
WebMvcConfigurer#addCorsMappings |
WebFluxConfigurer#addCorsMappings |
映射路由接口 - RouterFunction
函数映射
RouterFunctionroute = 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 MonolistPeople(ServerRequest request) { // ... } public Mono createPerson(ServerRequest request) { // ... } public Mono getPerson(ServerRequest request) { // ... } }
示例
@SpringBootApplication public class WebFluxApplication { public static void main(String[] args) { SpringApplication.run(WebFluxApplication.class, args); } @Bean public RouterFunctionrouterFunction() { // 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是一种带有处理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 */ Monohandle(ServerHttpRequest request, ServerHttpResponse response); }
Bean name | Bean type | Count | Description |
|
|
0..N |
Provide handling for exceptions from the chain of |
|
|
0..N |
Apply interception style logic to before and after the rest of the filter chain and the target |
|
|
1 |
The handler for the request. |
|
|
0..1 |
The manager for |
|
|
0..1 |
For access to |
|
|
0..1 |
The resolver for |
|
|
0..1 |
For processing forwarded type headers, either by extracting and removing them or by removing them only. Not used by default. |
执行流程
注解驱动(Annotated Controllers)组件请求处理流程