Webflux
概要:底层完全基于netty+reactor+springweb 完成一个全异步非阻塞的web响应式框架。异步+消息队列(内存)+事件回调机制 = 整套系统,能使用少量资源处理大量请求。
- 依赖引入
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.5.3</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId>
</dependency>
原生API写法启动Webflux(Reactive Core)
public class SpringWebfluxProjectApplication {
public static void main(String[] args) throws IOException {
// 创建一个能处理Http请求的处理器。参数:请求、响应、返回值。
HttpHandler httpHandler = (ServerHttpRequest request, ServerHttpResponse response)->{
System.out.println("请求进来了"+request.getURI());
System.out.println("当前线程"+Thread.currentThread());
// 编写请求处理的业务,给浏览器写一个内容
response.getHeaders(); // 获取响应头
response.getCookies(); // 获取cookies
response.getStatusCode(); // 获取响应状态码
// response.bufferFactory(); // buffer工厂
DataBufferFactory factory = response.bufferFactory();
DataBuffer buffer = factory.wrap( new String(request.getURI().toString()).getBytes());
// response.setComplete();// 响应结束
return response.writeWith(Mono.just(buffer)); // 把数据写出去到网页
};
//启动一个服务器,监听8080端口,接收数据,拿到数据交给HttpHandler处理
ReactorHttpHandlerAdapter adapter = new ReactorHttpHandlerAdapter(httpHandler);
// 启动Netty服务器
HttpServer.create()
.host("localhost")
.port(8080)
.handle(adapter)
.bindNow();
System.out.println("服务器启动完成...监听8080端口");
System.in.read();
System.out.println("服务器结束");
}
}
使用Spring的方式启动
- 自己要pom依赖拉入的是webflux依赖,那么他就是用netty启动。他和spring-boot-starter-web冲突的。两个选一个,他也向下兼容,springMvc部分写法还是一样。
@SpringBootApplication
public class SpringWebfluxApplication {
public static void main(String[] args) throws IOException {
SpringApplication.run(SpringWebfluxApplication.class,args);
}
}
@RestController
public class HelloController {
// WebFlux; 向下兼容原来SpringMvc的大多数注解和API
@GetMapping("/hello")
public String hello(){
return "hello world !";
}
// 推荐
// 返回单个对象就用Mono
// 返回多个数据就用Flux
@GetMapping("/haha")
public Mono<String> haha(){
return Mono.just("哈哈");
}
@GetMapping("/hehe")
public Flux<String> hehe(){
return Flux.just("呵呵","呵呵呵");
}
// 配合Flux,完成 SSE, Server Send Event 服务端事件推送
// SSE测试: chatgpt再用,服务端推送
@GetMapping(value = "/sse",produces = MediaType.TEXT_EVENT_STREAM_VALUE)
public Flux sse(){
return Flux.range(0,10)
.map(i->"ha-"+i)
.delayElements(Duration.ofMillis(500));
}
}
DispatcherHandler
- SpringMvc:使用的是DispatcherServlet中的DoDispatch()方法处理所有请求。
- SpringWebflux:使用是DispatcherHandler中的handle()方法处理请求。
// 处理器映射器 每个请求由哪个方法处理
@Nullable
private List<HandlerMapping> handlerMappings;
// 处理器适配器 反射执行目标方法
@Nullable
private List<HandlerAdapter> handlerAdapters;
// 处理器结果处理器
@Nullable
private List<HandlerResultHandler> resultHandlers;
- Handle()方法
public Mono<Void> handle(ServerWebExchange exchange) {
// 如果没有找到对应的请求映射器,返回一个404 Mono.error
if (this.handlerMappings == null) {
return this.createNotFoundError();
} else {
// CorsUtils检查是否跨域请求
return CorsUtils.isPreFlightRequest(exchange.getRequest()) ? this.handlePreFlight(exchange) :
// concatMap遍历获取能处理该请求的mapping
// next拿到流的第一个元素,即如果以后多个handler能处理该请求,则拿第一个handlerAdapter
// switchIfEmpty 如果每日以后拿到元素。则返回404
// onErrorResume 异常处理
// flatMap 如果有元素,则直接调用方法处理请求
Flux.fromIterable(this.handlerMappings).concatMap((mapping) -> {
return mapping.getHandler(exchange);
}).next().switchIfEmpty(this.createNotFoundError()).onErrorResume((ex) -> {
return this.handleResultMono(exchange, Mono.error(ex));
}).flatMap((handler) -> {
return this.handleRequestWith(exchange, handler);
});
}
}
private <R> Mono<R> createNotFoundError() {
//defer 有订阅者,且流被激活以后,就动态调用该方法
return Mono.defer(() -> {
Exception ex = new ResponseStatusException(HttpStatus.NOT_FOUND);
return Mono.error(ex);
});
}
- HandlerRequestWith【编写HandlerAdapter怎么处理请求】\
private Mono<Void> handleRequestWith(ServerWebExchange exchange, Object handler) {
if (ObjectUtils.nullSafeEquals(exchange.getResponse().getStatusCode(), HttpStatus.FORBIDDEN)) {
return Mono.empty();
} else {
if (this.handlerAdapters != null) {
Iterator var3 = this.handlerAdapters.iterator();
while(var3.hasNext()) {
HandlerAdapter adapter = (HandlerAdapter)var3.next();
if (adapter.supports(handler)) {
Mono<HandlerResult> resultMono = adapter.handle(exchange, handler);
return this.handleResultMono(exchange, resultMono);
}
}
}
return Mono.error(new IllegalStateException("No HandlerAdapter: " + String.valueOf(handler)));
}
}
- HandlerResult【处理返回结果】
private Mono<Void> handleResult(ServerWebExchange exchange, HandlerResult handlerResult, String description) {
if (this.resultHandlers != null) {
Iterator var4 = this.resultHandlers.iterator();
while(var4.hasNext()) {
HandlerResultHandler resultHandler = (HandlerResultHandler)var4.next();
if (resultHandler.supports(handlerResult)) {
description = description + " [DispatcherHandler]";
return resultHandler.handleResult(exchange, handlerResult).checkpoint(description);
}
}
}
return Mono.error(new IllegalStateException("No HandlerResultHandler for " + String.valueOf(handlerResult.getReturnValue())));
}
目标方法传参
// ServerWebExchange 封装了请求和响应对象。 自定义获取request和Response
// WebSession 直接写到方法里可以获取session
// HttpMethod 是获取请求方式
// @PathVariable 获取路径变量
// MatrixVariable 获取矩阵变量
// @RequestParam 获取请求参数
// @RequestHeader 获取请求头内参数的
// @CookieValue 获取Cookie的value的
// @RequestBody 获取请求体的
// HttpEntity 获取请求头和请求体,他是header和body的封装
// @RequestPart 获取文件上传的数据 multipart/form-data
// @ModelAttribute 将请求体封装到对象上
@GetMapping("/getWebExchange")
public String webExchange(ServerWebExchange exchange,
WebSession webSession,
HttpMethod method,
@PathVariable(value = "id") Integer id,
@RequestParam HashMap<String,Integer> params,
@RequestHeader(value = "Contnet-Type",required = false) String header,
@CookieValue(value = "userInfo",required = false) String cookie,
@RequestBody Object objectBody,
HttpEntity<String> httpEntity,
@RequestPart MultipartFile file,
@ModelAttribute Object object,
){
ServerHttpRequest request = exchange.getRequest();
ServerHttpResponse response = exchange.getResponse();
Object data = webSession.getAttribute("data");
String methodName = method.name();
httpEntity.getHeaders();
httpEntity.getBody();
return null;
}
自定义flux配置
@Configuration
public class webFluxConfig {
// 配置底层 类似于 WebMvcConfig
@Bean
public WebFluxConfigurer webFluxConfigurer(){
return new WebFluxConfigurer(){
// 配置跨域
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedHeaders("*")
.allowedMethods("*")
.allowedOrigins("*");
}
};
}
}
Filter用法
@Component
public class MyWebFilter implements WebFilter {
@Override
public Mono<Void> filter(ServerWebExchange exchange, WebFilterChain chain) {
ServerHttpRequest request = exchange.getRequest();
ServerHttpResponse response = exchange.getResponse();
System.out.println("请求处理放行目标之前");
Mono<Void> filter = chain
.filter(exchange) //放行
;
// 如果操作老流,那么就得返回一个新的变量,不能直接返回filter得返回newFiler。新的操作才会追加
Mono<Void> newFilter = filter
.doOnError(err->{
System.out.println("发生异常后处理数据");
})
.doFinally(signalType -> {
System.out.println("目标方法执行之后触发");
});
return newFilter;
}
}
4070

被折叠的 条评论
为什么被折叠?



