Reactor中switchIfEmpty能否处理多异常?Mono异常处理问询
问题分析与解决方案
一、测试报错的核心原因
你当前代码存在两个关键问题:
- 异常类型与HTTP状态码不匹配:用户未找到时你抛出的是
UserBadRequestExeception(注意拼写应为UserBadRequestException),但测试期望的是404 NOT_FOUND状态。BadRequest对应400状态,这会导致Spring WebFlux默认的异常处理无法返回你期望的404响应结构。 - 未配置自定义异常响应体:默认情况下,Spring WebFlux不会自动将异常转换成包含
code、message等字段的JSON结构,所以测试时JSON路径code找不到对应值。
二、修复测试报错的步骤
1. 修正异常类型
先把用户未找到时的异常改为对应404的自定义异常,比如UserNotFoundException:
Mono.just(userId) .flatMap(repo::findById) .switchIfEmpty(Mono.error(new UserNotFoundException("用户不存在")))
2. 配置全局异常处理器
创建@ControllerAdvice类,统一处理异常并返回标准错误响应体:
@ControllerAdvice public class GlobalExceptionHandler { @ExceptionHandler(UserNotFoundException.class) public ResponseEntity<ErrorResponse> handleUserNotFound(UserNotFoundException e) { ErrorResponse error = new ErrorResponse( "404", "Not Found", "404 NOT_FOUND", RequestContextHolder.getRequestAttributes().getRequestURI() ); return new ResponseEntity<>(error, HttpStatus.NOT_FOUND); } @ExceptionHandler(UserBadRequestException.class) public ResponseEntity<ErrorResponse> handleBadRequest(UserBadRequestException e) { ErrorResponse error = new ErrorResponse( "400", "Bad Request", "400 BAD_REQUEST", RequestContextHolder.getRequestAttributes().getRequestURI() ); return new ResponseEntity<>(error, HttpStatus.BAD_REQUEST); } // 定义错误响应体结构 public static class ErrorResponse { private String code; private String message; private String description; private String instance; // 构造函数、getter/setter public ErrorResponse(String code, String message, String description, String instance) { this.code = code; this.message = message; this.description = description; this.instance = instance; } public String getCode() { return code; } public String getMessage() { return message; } public String getDescription() { return description; } public String getInstance() { return instance; } } }
三、Mono/Flux中处理多种异常的方法
完全可以在Mono/Flux中处理多种异常,常用的操作符有以下几种:
1. onErrorResume:按异常类型分支处理
针对不同异常类型返回不同的Mono,实现分支逻辑:
Mono.just(userId) .flatMap(repo::findById) .switchIfEmpty(Mono.error(new UserNotFoundException())) // 处理用户未找到异常 .onErrorResume(UserNotFoundException.class, e -> Mono.error(new ResponseStatusException(HttpStatus.NOT_FOUND, e.getMessage())) ) // 处理请求参数错误异常 .onErrorResume(UserBadRequestException.class, e -> Mono.error(new ResponseStatusException(HttpStatus.BAD_REQUEST, e.getMessage())) ) // 兜底处理其他所有异常 .onErrorResume(Exception.class, e -> Mono.error(new ResponseStatusException(HttpStatus.INTERNAL_SERVER_ERROR, "服务器内部错误")) );
2. onErrorMap:转换异常类型
把自定义异常转换成Spring的ResponseStatusException,让框架自动处理状态码:
Mono.just(userId) .flatMap(repo::findById) .switchIfEmpty(Mono.error(new UserNotFoundException())) .onErrorMap(UserNotFoundException.class, e -> new ResponseStatusException(HttpStatus.NOT_FOUND, e.getMessage()) ) .onErrorMap(UserBadRequestException.class, e -> new ResponseStatusException(HttpStatus.BAD_REQUEST, e.getMessage()) );
3. 全局异常处理器(推荐)
相比在每个Mono链中单独处理异常,全局异常处理器更简洁易维护,只需定义一次就能统一处理所有控制器的异常,避免重复代码。
四、验证测试
完成上述配置后重新运行测试,Spring会将UserNotFoundException转换成包含code、message等字段的404响应,测试中的JSON路径断言就能正常通过。
内容的提问来源于stack exchange,提问作者user22504890
相关产品推荐
相关产品推荐

