Java响应式编程-2.Spring Webflux
Spring Webflux
- Reactor核心:HttpHandler 原生API
- DispatcherHandler 原理
- DispatcherHandler 组件分析
- DispatcherHandler 请求处理流程
- 返回结果处理
- 异常处理
- 视图解析
- 重定向
- Rendering
- 注解式 - Controller
- 兼容老版本方式
- 新版本变化
- SSE
- 文件上传
- 错误响应
- @ExceptionHandler
- ErrorResponse: 自定义 错误响应
- ProblemDetail:自定义PD返回
- WebFlux配置
- @EnableWebFlux
- WebFluxConfigurer
WebFlux:底层完全基于netty+reactor+springweb 完成一个全异步非阻塞的web响应式框架
底层:异步 + 消息队列(内存) + 事件回调机制 = 整套系统
优点:能使用少量资源处理大量请求;
组件对比
API功能 | Servlet-阻塞式Web | WebFlux-响应式Web |
---|---|---|
前端控制器 | DispatcherServlet | DispatcherHandler |
处理器 | Controller | WebHandler/Controller |
请求、响应 | ServletRequest、ServletResponse | ServerWebExchange:ServerHttpRequest、ServerHttpResponse |
过滤器 | Filter(HttpFilter) | WebFilter |
异常处理器 | HandlerExceptionResolver | DispatchExceptionHandler |
Web配置 | @EnableWebMvc | @EnableWebFlux |
自定义配置 | WebMvcConfigurer | WebFluxConfigurer |
返回结果 | 任意 | Mono、Flux、任意 |
发送REST请求 | RestTemplate | WebClient |
Mono: 返回0|1 数据流
Flux:返回N数据流
WebFlux
底层基于Netty实现的Web容器与请求/响应处理机制
参照:https://docs.spring.io/spring-framework/reference/6.0/web/webflux.html
引入
1 | <parent> |
Context 响应式上下文数据传递; 由下游传播给上游;
以前: 浏览器 --> Controller --> Service --> Dao: 阻塞式编程
现在: Dao(数据源查询对象【数据发布者】) --> Service --> Controller --> 浏览器: 响应式
1 | //大数据流程: 从一个数据源拿到大量数据进行分析计算; |
Reactor Core
HttpHandler、HttpServer
1 | public static void main(String[] args) throws IOException { |
DispatcherHandler
SpringMVC: DispatcherServlet
SpringWebFlux: DispatcherHandler
- 请求处理流程
- HandlerMapping:请求映射处理器; 保存每个请求由哪个方法进行处理
- HandlerAdapter:处理器适配器;反射执行目标方法
- HandlerResultHandler:处理器结果处理器;
SpringMVC: DispatcherServlet 有一个 doDispatch() 方法,来处理所有请求;
WebFlux: DispatcherHandler 有一个 handle() 方法,来处理所有请求;
1 | public Mono<Void> handle(ServerWebExchange exchange) { |
- 请求和响应都封装在 ServerWebExchange 对象中,由handle方法进行处理
- 如果没有任何的请求映射器; 直接返回一个: 创建一个未找到的错误; 404; 返回Mono.error;终结流
- 跨域工具,是否跨域请求,跨域请求检查是否复杂跨域,需要预检请求;
- Flux流式操作,先找到HandlerMapping,再获取handlerAdapter,再用Adapter处理请求,期间的错误由onErrorResume触发回调进行处理;
源码中的核心两个:
- handleRequestWith: 编写了handlerAdapter怎么处理请求
- handleResult: String、User、ServerSendEvent、Mono、Flux …
concatMap: 先挨个元素变,然后把变的结果按照之前元素的顺序拼接成一个完整流
1 | private <R> Mono<R> createNotFoundError() { |
注解开发
目标方法传参
Controller method argument | Description |
---|---|
ServerWebExchange | 封装了请求和响应对象的对象; 自定义获取数据、自定义响应 |
ServerHttpRequest, ServerHttpResponse | 请求、响应 |
WebSession | 访问Session对象 |
java.security.Principal | |
org.springframework.http.HttpMethod | 请求方式 |
java.util.Locale | 国际化 |
java.util.TimeZone + java.time.ZoneId | 时区 |
@PathVariable | 路径变量 |
@MatrixVariable | 矩阵变量 |
@RequestParam | 请求参数 |
@RequestHeader | 请求头; |
@CookieValue | 获取Cookie |
@RequestBody | 获取请求体,Post、文件上传 |
HttpEntity<B> | 封装后的请求对象 |
@RequestPart | 获取文件上传的数据 multipart/form-data |
java.util.Map, org.springframework.ui.Model, and org.springframework.ui.ModelMap. | Map、Model、ModelMap |
@ModelAttribute | |
Errors, BindingResult | 数据校验,封装错误 |
SessionStatus + class-level @SessionAttributes | |
UriComponentsBuilder | For preparing a URL relative to the current request’s host, port, scheme, and context path. See URI Links. |
@SessionAttribute | |
@RequestAttribute | 转发请求的请求域数据 |
Any other argument | 所有对象都能作为参数:1、基本类型 ,等于标注@RequestParam 2、对象类型,等于标注 @ModelAttribute |
返回值写法
sse和websocket区别:
- SSE:单工;请求过去以后,等待服务端源源不断的数据
- websocket:双工: 连接建立后,可以任何交互
Controller method return value | Description |
---|---|
@ResponseBody | 把响应数据写出去,如果是对象,可以自动转为json |
HttpEntity<B>, ResponseEntity<B> | ResponseEntity:支持快捷自定义响应内容 |
HttpHeaders | 没有响应内容,只有响应头 |
ErrorResponse | 快速构建错误响应 |
ProblemDetail | SpringBoot3 |
String | 就是和以前的使用规则一样;forward: 转发到一个地址redirect: 重定向到一个地址配合模板引擎 |
View | 直接返回视图对象 |
java.util.Map, org.springframework.ui.Model | 以前一样 |
@ModelAttribute | 以前一样 |
Rendering | 新版的页面跳转API; 不能标注 @ResponseBody 注解 |
void | 仅代表响应完成信号 |
Flux<ServerSentEvent>, Observable<ServerSentEvent>, or other reactive type | 使用 text/event-stream 完成SSE效果 |
Other return values | 未在上述列表的其他返回值,都会当成给页面的数据 |
文件上传
1 | class MyForm { |
现在
1 |
|
错误处理
1 |
|
RequestContext
自定义Flux配置
WebFluxConfigurer
容器中注入这个类型的组件,重写底层逻辑
1 |
|
Filter
1 |
|
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 元渊`Blog!
评论