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

Spring Boot中不使用ControllerAdvice如何捕获并抛出精确异常?

Spring Boot REST接口异常处理(仅try-catch实现)

核心结论:优先捕获精确异常

直接捕获业务/系统中明确可能抛出的精确异常类型,比捕获通用Exception更严谨,能避免误抓无关异常、提升代码可读性,减少后续维护混乱。

具体实现步骤

1. 定义自定义业务异常(按需)

针对业务场景定义专属异常,继承RuntimeException(Spring会自动将未捕获的RuntimeException映射为对应HTTP状态码):

// 用户未找到异常(对应HTTP 404)
public class UserNotFoundException extends RuntimeException {
    public UserNotFoundException(String message) {
        super(message);
    }
}

// 数据库访问异常(对应HTTP 500)
public class DatabaseAccessException extends RuntimeException {
    public DatabaseAccessException(String message, Throwable cause) {
        super(message, cause);
    }
}

2. Controller中按精确异常分catch块处理

在try块执行业务逻辑,每个catch块对应一种异常类型,完成邮件通知后抛出异常给客户端:

@GetMapping(value = "/users")
public Users getUsers() { 
    try {
        return service.getUsers();
    } catch (UserNotFoundException ex) {
        // 发送管理员邮件:用户查询未找到
        sendAdminEmail("业务异常提醒", "请求/users时未找到匹配用户,异常信息:" + ex.getMessage());
        // 抛出异常,Spring自动返回404响应
        throw ex;
    } catch (DatabaseAccessException ex) {
        // 发送管理员邮件:数据库访问失败
        sendAdminEmail("系统异常警告", "请求/users数据库访问失败,异常栈:\n" + getStackTraceAsString(ex));
        // 抛出异常,Spring自动返回500响应
        throw ex;
    } catch (Exception ex) {
        // 兜底处理未知异常(谨慎使用)
        sendAdminEmail("未知异常告警", "请求/users发生未知异常,异常栈:\n" + getStackTraceAsString(ex));
        // 转为通用友好异常抛出,避免暴露敏感信息
        throw new RuntimeException("系统繁忙,请稍后再试", ex);
    }
}

// 邮件发送工具方法(示例,需结合实际邮件客户端实现)
private void sendAdminEmail(String subject, String content) {
    // 示例逻辑:使用Spring JavaMailSender
    // SimpleMailMessage message = new SimpleMailMessage();
    // message.setTo("admin@yourdomain.com");
    // message.setSubject(subject);
    // message.setText(content);
    // mailSender.send(message);
}

// 异常栈转为字符串工具方法
private String getStackTraceAsString(Throwable ex) {
    StringWriter sw = new StringWriter();
    PrintWriter pw = new PrintWriter(sw);
    ex.printStackTrace(pw);
    return sw.toString();
}

两种捕获方式对比

  • 直接捕获精确异常:推荐,逻辑清晰、针对性强,不会误处理空指针、参数错误这类代码bug级异常,维护成本低。
  • 捕获通用Exception再识别:不推荐,会捕获所有异常,容易掩盖潜在代码问题,且需用instanceof判断异常类型,代码可读性差,示例写法如下(仅作对比,不建议使用):
// 不推荐的写法
try {
    return service.getUsers();
} catch (Exception ex) {
    if (ex instanceof UserNotFoundException) {
        sendAdminEmail("业务异常", ex.getMessage());
        throw (UserNotFoundException) ex;
    } else if (ex instanceof DatabaseAccessException) {
        sendAdminEmail("系统异常", getStackTraceAsString(ex));
        throw (DatabaseAccessException) ex;
    } else {
        sendAdminEmail("未知异常", getStackTraceAsString(ex));
        throw new RuntimeException("系统繁忙", ex);
    }
}

内容的提问来源于stack exchange,提问作者elvis

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.18 19:22:57