spring框架做全局异常捕获_Springboot 2.x 实现异常全局捕获

本文介绍了一种在SpringBoot项目中进行全局异常处理的方法,包括自定义异常类、控制器异常抛出及统一异常处理机制。通过这些技术手段,能够有效简化代码并提高系统的健壮性和用户体验。

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

cb1150e7e487e7159354cc06d7bf8009.png

初始化异常

@GetMapping("/test1")
public String test1() {
    // TODO 这里只是模拟异常,假设业务处理的时候出现错误了,或者空指针了等等...
    int i = 10 / 0;
    return "test1";
}

打开浏览器访问时

35e909cda3797349ec69f279fe73cbbf.png

采用try catch 方法 手动抓取异常;这是很多人想到得,但是明显得弊端时;出现大量的重复的try catch;代码量上去了;

@GetMapping("/test2")
public Map<String, String> test2() {
    Map<String, String> result = new HashMap<>(16);
    // TODO 直接捕获所有代码块,然后在 cache
    try {
        int i = 10 / 0;
        result.put("code", "200");
        result.put("data", "具体返回的结果集");
    } catch (Exception e) {
        result.put("code", "500");
        result.put("message", "请求错误");
    }
    return result;
}

解决方案使用全局异常捕获

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-test</artifactId>
    <scope>test</scope>
</dependency>

自定义异常

package com.meyue.xiwen.exception;


/**
 * 类: BaseException <br>
 * 描述: 运行时异常基类<br>
 */
public class BaseException extends RuntimeException implements BaseMsgDes{
    
    /**  */
   private static final long serialVersionUID = -5335258347966254381L;
   
   private final ExceptionLevel level;
   
   private final ExceptionCode code;
   
   private String remark;

   protected String outPusMsg;

   public String getOutPusMsg() {
      return outPusMsg;
   }

   public void setOutPusMsg(String outPusMsg) {
      this.outPusMsg = outPusMsg;
   }

   /**
    * 标题: 构造器 <br>
    * 描述: TODO <br>
    * @param level
    * @param code 
    */
   public BaseException(ExceptionLevel level, ExceptionCode code) {
      super();
      this.level = level;
      this.code = code;
   }

   public BaseException(String remark,String message,ExceptionLevel level, ExceptionCode code) {
        super(message);
       this.level = level;
      this.code = code;
      this.remark=remark;
    }

    public BaseException(Throwable cause,ExceptionLevel level, ExceptionCode code) {
        super(cause);
       this.level = level;
      this.code = code;
    }

    public BaseException(String remark,String message, Throwable cause,ExceptionLevel level, ExceptionCode code) {
        super(message, cause);
       this.level = level;
      this.code = code;
      this.remark=remark;
    }

   public ExceptionLevel getLevel() {
      return level;
   }

   public ExceptionCode getCode() {
      return code;
   }

    public String getRemark() {
        return remark;
    }

    public void setRemark(String remark) {
        this.remark = remark;
    }

     
    
}

控制层输出

@RestController
public class ExceptionController {

    @GetMapping("/ex")
    public String ex(Integer num) {
        // TODO 演示需要,实际上参数是否为空通过 @RequestParam(required = true)  就可以控制
        if (num == null) {
            throw new BaseException (400, "num不能为空");
        }
        int i = 10 / num;
        return "result:" + i;
    }
}

异常处理

注解概述@ControllerAdvice 捕获 Controller 层抛出的异常,如果添加 @ResponseBody 返回信息则为JSON 格式。@RestControllerAdvice 相当于 @ControllerAdvice@ResponseBody 的结合体。@ExceptionHandler 统一处理一种类的异常,减少代码重复率,降低复杂度。创建一个 GlobalExceptionHandler 类,并添加上 @RestControllerAdvice 注解就可以定义出异常通知类了,然后在定义的方法中添加上 @ExceptionHandler 即可实现异常的捕捉…
package com.meyue.xiwen.config;

import com.meyue.xiwen.bo.ErrorResponseEntity;
import com.meyue.xiwen.exception.CustomerException;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.context.request.WebRequest;
import org.springframework.web.method.annotation.MethodArgumentTypeMismatchException;
import org.springframework.web.servlet.mvc.method.annotation.ResponseEntityExceptionHandler;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * @ClassName:GlobalExceptionHandler </br>
 * @Description: TODO  </br>
 * @Author:童晶继 tongjingji01@gmail.com </br>
 * @Date:
 * @version:1.0
 */
@RestControllerAdvice
public class GlobalExceptionHandler extends ResponseEntityExceptionHandler {


    /**
     * 定义要捕获的异常 可以多个 @ExceptionHandler({})
     *
     * @param request  request
     * @param e        exception
     * @param response response
     * @return 响应结果
     */
    @ExceptionHandler(CustomerException.class)
    public ErrorResponseEntity customExceptionHandler(HttpServletRequest request, final Exception e, HttpServletResponse response) {
        response.setStatus(HttpStatus.BAD_REQUEST.value());
        CustomerException exception = (CustomerException) e;
        return new ErrorResponseEntity(exception.getCode(), exception.getMessage());
    }

    /**
     * 捕获  RuntimeException 异常
     * TODO  如果你觉得在一个 exceptionHandler 通过  if (e instanceof xxxException) 太麻烦
     * TODO  那么你还可以自己写多个不同的 exceptionHandler 处理不同异常
     *
     * @param request  request
     * @param e        exception
     * @param response response
     * @return 响应结果
     */
    @ExceptionHandler(RuntimeException.class)
    public ErrorResponseEntity runtimeExceptionHandler(HttpServletRequest request, final Exception e, HttpServletResponse response) {
        response.setStatus(HttpStatus.BAD_REQUEST.value());
        RuntimeException exception = (RuntimeException) e;
        return new ErrorResponseEntity(400, exception.getMessage());
    }

    /**
     * 通用的接口映射异常处理方
     */
    @Override
    protected ResponseEntity<Object> handleExceptionInternal(Exception ex, Object body, HttpHeaders headers,
                                                             HttpStatus status, WebRequest request) {
        if (ex instanceof MethodArgumentNotValidException) {
            MethodArgumentNotValidException exception = (MethodArgumentNotValidException) ex;
            return new ResponseEntity<>(new ErrorResponseEntity(status.value(), exception.getBindingResult().getAllErrors().get(0).getDefaultMessage()), status);
        }
        if (ex instanceof MethodArgumentTypeMismatchException) {
            MethodArgumentTypeMismatchException exception = (MethodArgumentTypeMismatchException) ex;
            logger.error("参数转换失败,方法:" + exception.getParameter().getMethod().getName() + ",参数:" + exception.getName()
                    + ",信息:" + exception.getLocalizedMessage());
            return new ResponseEntity<>(new ErrorResponseEntity(status.value(), "参数转换失败"), status);
        }
        return new ResponseEntity<>(new ErrorResponseEntity(status.value(), "参数转换失败"), status);
    }
}

package com.meyue.xiwen.bo;

/**
 * @ClassName:ErrorResponseEntity </br>
 * @Description: TODO  </br>
 * @Author:童晶继 tongjingji01@gmail.com </br>
 * @Date:
 * @version:1.0
 */
public class ErrorResponseEntity {
    private int code;
    private String message;

    public ErrorResponseEntity(int code, String message) {
        this.code=code;
        this.message=message;
    }

    public int getCode() {
        return code;
    }

    public void setCode(int code) {
        this.code = code;
    }

    public String getMessage() {
        return message;
    }

    public void setMessage(String message) {
        this.message = message;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值