Spring Web Flux函数式端点自定义异常抛出与全局处理问题求助
Spring Web Flux函数式端点自定义异常抛出与全局处理问题求助
兄弟,我看了你遇到的问题了,咱们一步步来拆解和解决:
为什么你的代码里USER NOT FOUND!!!永远打不出来?
核心原因是你对Reactor中**Flux的行为理解有点偏差:当repo.findByFirstName(req.pathVariable("name"))查询不到匹配的学生时,这个Flux是空的——它不会发射任何元素,直接进入onComplete状态。而handle操作符的回调函数只有在Flux发射元素的时候才会执行**,所以你写的stu==null的分支根本不会被触发,自然也就不会抛出自定义异常。
怎么修改才能正确抛出自定义异常?
根据你的业务场景(按名字查学生,可能是单个或多个结果),给你两种可行的方案:
方案1:适合「按名字查最多一个学生」的场景
如果你的业务逻辑里,学生名字是唯一的,那直接把Flux转成Mono,用switchIfEmpty来处理空结果的情况,代码更简洁:
public Mono<ServerResponse> getStudentByName(ServerRequest req) { String name = req.pathVariable("name"); return repo.findByFirstName(name) // 期望最多一个结果,找不到会触发switchIfEmpty .single() .switchIfEmpty(Mono.error(new UserNotFoundException("USER NOT FOUND"))) .flatMap(student -> ServerResponse.ok().bodyValue(student)); }
方案2:适合「允许多个学生重名,但要处理无匹配结果」的场景
如果确实需要保留Flux,那可以用defaultIfEmpty(null)让空Flux发射一个null元素,这样handle的回调就能捕获到并抛出异常:
public Mono<ServerResponse> getStudentByName(ServerRequest req) { String name = req.pathVariable("name"); Flux<Student> studentFlux = repo.findByFirstName(name) // 当Flux为空时,发射一个null元素 .defaultIfEmpty(null) .handle((stu, sink) -> { if (stu == null) { System.out.println("USER NOT FOUND!!!"); sink.error(new UserNotFoundException("USER NOT FOUND")); } else { System.out.println("OK OK OK OK"); sink.next(stu); } }); return ServerResponse.ok().body(studentFlux, Student.class); }
关于全局异常处理的注意点
你提到用@RestControllerAdvice做全局异常处理,但要注意:@RestControllerAdvice主要是处理注解式控制器(比如@RestController)的异常,对于函数式端点(你现在用的ServerRequest/ServerResponse这种),需要自定义ErrorWebExceptionHandler来实现全局异常处理,示例代码如下:
@Component public class GlobalErrorWebExceptionHandler extends AbstractErrorWebExceptionHandler { public GlobalErrorWebExceptionHandler(ErrorAttributes errorAttributes, WebProperties webProperties, ApplicationContext applicationContext) { super(errorAttributes, webProperties.getResources(), applicationContext); } @Override protected RouterFunction<ServerResponse> getRoutingFunction(ErrorAttributes errorAttributes) { // 匹配所有请求,统一处理异常 return RouterFunctions.route(RequestPredicates.all(), this::handleException); } private Mono<ServerResponse> handleException(ServerRequest request) { Throwable error = getError(request); // 处理自定义的UserNotFoundException if (error instanceof UserNotFoundException) { return ServerResponse.status(HttpStatus.NOT_FOUND) .bodyValue(Map.of( "status", HttpStatus.NOT_FOUND.value(), "message", error.getMessage() )); } // 处理其他通用异常 return ServerResponse.status(HttpStatus.INTERNAL_SERVER_ERROR) .bodyValue(Map.of( "status", HttpStatus.INTERNAL_SERVER_ERROR.value(), "message", "Internal Server Error" )); } }
这样当你的自定义异常抛出后,全局异常处理器就能捕获并返回你想要的自定义响应了。
内容来源于stack exchange
相关产品推荐
相关产品推荐

