SpringBoot如何进行全局异常处理?

1.为什么需要全局异常处理?

在日常开发中,为了不抛出异常堆栈信息给前端页面,每次编写Controller层代码都要尽可能的catch住所有service层、dao层等异常,代码耦合性较高,且不美观,不利于后期维护。

应用场景是什么?

  • 非常方便的去掉了try...catch这类冗杂难看的代码,有利于代码的整洁和优雅
  • 自定义参数校验时候全局异常处理会捕获异常,将该异常统一返回给前端,省略很多if...else代码
  • 当后端出现异常时,需要返回给前端一个友好的界面的时候就需要全局异常处理
  • 因为异常时层层向上抛出的,为了避免控制台打印一长串异常信息

2.代码工程

实验目的

实现全局异常拦截

controller

package com.et.exception.controller;

import com.et.exception.config.BizException;
import com.et.exception.model.User;
import org.springframework.web.bind.annotation.*;

import java.util.HashMap;
import java.util.Map;

@RestController
public class HelloWorldController {
    @RequestMapping("/hello")
    public Map showHelloWorld(){
        Map map = new HashMap<>();
        map.put("msg", "HelloWorld");
        return map;
    }
   @PostMapping("/user")
   public boolean insert(@RequestBody User user) {
      System.out.println("add...");
      if(user.getName()==null){
         throw  new BizException("-1","username is empty!");
      }
      return true;
   }

   @PutMapping("/user")
   public boolean update(@RequestBody User user) {
      System.out.println("update...");
      //mock NullException
      String str=null;
      str.equals("111");
      return true;
   }

   @DeleteMapping("/user")
   public boolean delete(@RequestBody User user)  {
      System.out.println("delete...");
      //mock Exception
      Integer.parseInt("abc123");
      return true;
   }


}

globe exception config

定义全局异常拦截类

package com.et.exception.config;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.servlet.http.HttpServletRequest;

@ControllerAdvice
public class GlobalExceptionHandler {
   private static final Logger logger = LoggerFactory.getLogger(GlobalExceptionHandler.class);
   
   /**
    *process BizException
    * @param req
    * @param e
    * @return
    */
    @ExceptionHandler(value = BizException.class)
    @ResponseBody
   public  ResultBody bizExceptionHandler(HttpServletRequest req, BizException e){
       logger.error("biz exception!the reason is:{}",e.getErrorMsg());
       return ResultBody.error(e.getErrorCode(),e.getErrorMsg());
    }

   /**
    * process NUllException
    * @param req
    * @param e
    * @return
    */
   @ExceptionHandler(value =NullPointerException.class)
   @ResponseBody
   public ResultBody exceptionHandler(HttpServletRequest req, NullPointerException e){
      logger.error("null exception!the reason is:",e);
      return ResultBody.error(CommonEnum.BODY_NOT_MATCH);
   }


    /**
    * unkown Exception
     * @param req
     * @param e
     * @return
     */
    @ExceptionHandler(value =Exception.class)
   @ResponseBody
   public ResultBody exceptionHandler(HttpServletRequest req, Exception e){
       logger.error("unkown Exception!the reason is:",e);
           return ResultBody.error(CommonEnum.INTERNAL_SERVER_ERROR);
    }
}

自定义业务异常

package com.et.exception.config;

public class BizException extends RuntimeException {

   private static final long serialVersionUID = 1L;


   protected String errorCode;

   protected String errorMsg;

   public BizException() {
      super();
   }

   public BizException(BaseErrorInfoInterface errorInfoInterface) {
      super(errorInfoInterface.getResultCode());
      this.errorCode = errorInfoInterface.getResultCode();
      this.errorMsg = errorInfoInterface.getResultMsg();
   }
   
   public BizException(BaseErrorInfoInterface errorInfoInterface, Throwable cause) {
      super(errorInfoInterface.getResultCode(), cause);
      this.errorCode = errorInfoInterface.getResultCode();
      this.errorMsg = errorInfoInterface.getResultMsg();
   }
   
