优点:
底层完全基于netty+reactor+springweb
完成的一个全异步,非阻塞的web响应式框架
底层:异步+消息队列(内存) +事件回调机制 = 整个系统
使用少量资源处理大量请求
组件对比:
Mono:返回0/1数据流
Flux:返回n数据流
底层基于netty实现的web容器与请求/响应处理机制
引入依赖pom.xml
父依赖
<parent>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-parentartifactId>
<version>3.1.6version>
parent>
子模块:webflux
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-webfluxartifactId>
dependency>
响应式流程:
背压模式
dao(数据源查询对象:数据包发布者)
–>service–>controller–>浏览器
Context响应式上下文数据传递:由下游传递给上游
大数据流程:从一个数据源拿到大量数据进行分析计算
ProductorVistorDao.loadData()
.distinct()
.map()
.filter()
.handler()
…
.subscribe();//加载最新的商品浏览数据
使用HttpHanlder,HttpServlet原生Reactor-Netty api
编写一个服务器
public static void main(String[] args) throws Exception{
//快速自己编写一个能处理请求的服务器
//1.创建一个能处理http请求的处理器
//参数:请求和响应
//返回值Mono:代表处理完成的信号
HttpHandler handler = (ServerHttpRequest req, ServerHttpResponse resp) -> {
//编写请求处理业务
System.out.println("request entry,uri:" + req.getURI());
//响应给浏览器内容
//数据发布者:Mono,just
//创建响应数据的dataBuffer
DataBufferFactory dataBufferFactory = resp.bufferFactory();
DataBuffer dataBuffer = dataBufferFactory.wrap(String.valueOf(req.getURI()).getBytes());
//需要一个dataBuffer的发布者
return resp.writeWith(Mono.just(dataBuffer));
};
//2.启动一个服务器,监听8080端口,接收数据,拿到数据,交给handler,进行请求
ReactorHttpHandlerAdapter adapter = new ReactorHttpHandlerAdapter(handler);
HttpServer.create()
.host("localhost")
.port(8080)
.handle(adapter)//用指定的处理器处理请求
.bindNow();
System.out.println("server run success");
System.in.read();
}
springMvc: dispatcherServlet
springWebFlux:DispatcherHandler
返回单个数据
@GetMapping("/start")
public Mono<String> returnStr() {
return Mono.just("req success");
}
返回一组数据
@GetMapping("/reqFlux")
public Flux<String> reqFlux () {
return Flux.just("req success1","req success2","req success3");
}
配合Flux完成SSE:server send event(服务端事件推送)
chatGPT在用
@GetMapping(value = "/reqSse",produces = MediaType.TEXT_EVENT_STREAM_VALUE)
public Flux<String> reqSse () {
return Flux.range(1,10)
.map(item -> "req" + item)
.delayElements(Duration.ofMillis(500));
}
@GetMapping("/sseApi")
public Flux<ServerSentEvent<String>>sseApi() {
return Flux.range(1,10)
.map(item -> {
return ServerSentEvent.builder("sse:" + item)
.id(item + "")
.comment("comment")
.event("event")
.build();
})
.delayElements(Duration.ofMillis(500));
}
handlerMappings:
请求映射处理器,保存每个请求有哪个方法进行处理
handlerAdapter:
处理器适配器,反射执行目标方法
handlerResultHandler:
处理器结果处理器
SpringMVC:DispatcherServlet有一个doDispatch()方法处理所有请求
WebFlux:DispatcherHandler有一个handle()方法处理所有请求
@Override
public Mono<Void> handle(ServerWebExchange exchange) {
if (this.handlerMappings == null) {
return createNotFoundError();
}
if (CorsUtils.isPreFlightRequest(exchange.getRequest())) {
return handlePreFlight(exchange);
}
return Flux.fromIterable(this.handlerMappings)//拿到所有的handlerMappings
.concatMap(mapping -> mapping.getHandler(exchange))//找每一个mapping看谁能处理请求
.next()//直接触发获取元素,拿到流的第一个元素,找到第一个能处理请求的handlerApapter
.switchIfEmpty(createNotFoundError())//如果没拿到这个元素,响应404错误
.onErrorResume(ex -> handleDispatchError(exchange, ex))//异常处理,一旦前面发生异常,调用handleDispatchError()处理
.flatMap(handler -> handleRequestWith(exchange, handler));//调用方法处理请求,得到结果
}
流程:
1.请求和响应都封装在ServerWebExchange对象中,由handle方法进行处理
2.如果没有任何请求映射器,直接返回一个:创建一个未犯过错误(404)
private <R> Mono<R> createNotFoundError() {
return Mono.defer(() -> {
Exception ex = new ResponseStatusException(HttpStatus.NOT_FOUND);
return Mono.error(ex);
});//有订阅者且流被激活后动态调用这个方法,延迟加载
}
3.跨域工具检查请求是否是跨域请求
跨域请求检查是否复杂跨域,需要预检请求
4.Flux流式操作:先找到HandlerMapping,再获取handlerApapter,再用adapter处理请求
期间错误由onErrorResume触发回调进行处理
contactMap():先挨个元素变,然后把变的结果按照之前元素的顺序拼接成一个完整的流
核心:
handleRequestWith():编写了handlerAdapter怎么处理请求
handleResult():
@RestControllerAdvice
@Slf4j
public class GlobalExceptionHandler {
@ExceptionHandler(ArithmeticException.class)
public String error(ArithmeticException exception) {
log.error("exception happen:" + exception.getMessage(),exception);
return "server error: " + exception.getMessage();
}
}
controller方法参数 | 描述 |
---|---|
ServerWebExchange | 封装了请求和响应对象的对象 |
@PathVariable | 路径变量 |
@RequestParam | 请求参数 |
@RequestHeader | 请求头 |
@RequestPart | 获取文件上传数据 multipart/form-data |
@EnableWebFlux:开启webFlux自定义
不建议使用,会禁用webFlux默认效果,完全自定义
WebFluxAutoConfiguration的自动配置会默认生效
自定义Flux配置
webFluxConfigurer
容器中注入这个类型的组件,重写底层逻辑
自定义配置
@Configuration
public class WebFluxConfig {
//配置底层
@Bean
public WebFluxConfigurer webFluxConfigurer() {
return new WebFluxConfigurer() {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedHeaders("*")
.allowedMethods("*")
.allowedOrigins("*");
}
};
}
}
自定义过滤器
流一旦经过某些操作之后,会编程新流
public class MyWebFilter implements WebFilter {
@Override
public Mono<Void> filter(ServerWebExchange exchange, WebFilterChain chain) {
ServerHttpRequest request = exchange.getRequest();
ServerHttpResponse response = exchange.getResponse();
//放行
Mono<Void> filter = chain.filter(exchange);
//流一旦经过某个操作就会变成新流
return filter.doFinally(singleType -> {
//目标方法执行之后,要做的事情
})
.doOnError(err -> {
//目标方法发生异常之后做的事情
});
//看清返回的是哪个流
}
}