springboot 统一异常处理

该博客介绍了如何在Java Spring Boot应用中实现统一异常处理,以避免在每个控制器方法中都使用try...catch语句。首先,自定义了一个全局异常类`HaoqianException`,继承自`RuntimeException`,并包含了错误代码和消息。接着,创建了`GlobalExceptionHandler`作为全局异常处理器,使用`@ControllerAdvice`注解使其生效。处理器中定义了两个`@ExceptionHandler`方法,分别处理自定义异常和所有未捕获的异常,返回统一格式的响应结果。通过这种方式,即使代码中不显式捕获异常,也能保证返回给前端的响应格式一致。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

0 问题

在日常开发中你是否遇到过这样的问题:

当程序出现异常响应给前端的数据格式不是你预期想要的如图所示:
在这里插入图片描述
为了返回统一的响应格式,每次代码中都需要手动捕获异常,然后返回统一格式,写法可能会是这样:

import lombok.extern.slf4j.Slf4j;

@Slf4j
@RestController
public class EmployeeController {

    @GetMapping("testCustomException/{num}")
    @TraceLog
    public Result testCustomException(@PathVariable("num") int num) {
        try {
            int a = 10 / num;
            return Result.success().data(a);
        } catch (Exception e) {
            log.error("error:", e);
            return Result.failure(ResultCodeEnum.PARAM_IS_INVALID);
        }
    }
}

注意:其中的 Result、ResultCodeEnum 类来源于另一片文章介绍的 “Java 统一封装响应结果”
https://blog.youkuaiyun.com/QiuHaoqian/article/details/113493682

但是,你有没有想过,如果每个请求的方法都需要使用 try…catch来包装代码是不是会很臃肿呢?
所以接下来看一下如何实现统一异常处理。

1 实现

第一步:自定义异常类(可选)

package com.haoqian.log_demo.utils.exception;

import com.haoqian.log_demo.utils.result.ResultCodeEnum;
import lombok.Data;

/**
 * 自定义全局异常类
 *
 * @author qy
 */
@Data
public class HaoqianException extends RuntimeException {

    private Integer code;

    /**
     * 通过状态码和错误消息创建异常对象
     *
     * @param code
     * @param message
     */
    public HaoqianException(Integer code, String message) {
        super(message);
        this.code = code;
    }

    /**
     * 接收枚举类型对象
     *
     * @param resultCodeEnum
     */
    public HaoqianException(ResultCodeEnum resultCodeEnum) {
        super(resultCodeEnum.getMessage());
        this.code = resultCodeEnum.getCode();
    }

    @Override
    public String toString() {
        return "HaoqianException{" +
                "code=" + code +
                ", message=" + this.getMessage() +
                '}';
    }
}

第二步:自定义全局异常处理器

package com.haoqian.log_demo.utils.exception;

import com.haoqian.log_demo.utils.result.Result;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;

@Slf4j
@ControllerAdvice
public class GlobalExceptionHandler {

    /**
     * 自定义异常处理
     *
     * @param e 异常
     * @return 统一封装的响应结果
     */
    @ExceptionHandler(HaoqianException.class)
    @ResponseBody
    public Result error(HaoqianException e) {
        log.error("info:", e);
        return Result.code(500).message(e.getMessage());
    }

    /**
     * 统一异常处理
     *
     * @param e 异常
     * @return 统一封装的响应结果
     */
    @ExceptionHandler(Exception.class)
    @ResponseBody
    public Result error(Exception e) {
        log.error("info:", e);
        return Result.code(500).message(e.getMessage());
    }

}





2 测试

package com.haoqian.log_demo.controller;

import com.haoqian.log_demo.service.EmployeeService;
import com.haoqian.log_demo.utils.interceptor.TraceLog;
import com.haoqian.log_demo.utils.result.Result;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class EmployeeController {
    private final Logger log = LoggerFactory.getLogger(this.getClass());

    @GetMapping("testCustomException/{num}")
    @TraceLog
    public Result testCustomException(@PathVariable("num") int num) {
        int a = 10 / num;
        return Result.success().data(a);
    }
}

可以看到上述代码并没有使用 try…catch 捕获并处理异常,但却实现了 统一的异常捕获处理,并可以 返回自定义响应结果
在这里插入图片描述

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值