Spring WebFlux 全异步响应式框架
简介
WebFlux 是一种全异步类的响应式框架,现在已被Spring 归到另一类与 Servlet 同级的Web框架,为了向下兼容,WebFlux 在基础上依然支持 SpringMVC 的部分开发逻辑,但建议使用 Flux 风格的开发逻辑。
WebFlux 是有别于 Servlet 框架外独立开发的一种新的服务器请求框架,因此它严格来说不再使用 Servlet 的接口逻辑,而是使用了属于Flux 的接口逻辑。
具体与 Servlet 的底层逻辑区别如下:
引入WebFlux
我们可以直接依赖WebFlux进行全过程的 Web 服务开发,所以我们不再需要引入 spring-boot-starter-web 依赖,取而代之的是 spring-boot-starter-webflux 依赖。
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId>
</dependency>
另外,Flux 框架默认使用 Netty 而非 Tomcat 了,虽然像 Tomcat,Underton 这些服务器在后期都增加了对 Flux 的支持,但是依然不及 Netty 的原生 Flux 支持,所以基本都使用 Netty 作为 Flux 服务器容器。
开发第一个 Flux 请求
在 Controller 请求上,Flux 与 Servlet 基本无异,虽然在响应请求方面,Flux 支持任意数据类型返回,但是 Flux 建议使用 Mono<> 或 Flux<> 这类对象对数据进行封装返回。
@RestController
public class HelloController {
@GetMapping(value = "/index")
public Mono<String> index(@RequestParam(value = "key",required = false,defaultValue = "hello") String key){
System.out.println("收到请求参数:"+key);
// 对数据进行封装,并返回,当然依然可以使用以往的其它对象直接返回也行
return Mono.just(key);
}
}
SSE 服务器推送响应
SSE,又称 Server Send Event,服务器发送事件,它可以使浏览器在一次请求当中,持续的接收服务器发来的分块数据,边接收边渲染网页,而不是每一次浏览器都要完全接收服务器的数据后才响应网页
在使用 SSE 之前,我们需要靠诉浏览器 header,我们响应的数据是 stream 类型的,可以在 @GetMapping 中指定 header 文档类型
@GetMapping(value = "/index",produces = MediaType.TEXT_EVENT_STREAM_VALUE) // 这是其中之一种,用于推送文本的流类型
因为 Flux 是全异步的框架,所以不存在阻塞机制,数据什么时候处理完,就什么时候发送给浏览器,浏览器接收到一部分就渲染一部分。SSE 只有 Flux 框架才能做到
我们可以让 Flux 数据做延迟派发来模拟数据持续发送的情况:
@GetMapping(value = "/index", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
public Flux<String> index(@RequestParam(value = "key", required = false, defaultValue = "hello") String key) {
/**
* 创建原始数据
* 让这些数据每500毫秒派发一次
*/
Flux<String> data = Flux.range(1, 10)
.delayElements(Duration.ofMillis(500))
.map(v -> v + "-haha");
return data;
}
对于 Flux 来说,任务会每 500 毫秒才会派发一次,那么返回给浏览器,则是每500毫秒接收到一次响应数据。
严格来说,SSE 请求推送,是有一个专用的封装类型 ServerSendEvent 类来处理的,我们可以使用这个类来包装用于 SSE 的数据。
@GetMapping(value = "/index", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
public Flux<ServerSentEvent<String>> index(@RequestParam(value = "key", required = false, defaultValue = "hello") String key) {
/**
* 创建原始数据
* 让这些数据每500毫秒派发一次
*/
Flux<ServerSentEvent<String>> data = Flux.range(1, 10)
.delayElements(Duration.ofMillis(500))
.map(v->{
return ServerSentEvent
.builder(v+"-data")
.id(v+"-id")
.comment(v+"-comment")
.event(v+"event")
.build();
});
return data;
}
效果:
注解开发
目标方法传参
对于在业务方法中,WebFlux 会给我们传入以下的参数:
- ServerWebExchange
- 封装了请求和响应对象的对象; 自定义获取数据、自定义响应。它与 Servlet 不同的是,Servlet 提供 ServletHttpRequest 和 ServletHttpResponse。而 WebFlux 中只提供了 ServerWebExchange ,而 ServerWebExchange 中则已包含 ServerHttpRequesst 和 ServerHttpResponse
- ServerHttpRequest, ServerHttpResponse
- 请求、响应对象
- WebSession
- 访问Session对象
- 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 与以前的ModelAndView 类似的 Model 数据模型
- Errors, BindingResult
- 数据校验,封装错误
- @RequestAttribute
- 转发请求的请求域数据
- 其它参数
- 所有对象都能作为参数:
- 1、基本类型 ,等于标注@RequestParam
- 2、对象类型,等于标注 @ModelAttribute
返回值写法
WebFlux 支持的业务返回值,以下列表中的返回值,会被WebFlux 识别为特殊处理的类型,
- @ResponseBody
- 把响应数据写出去,如果是对象,可以自动转为json
- HttpEntity<B> , ResponseEntity<B>
- ResponseEntity:支持快捷自定义响应内容
- HttpHeaders
- 没有响应内容,只有响应头
- ErrorResponse
- 快速构建错误响应,与 ProblemDetail 差不多的用于构建异常信息返回类,底层调用 ProblemDetail
- ProblemDetail
- SpringBoot3 中新出的一种用于构建异常信息返回类,可以使用这个类来构建错误代码和错误原因,如 code:404 原因:Not Found等
- String
- 就是和以前的使用规则一样;当使用模板引擎时,String 的返回值会被识别为一个html模板的文件名。forward: 转发到一个地址 redirect: 重定向到一个地址
- View
- 直接返回视图对象
- java.util.Map, org.springframework.ui.Model
- 与原来的 Servlet 框架一样
- @ModelAttribute
- 与原来的 Servlet 框架一样
- Rendering
- WebFlux 新增的功能,当使用模板引擎时,可以使用 Rendering 类创建响应页面
- void
- 仅代表响应完成信号,在返回值中为 Mono<Void> 时,则相当于返回一个只有成功信号,无数据的Mono流
- 其它参数
- 未在上述列表的其他返回值,都会当成给页面的数据
文件上传
在以往的 Servlet 框架中,使用 MultipartFile 类型接收上传的文件,而在 WebFlux 中会有所区别
使用 @RequestPart 接收文件上传的参数名,使用 FilePart 来用于接收文件
@PostMapping("/")
public String handle(@RequestPart("meta-data") Part metadata, @RequestPart("file-data") FilePart file) {
// ...
}
当然也可以使用 MultipartFile 来接收,但是 FilePart 与 MultipartFile 有区别,MultipartFile 依然是阻塞式的,而 FilePart 使用无拷贝式,性能会更快,更适合在 WebFlux 这种响应式编程框中使用。
RequestContext
WebFluxConfigurer 自定义配置
Filter 过滤器



共有 0 条评论