   public BizException(String errorMsg) {
      super(errorMsg);
      this.errorMsg = errorMsg;
   }
   
   public BizException(String errorCode, String errorMsg) {
      super(errorCode);
      this.errorCode = errorCode;
      this.errorMsg = errorMsg;
   }

   public BizException(String errorCode, String errorMsg, Throwable cause) {
      super(errorCode, cause);
      this.errorCode = errorCode;
      this.errorMsg = errorMsg;
   }
   

   public String getErrorCode() {
      return errorCode;
   }

   public void setErrorCode(String errorCode) {
      this.errorCode = errorCode;
   }

   public String getErrorMsg() {
      return errorMsg;
   }

   public void setErrorMsg(String errorMsg) {
      this.errorMsg = errorMsg;
   }

   public String getMessage() {
      return errorMsg;
   }

   @Override
   public Throwable fillInStackTrace() {
      return this;
   }

}

自定义返回结果

package com.et.exception.config;

import com.alibaba.fastjson.JSONObject;

public class ResultBody {

   private String code;

   private String message;


   private Object result;

   public ResultBody() {
   }

   public ResultBody(BaseErrorInfoInterface errorInfo) {
      this.code = errorInfo.getResultCode();
      this.message = errorInfo.getResultMsg();
   }

   public String getCode() {
      return code;
   }

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

   public String getMessage() {
      return message;
   }

   public void setMessage(String message) {
      this.message = message;
   }

   public Object getResult() {
      return result;
   }

   public void setResult(Object result) {
      this.result = result;
   }


   public static ResultBody success() {
      return success(null);
   }

   public static ResultBody success(Object data) {
      ResultBody rb = new ResultBody();
      rb.setCode(CommonEnum.SUCCESS.getResultCode());
      rb.setMessage(CommonEnum.SUCCESS.getResultMsg());
      rb.setResult(data);
      return rb;
   }


   public static ResultBody error(BaseErrorInfoInterface errorInfo) {
      ResultBody rb = new ResultBody();
      rb.setCode(errorInfo.getResultCode());
      rb.setMessage(errorInfo.getResultMsg());
      rb.setResult(null);
      return rb;
   }


   public static ResultBody error(String code, String message) {
      ResultBody rb = new ResultBody();
      rb.setCode(code);
      rb.setMessage(message);
      rb.setResult(null);
      return rb;
   }


   public static ResultBody error( String message) {
      ResultBody rb = new ResultBody();
      rb.setCode("-1");
      rb.setMessage(message);
      rb.setResult(null);
      return rb;
   }

   @Override
   public String toString() {
      return JSONObject.toJSONString(this);
   }

}

实体类

package com.et.exception.model;

import com.alibaba.fastjson.JSONObject;

import java.io.Serializable;

public class User implements Serializable {
   private static final long serialVersionUID = 1L;
    private int id;
    private String name;
    private int age;
    
    public User(){
    }

   public int getId() {
      return id;
   }
   
   public void setId(int id) {
      this.id = id;
   }

   public String getName() {
      return name;
   }

   public void setName(String name) {
      this.name = name;
   }

   public int getAge() {
      return age;
   }

   public void setAge(int age) {
      this.age = age;
   }

   public String toString() {
      return JSONObject.toJSONString(this);
   }
}

以上只是一些关键代码,所有代码请参见下面代码仓库

代码仓库

  • GitHub - Harries/springboot-demo: a simple springboot demo with some components for example: redis,solr,rockmq and so on.(exception)

3.测试

启动Spring Boot项目

模拟业务异常

SpringBoot如何进行全局异常处理?_第1张图片

模拟null异常

​编辑0%模拟其他异常

SpringBoot如何进行全局异常处理?_第2张图片

4.引用

  • SpringBoot如何进行全局异常处理? | Harries Blog™

你可能感兴趣的:(Spring,Boot,Demo,spring,boot,后端,java,exception)