SpringBoot企业级全局异常处理方案

https://www.cnblogs.com/xuwujing/p/10933082.html
这个是网上找的异常处理方案,有几个问题:

  • http状态码是三位数的,自定义状态码应该跟他们分开,应该类似于10001这样

  •    /**
            * 处理其他异常
         * @param req
         * @param e
         * @return
         */
        @ExceptionHandler(value =Exception.class)
        @ResponseBody
        public ResultBody exceptionHandler(HttpServletRequest req, Exception e){
            logger.error("未知异常!原因是:",e);
            return ResultBody.error(CommonEnum.INTERNAL_SERVER_ERROR);
        }
    

    这个地方的http状态码不应该是200 了,需要去改变http的状态码

  • 返回信息中应该包含请求的方式和请求的对应请求路径

  • 缺少自定义异常的http状态码的动态处理

借鉴了一下它的方案,总结了以下几步,测试代码就不贴出来了。

Step1、自定义错误码配置文件

exception-codes-demo.properties

sell.codes[1]=SUCCESS
#参数错误
sell.codes[10001]=参数为空
sell.codes[10002]=参数不全
sell.codes[10003]=参数类型错误
sell.codes[10004]=参数无效
#用户错误
sell.codes[20001]=永久不存在
sell.codes[20002]=用户未登录
sell.codes[20003]=用户名或者密码错误
sell.codes[20004]=用户账户已被禁用
sell.codes[20005]=用户已经存在
#业务错误
sell.codes[30001]=系统业务出现问题
#系统错误
sell.codes[40001]=系统内部错误
#数据错误
sell.codes[50001]=数据未找到
sell.codes[50002]=数据有误
sell.codes[50003]=数据已存在
#接口错误
sell.codes[60001]=系统业务出现问题
sell.codes[60002]=系统外部接口调用异常
sell.codes[60003]=接口禁止访问
sell.codes[60004]=接口地址无效
sell.codes[60005]=接口请求超时
sell.codes[60006]=接口负载过高

#权限错误
sell.codes[70001]=没有访问权限

Step2、编写自定义错误码的处理类,与配置文件绑定

package com.immoc.sell.core.configuration;


import lombok.Getter;
import lombok.Setter;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.PropertySource;
import org.springframework.stereotype.Component;

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


/**
 * @author allen
 */
@Component
@PropertySource(value = "classpath:config/exception-codes-demo.properties",encoding = "utf-8")
@ConfigurationProperties(prefix = "sell")
@Getter
@Setter
public class ExceptionCodeConfiguration {
    private Map<Integer, String> codes = new HashMap<>();


    public String getMessage(int code){
        return codes.get(code);

    }
}

Step3、编写通用返回消息类 也就是ResultBody

package com.immoc.sell.core;

import lombok.AllArgsConstructor;
import lombok.Data;

import java.util.StringTokenizer;

/**
 * @author allen
 */
@Data
@AllArgsConstructor
public class UnifyResponse {
    private int code;
    private String message;
    private String request;
}

Step4、自定义异常父类和它的子类

package com.immoc.sell.exception.http;


import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.Setter;

/**
 * @author allen
 */
@Data
public class HttpException extends RuntimeException {

    protected Integer code;
    protected Integer httpStatusCode = 500;
}

package com.immoc.sell.exception.http;

/**
 * @author allen
 */
public class ForbiddenException extends HttpException {
    public ForbiddenException(int code) {
        this.code = code;
        this.httpStatusCode = 403;
    }
}
package com.immoc.sell.exception.http;

/**
 * @author allen
 */
public class NotFoundException  extends HttpException{
    public NotFoundException(int code) {
        this.httpStatusCode = 404;
        this.code = code;
    }
}

Step5、编写全局异常处理通知类

package com.immoc.sell.core;


import com.immoc.sell.core.configuration.ExceptionCodeConfiguration;
import com.immoc.sell.exception.http.HttpException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.ResponseStatus;

import javax.servlet.http.HttpServletRequest;

/**
 * @author allen
 */
@ControllerAdvice
public class GlobalExceptionAdvice {
    private static final Logger logger = LoggerFactory.getLogger(GlobalExceptionAdvice.class);

    @Autowired
    private ExceptionCodeConfiguration exceptionCodeConfiguration;

    /**
     * 处理自定义的业务异常
     * http类型的
     *
     * @param req
     * @param e
     * @return
     */
    @ExceptionHandler(value = HttpException.class)
    @ResponseBody
    public ResponseEntity<UnifyResponse> httpExceptionHandler(HttpServletRequest req, HttpException e) {
        logger.error("发生http类型的异常!原因是:{}", e.getMessage());

        UnifyResponse response = new UnifyResponse(e.getCode(), exceptionCodeConfiguration.getMessage(e.getCode()), req.getMethod() + " " + req.getRequestURI());

        return ResponseEntity.status(e.getHttpStatusCode()).body(response);
    }


    /**
     * 处理其他异常
     *
     * @param req
     * @param e
     * @return
     */
    @ExceptionHandler(value = Exception.class)
    @ResponseBody
    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
    public UnifyResponse exceptionHandler(HttpServletRequest req, Exception e) {
        logger.error("未知异常!原因是:", e);


        return new UnifyResponse(99999, "服务器异常", req.getMethod() + " " + req.getRequestURI());

    }


}

总结:

  • 自定义已知异常其实是用把异常当做通知表达出来,传递到前端和日志系统
  • httpStatus和自定义的错误码是两个维度的东西
  • 在全局异常类里面我们要做的:
    1、捕获未知的异常,拦截出来定义出500 的系统异常
    2、已知的异常主动抛出,分门别类的用自定义异常类来抛出,通知给前端
  • 作为使用异常框架的同学只需要
    1、维护自定义异常码的配置文件
    2、在业务代码中抛出异常并传入错误码
©️2020 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页