当前位置: 代码网 > it编程>编程语言>Java > SpringBoot统一异常处理的实用方案

SpringBoot统一异常处理的实用方案

2026年03月25日 Java 我要评论
前言在日常开发中,你一定见过这样的代码:try { // 业务逻辑} catch (exception e) { e.printstacktrace();}或者接口返回五花八门:有的返回5

前言

在日常开发中,你一定见过这样的代码:

try {
    // 业务逻辑
} catch (exception e) {
    e.printstacktrace();
}

或者接口返回五花八门:

  • 有的返回 500 错误
  • 有的返回一段文字
  • 有的直接抛异常前端看不懂
  • 每个接口都写一遍 try-catch

代码冗余、维护困难、前端对接痛苦、日志混乱,线上出问题还难定位。

统一异常处理,就是用来解决这些问题的。

今天这篇文章,带你从零到一实现 spring boot 全局统一异常处理

包含:自定义异常、统一返回、全局捕获、异常分类、日志规范、实战案例。

看完直接落地到你的项目里。

一、为什么要做统一异常处理?

1. 现状痛点

  • 每个接口都写 try-catch,代码重复
  • 异常信息不规范,前端无法统一解析
  • 错误信息暴露给用户,不安全
  • 日志混乱,难以排查问题
  • 系统稳定性差,容易直接崩接口

2. 统一异常处理的好处

  • 代码更优雅,业务层不用处理异常
  • 所有异常统一格式返回
  • 异常可监控、可统计、可告警
  • 安全:不把系统异常暴露给前端
  • 提升开发效率与维护性

二、实现统一异常处理的核心组件

spring boot 提供两个最核心注解:

  • @restcontrolleradvice:全局捕获控制器异常
  • @exceptionhandler:捕获指定类型异常

配合:

  • 统一返回结果类
  • 自定义业务异常
  • 异常分类
  • 日志规范

就能完成一套企业级异常体系。

三、第一步:定义统一返回格式

前端最需要的是固定结构

创建 result.java

import lombok.data;
@data
public class result<t> {
    private int code;
    private string msg;
    private t data;
    // 成功
    public static <t> result<t> success(t data) {
        result<t> r = new result<>();
        r.setcode(200);
        r.setmsg("success");
        r.setdata(data);
        return r;
    }
    // 失败
    public static <t> result<t> fail(int code, string msg) {
        result<t> r = new result<>();
        r.setcode(code);
        r.setmsg(msg);
        r.setdata(null);
        return r;
    }
}

以后所有接口统一返回 result

四、第二步:自定义业务异常

系统异常和业务异常要分开。

创建 businessexception.java

public class businessexception extends runtimeexception {
    private int code;
    private string msg;
    public businessexception(string msg) {
        super(msg);
        this.code = 500;
        this.msg = msg;
    }
    public businessexception(int code, string msg) {
        super(msg);
        this.code = code;
        this.msg = msg;
    }
    // getter
}

使用示例:

if (user == null) {
    throw new businessexception(400, "用户不存在");
}

五、第三步:定义全局异常捕获类(核心)

创建 globalexceptionhandler.java

import lombok.extern.slf4j.slf4j;
import org.springframework.web.bind.annotation.exceptionhandler;
import org.springframework.web.bind.annotation.restcontrolleradvice;
@restcontrolleradvice
@slf4j
public class globalexceptionhandler {
    /**
     * 捕获业务异常
     */
    @exceptionhandler(businessexception.class)
    public result<?> handlebusinessexception(businessexception e) {
        log.warn("业务异常:{}", e.getmsg());
        return result.fail(e.getcode(), e.getmsg());
    }
    /**
     * 捕获参数校验异常
     */
    @exceptionhandler(illegalargumentexception.class)
    public result<?> handleillegalargument(illegalargumentexception e) {
        log.warn("参数异常:{}", e.getmessage());
        return result.fail(400, e.getmessage());
    }
    /**
     * 捕获空指针
     */
    @exceptionhandler(nullpointerexception.class)
    public result<?> handlenullpointer(nullpointerexception e) {
        log.error("空指针异常", e);
        return result.fail(500, "服务器内部错误");
    }
    /**
     * 兜底:所有其他异常
     */
    @exceptionhandler(exception.class)
    public result<?> handleexception(exception e) {
        log.error("系统异常", e);
        return result.fail(500, "服务器繁忙,请稍后再试");
    }
}

作用:

所有 controller 抛出的异常,都会进入这里统一处理。

六、第四步:整合 validation 参数校验(非常实用)

前端传参错误,统一返回。

1. 引入依赖

<dependency>
    <groupid>org.springframework.boot</groupid>
    <artifactid>spring-boot-starter-validation</artifactid>
</dependency>

2. dto 加校验

import jakarta.validation.constraints.notblank;
public class userlogindto {
    @notblank(message = "用户名不能为空")
    private string username;
    @notblank(message = "密码不能为空")
    private string password;
}

3. 接口加@valid

@postmapping("/login")
public result<?> login(@valid @requestbody userlogindto dto) {
    return result.success("login success");
}

4. 捕获校验异常

import org.springframework.validation.bindexception;
import org.springframework.validation.fielderror;
@exceptionhandler(bindexception.class)
public result<?> handlebindexception(bindexception e) {
    fielderror fielderror = e.getfielderror();
    string msg = fielderror.getdefaultmessage();
    log.warn("参数校验失败:{}", msg);
    return result.fail(400, msg);
}

效果:

前端收到干净的:

{
  "code": 400,
  "msg": "用户名不能为空",
  "data": null
}

七、第五步:规范日志级别(线上必备)

  • 业务异常:warn
  • 参数异常:warn
  • 系统异常:error

示例:

log.warn("业务异常:{}", e.getmsg());
log.error("空指针异常", e);

便于日志平台筛选、告警。

八、第六步:实际业务中怎么用?(最真实示例)

service 层:

@service
public class userservice {
    public user login(string username, string password) {
        user user = usermapper.selectbyusername(username);
        if (user == null) {
            throw new businessexception(400, "用户名或密码错误");
        }
        if (!user.getpassword().equals(password)) {
            throw new businessexception(400, "用户名或密码错误");
        }
        return user;
    }
}

controller 层:

@postmapping("/login")
public result<user> login(@valid @requestbody userlogindto dto) {
    user user = userservice.login(dto.getusername(), dto.getpassword());
    return result.success(user);
}

没有 try-catch!

代码极度清爽。

九、企业级异常分类规范

你可以直接在项目里使用这套异常码:

  • 200 成功
  • 400 参数错误
  • 401 未登录
  • 403 无权限
  • 404 不存在
  • 500 系统错误
  • 1001~1999 业务自定义

示例:

throw new businessexception(401, "请先登录");
throw new businessexception(403, "无此权限");
throw new businessexception(1001, "余额不足");

以上就是springboot统一异常处理的实用方案的详细内容,更多关于springboot统一异常处理的资料请关注代码网其它相关文章!

(0)

相关文章:

版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。

发表评论

验证码:
Copyright © 2017-2026  代码网 保留所有权利. 粤ICP备2024248653号
站长QQ:2386932994 | 联系邮箱:2386932994@qq.com