
文章目录webfluxwebflux中的坑MonoFluxRouterFunctionRouterFunction示例MonoMono示例其他WebFlux和web可以同时引入吗?routerFunction和controller可以同时存在吗?webfluxwebflux中的坑坑点表现解法阻塞调用接口变慢、超时用 R2DBC / WebClient / Lettuce阻塞逻辑走subscribeOn(Schedulers.boundedElastic())链未订阅代码没执行直接返回Mono/Flux别手动subscribe()map/flatMap 混用MonoMonoT返回异步对象用flatMap普通值用map异常难捕获try-catch无效用onErrorReturn/onErrorResume/onErrorMapThreadLocal 失效上下文丢失改用 ReactorContext背压失控OOM / 数据丢失配onBackpressureBuffer/Drop/Latest生态不响应式阻塞组件拖垮线程优先响应式客户端调试困难堆栈不直观用.log()、Hooks.onOperatorDebug()、BlockHoundMVC 混用冲突启动混乱网关/路由单独 WebFlux业务用 MVC路由残留旧路由仍生效只保留一个RouterFunctionMapping刷新时替换内部路由MonoMono(monologue)(独白)表示0或1个。Flux表示多个。RouterFunctionrouterFunction就是webflux函数式编程的典型实现。大概需要如下几个条件。1、引入maven依赖2、搭建并配置nacos(测试动态路由)3、核心类4、验证功能RouterFunction示例1、创建FunctionRouterConfig配置类。Slf4jConfigurationpublicclassFunctionRouterConfig{BeanpublicRouterFunctionServerResponseroute(){returnRouterFunctions.route().POST(/testLog,this::handleLog).build();}privateServerResponsehandleLog(ServerRequestrequest)throwsException{// 读取原始请求体Stringbodyrequest.body(String.class);log.info(POST /testLog 收到报文: {},body);Stringresp{\success\:true,\message\:\已收到报文\};returnServerResponse.ok().contentType(MediaType.APPLICATION_JSON).body(resp);}}2、启动项目postman调用请求即可请求地址{{url}}/api/testLog请求报文{name:张三,age:18}响应报文{success:true,message:已收到报文}MonoMono(单细胞单核)这里把它理解为单体即可类似一张快递单只定义并不运行运行交由管理器。Mono示例依赖dependencygroupIdio.projectreactor/groupIdartifactIdreactor-core/artifactIdversion3.6.11/version/dependency代码importreactor.core.publisher.Mono;importjava.time.Duration;publicclassMonoConcurrentDemo{publicstaticvoidmain(String[]args){// 定义3个模拟耗时任务模拟调用LLM/工具/数据库MonoStringtask1runTask(任务1-调用大模型,2);MonoStringtask2runTask(任务2-向量检索,1);MonoStringtask3runTask(任务3-联网工具查询,3);// 并发执行三个Mono全部完成后统一收集结果MonoString[]allTasksMono.zip(task1,task2,task3).map(tuple-newString[]{tuple.getT1(),tuple.getT2(),tuple.getT3()});System.out.println( 开始并发执行3个任务 );// block() 主线程阻塞等待全部完成main方法专用String[]resultsallTasks.block();System.out.println( 所有任务执行完毕汇总结果 );for(Stringres:results){System.out.println(res);}}/** * 封装一个耗时Mono任务 * param name 任务名称 * param delay 模拟耗时秒数 * return Mono单结果 */privatestaticMonoStringrunTask(Stringname,longdelay){returnMono.fromCallable(()-{System.out.printf([%s] 开始执行线程%s%n,name,Thread.currentThread().getName());// 模拟IO阻塞模型调用、网络请求Thread.sleep(Duration.ofSeconds(delay).toMillis());StringresultString.format([%s] 执行完成耗时%d秒,name,delay);System.out.printf([%s] 结束线程%s%n,name,Thread.currentThread().getName());returnresult;})// 设置超时防止卡死.timeout(Duration.ofSeconds(10))// 异常兜底.onErrorReturn(name 执行失败);}}其他WebFlux和web可以同时引入吗?可以同时引入。1、同时引入 spring-boot-starter-web 和 spring-boot-starter-webflux 时Spring Boot 默认会按 Spring MVC 启动。如果想用 WebFlux需要设置spring.main.web-application-typereactive2、如果用了 Spring Cloud Gateway就不能同时保留 spring-boot-starter-web否则启动会报Spring MVC found on classpath,whichis incompatible with Spring Cloud Gateway这时要排除 spring-boot-starter-web。routerFunction和controller可以同时存在吗?设置了spring.main.web-application-typereactive之后注解式Controller/RestController仍然有效但必须按WebFlux的规则写。所以推荐只用一种。