You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Reactor中switchIfEmpty能否处理多异常?Mono异常处理问询

问题分析与解决方案

一、测试报错的核心原因

你当前代码存在两个关键问题:

  1. 异常类型与HTTP状态码不匹配:用户未找到时你抛出的是UserBadRequestExeception(注意拼写应为UserBadRequestException),但测试期望的是404 NOT_FOUND状态。BadRequest对应400状态,这会导致Spring WebFlux默认的异常处理无法返回你期望的404响应结构。
  2. 未配置自定义异常响应体:默认情况下,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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.11 11:48:27