zoukankan      html  css  js  c++  java
  • springboot 全局异常处理器

    1、GlobalExceptionHandler  全局异常处理拦截器,捕获400,405和自定义等controller之后的异常

    import com.dm.exception.BSException;
    import com.dm.model.Result;
    import com.dm.model.StatusCode;
    import lombok.extern.slf4j.Slf4j;
    import org.springframework.http.HttpStatus;
    import org.springframework.http.converter.HttpMessageNotReadableException;
    import org.springframework.web.HttpRequestMethodNotSupportedException;
    import org.springframework.web.bind.MethodArgumentNotValidException;
    import org.springframework.web.bind.MissingServletRequestParameterException;
    import org.springframework.web.bind.ServletRequestBindingException;
    import org.springframework.web.bind.annotation.ExceptionHandler;
    import org.springframework.web.bind.annotation.ResponseStatus;
    import org.springframework.web.bind.annotation.RestControllerAdvice;
    
    import javax.validation.ConstraintViolationException;
    import java.net.BindException;
    
    /**
     * 解决Controller之后的异常
     */
    @Slf4j
    @RestControllerAdvice
    public class GlobalExceptionHandler {
        /**
         * 400 - Bad Request
         */
        @ResponseStatus(HttpStatus.BAD_REQUEST)
        @ExceptionHandler({HttpMessageNotReadableException.class, MissingServletRequestParameterException.class, BindException.class,
                ServletRequestBindingException.class, MethodArgumentNotValidException.class, ConstraintViolationException.class})
        public Result handleHttpMessageNotReadableException(Exception e) {
            log.error("------err------Bad Request: " + e.getMessage(), e);
            return new Result(StatusCode.BAD_REQUEST, "参数解析失败");
        }
    
        /**
         * 405 - Method Not Allowed
         */
        @ResponseStatus(HttpStatus.METHOD_NOT_ALLOWED)
        @ExceptionHandler(HttpRequestMethodNotSupportedException.class)
        public Result handleHttpRequestMethodNotSupportedException(HttpRequestMethodNotSupportedException e) {
            log.error("------err------Method Not Allowed: " + e.getMessage(), e);
            return new Result(StatusCode.METHOD_NOT_ALLOWED, "不支持当前请求方法");
        }
    
        /**
         * 自定义异常在此捕获
         */
        @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
        @ExceptionHandler(Throwable.class)
        public Result handleException(Throwable e) {
            log.error("------err------Service Run Exception: " + e.getMessage(), e);
            if (e instanceof BSException) {
                return new Result(((BSException) e).getCode(), ((BSException) e).getMsg());
            }
            return new Result(StatusCode.SYSTEM_ERR, "服务器运行异常");
        }
    } 

    注意:自定义异常在方法handleException中进行捕获

    2、FrontErrHandler,404异常是全局异常捕获不到的,所以放在FrontErrHandler进行处理

    import com.dm.model.Result;
    import com.dm.model.StatusCode;
    import io.swagger.annotations.Api;
    import lombok.extern.slf4j.Slf4j;
    import org.springframework.boot.web.servlet.error.ErrorController;
    import org.springframework.http.HttpStatus;
    import org.springframework.web.bind.annotation.GetMapping;
    import org.springframework.web.bind.annotation.ResponseStatus;
    import org.springframework.web.bind.annotation.RestController;
    
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    
    /**
     * 解决Controller之前的异常
     */
    @RestController
    @Slf4j
    @Api(tags = "FrontErrHandler", description = "FrontErrHandler相关接口")
    public class FrontErrHandler implements ErrorController {
        @Override
        public String getErrorPath() {
            return "/error";
        }
    
        @GetMapping(value = "/error")
        @ResponseStatus(HttpStatus.NOT_FOUND)
        public Object error(HttpServletRequest request, HttpServletResponse response) {
    
            log.error("------err------Response Error,HttpCode: " + response.getStatus());
    
            // 错误处理逻辑
            int status = response.getStatus();
            if (status == 404) {
                return new Result(StatusCode.REQUEST_NOT_FOUND, "访问地址不存在");
            } else if (status == 500) {
                return new Result(StatusCode.SYSTEM_ERR, "服务器运行异常");
            } else if (status >= 100 && status < 200) {
                return new Result(StatusCode.HTTP_ERROR_100, null);
            } else if (status >= 300 && status < 400) {
                return new Result(StatusCode.HTTP_ERROR_300, null);
            } else if (status >= 400 && status < 500) {
                return new Result(StatusCode.HTTP_ERROR_400, null);
            } else {
                return new Result(StatusCode.SYSTEM_ERR, "服务器运行异常");
            }
        }
    }
    

    3、捕获到异常以后将返回结果统一封装到Result中,封装Result时有两种方式,

    1)采用普通返回码,如返回正常,400,500等可以直接从普通返回码类中拿CODE进行返回的直接封装

    return new Result(StatusCode.OK, "添加成功")
    return new Result(StatusCode.SYSTEM_ERR, "服务器运行异常"); 

    2)从自定义异常中拿到code和msg封装最终返回,code和msg来自异常枚举

    return new Result(((BSException) e).getCode(), ((BSException) e).getMsg());

    3)Result定义

    import io.swagger.annotations.ApiModel;
    
    /**
     * 返回结果实体类
     */
    @ApiModel(description = "Result",value = "Result")
    public class Result<T> {
    
        private Integer code;//返回码
        private String message;//返回消息
    
        private T data;//返回数据
    
        public Result(Integer code, String message, Object data) {
            this.code = code;
            this.message = message;
            this.data = (T)data;
        }
    
        public Result(Integer code, String message) {
            this.code = code;
            this.message = message;
        }
    
        public Result() {
            this.code = StatusCode.OK;
            this.message = "执行成功";
        }
    
        public Integer getCode() {
            return code;
        }
    
        public void setCode(Integer code) {
            this.code = code;
        }
    
        public String getMessage() {
            return message;
        }
    
        public void setMessage(String message) {
            this.message = message;
        }
    
        public T getData() {
            return data;
        }
    
        public void setData(T data) {
            this.data = data;
        }
    }
    

    4)普通返回码定义

    /**
     * 普通返回码
     */
    public class StatusCode {
    
        public static final int OK = 200;//成功
        public static final int SYSTEM_ERR = 500;//服务器运行异常
        public static final int REQUEST_NOT_FOUND = 404;//访问地址不存在
        public static final int HTTP_ERROR_100 = 100;//1XX错误
        public static final int HTTP_ERROR_300 = 300;//3XX错误
        public static final int HTTP_ERROR_400 = 400;//4XX错误
        public static final int HTTP_ERROR_500 = 500;//5XX错误
    
        public static final int BAD_REQUEST = 407;//参数解析失败
        public static final int METHOD_NOT_ALLOWED = 405;//不支持当前请求方法
    }
    

    4、exception目录下定义异常类和异常枚举

    1)自定义异常类

    public class BSException extends RuntimeException {
    
        private int code;
        private String msg;
    
        public BSException(ErrorEnum errEnum, Exception e) {
            super(e);
            this.code = errEnum.getCode();
            this.msg = errEnum.getMsg();
        }
    
        public int getCode() {
            return code;
        }
    
        public void setCode(int code) {
            this.code = code;
        }
    
        public String getMsg() {
            return msg;
        }
    
        public void setMsg(String msg) {
            this.msg = msg;
        }
    }
    

    2)自定义异常枚举

    /**
     * 自定义异Enum
     */
    public enum ErrorEnum {
    
        //CUSTOM_EXCEPTION(6007, "自定义异常7"),
        CUSTOM_EXCEPTION(6008, "自定义异常8");
    
        private final Integer code;
        private final String msg;
    
        public Integer getCode() {
            return code;
        }
    
        public String getMsg() {
            return msg;
        }
    
        ErrorEnum(int code, String msg) {
            this.code = code;
            this.msg = msg;
        }
    }
    

    5、自定义异常的使用

        /**
         * 根据ID查询BsCategory
         */
        @Override
        public BsCategory findById(Integer id) {
            try {
                int i = 1 / 0;
            } catch (Exception e) {
                log.info("...err:::{}", e.getMessage());
                throw new BSException(ErrorEnum.CUSTOM_EXCEPTION,e);
            }
            return bsCategoryMapper.selectById(id);
    
        } 

    6、总结

    通过两个全局异常处理器将controller之前和之后的异常全部捕获到,然后通过Result通过封装结果进行返回,利用自定义异常和枚举来定义自己想要处理的异常。

  • 相关阅读:
    四则运算——结对编程
    《构建之法》第4章、第17章阅读与思考
    2016012063 小学四则运算练习软件项目报告
    基于《构建之法》的几个小见解
    结缘软件工程
    散列函数的应用及其安全性
    结对项目作业
    《构建之法》第四章第十七章阅读作业
    2016012048+小学四则运算练习软件项目报告
    读《构建之法》
  • 原文地址:https://www.cnblogs.com/songjn/p/13438514.html
Copyright © 2011-2022 走看看