全局异常捕获-SpringBoot如何优雅的写一个自己的异常捕获工具并使用日记进行记录

全局异常捕获-SpringBoot如何优雅的写一个自己的异常捕获工具并使用日记进行记录

​ 在进行设置自己的异常捕获器之前,我先介绍一下怎么记录日志,记录日志可以使用SpringBoot内部的框架logback,不需要引坐标.如果想要生成日志文件方便检查的话就需要配置文件(最好是按天生成日志,可以根据日志查看程序的执行过程)废话不多说直接上代码!!!

在resources添加配置文件:logback-spring.xml


<configuration scan="true" scanPeriod="60 seconds" debug="false">
    <contextName>logbackcontextName> 
    <appender name="console" class="ch.qos.logback.core.ConsoleAppender">
        <encoder>
            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger- %msg%npattern>
        encoder>
    appender> 
    <appender name="logFile" class="ch.qos.logback.core.rolling.RollingFileAppender">
        
        <Prudent>falsePrudent>
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <FileNamePattern>logs/consumer/%d{yyyy-MM-dd}.logFileNamePattern> 
        rollingPolicy>
        <encoder>
            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger- %msg%npattern>
        encoder>
    appender>
    <root level="info">
        <appender-ref ref="console"/>
        <appender-ref ref="logFile"/>
    root>
configuration>

配置加好后,这个时候重新启动项目,如果在项目列表中发现多了一个文件:
全局异常捕获-SpringBoot如何优雅的写一个自己的异常捕获工具并使用日记进行记录_第1张图片

那么说明你的配置已经生效了,那么接下来就开始全局异常捕获器的编写:

首先写一个服务的接口:

/**
 * @description 服务的接口
 * @author zhangfc
 * @2021-04-22 08:38:25
 *
 */
public interface BaseErrorInfoInterface {
     

    /**
     * 错误码
     * @return
     */
    public String getResultCode();

    /**
     * 错误信息
     * @return
     */
    public String getResultMsg();

}

接下来写一个异常信息的枚举将错误信息进行分类:

/**
 *
 * @description 异常信息的枚举
 * @date 2021-04-22 08:58:01
 * @author zhangfc
 * @version V0.1
 *
 */
public enum ExceptionEnum implements BaseErrorInfoInterface {
     

    SUCCESS("2000","成功!"),
    NUM_ERROR("4000","数据计算错误!"),
    NULL_ERROR("4001","空指针异常"),
    SYS_ERROR("5000","服务器出现错误!"),
    SYS_BUSY("5001","服务器繁忙!")

    ;
    //返回的错误状态码
    private final String resultCode;

    //返回的错误状态信息
    private final String resultMsg;
    ExceptionEnum(String code,String msg){
     
        this.resultCode = code;
        this.resultMsg = msg;
    }
    @Override
    public String getResultCode() {
     
        return this.resultCode;
    }

    @Override
    public String getResultMsg() {
     
        return this.resultMsg;
    }
}

接下来写一个自定义的数据传输类:

/**
 * @author : zhangfc
 * @version : V0.1
 * @description : 自定义数据传输
 * @date : 2021-04-22 09:22:07
 */
@Setter
@Getter
public class ResultResponse {
     
    //响应码
    private String code;

    //响应信息
    private String msg;

    //响应结果
    private Object result;

    /**
     * @return
     * @description 成功
     */
    public static ResultResponse success() {
     
        return success(null);
    }

    /**
     * @param data
     * @return
     * @description 成功
     */
    public static ResultResponse success(Object data) {
     
        ResultResponse resultResponse = new ResultResponse();
        //响应信息加上成功状态码
        resultResponse.setCode(ExceptionEnum.SUCCESS.getResultCode());
        //响应信息加上成功状态信息
        resultResponse.setMsg(ExceptionEnum.SUCCESS.getResultMsg());
        //响应信息加上返回数据
        resultResponse.setResult(data);
        return resultResponse;
    }

    /**
     * @description 失败
     * @param baseErrorInfoInterface
     * @return
     */
    public static ResultResponse error(BaseErrorInfoInterface baseErrorInfoInterface) {
     
        ResultResponse resultResponse = new ResultResponse();
        resultResponse.setCode(baseErrorInfoInterface.getResultCode());
        resultResponse.setMsg(baseErrorInfoInterface.getResultMsg());
        resultResponse.setResult(null);
        return resultResponse;
    }

    /**
     * @description 失败
     * @param code
     * @param msg
     * @return
     */
    public static ResultResponse error(String code,String msg){
     
        ResultResponse resultResponse = new ResultResponse();
        resultResponse.setCode(code);
        resultResponse.setMsg(msg);
        resultResponse.setResult(null);
        return resultResponse;
    }

    /**
     * @description 失败
     * @param msg
     * @return
     */
    public static ResultResponse error(String msg){
     
        ResultResponse resultResponse = new ResultResponse();
        resultResponse.setCode("-1");
        resultResponse.setMsg(msg);
        resultResponse.setResult(null);
        return resultResponse;
    }

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

写一个自己定义的异常类,这个异常主要是在业务逻辑中手动抛出的异常,便于自己快速找到问题的所在:

/**
 * @author zhangfc
 * @description 自定义的异常类
 * @date 2021-04-22 09:02:17
 */
public class VerbException extends RuntimeException implements Serializable {
     
    //序列化
    private static final long serialVersionUID = 1L;
    //错误状态码
    String errorCode;

    //错误状态信息
    String errorMsg;

    public VerbException() {
     
        super();
    }

    public VerbException(BaseErrorInfoInterface errorInfoInterface) {
     
        super(errorInfoInterface.getResultCode());
        this.errorCode = errorInfoInterface.getResultCode();
        this.errorMsg = errorInfoInterface.getResultMsg();
    }

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

    public VerbException(String errorMsg) {
     
        super(errorMsg);
        this.errorMsg = errorMsg;
    }

    public VerbException(String errorCode, String errorMsg) {
     
        super(errorCode);
        this.errorCode = errorCode;
        this.errorMsg = errorMsg;
    }

    public VerbException(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;
    }
    //用于填充执行堆栈跟踪,此方法在此对象中记录该线程的堆栈帧的当前状态
    @Override
    public synchronized Throwable fillInStackTrace() {
     
        return this;
    }
}

接下来写一个全局的异常捕获器用来捕获程序中出现的异常:

/**
 *
 * @description : 全局异常捕获器
 * @author : zhangfc
 * @date :  2021-04-21 22:34:34
 * @version : V0.1
 *
 */
@ControllerAdvice //ControllerAdvice 这个注解就是异常捕获器的注解用来拦截运行时出现的异常
public class MyExceptionHandler {
     
    //日志记录
    private static final Logger logger = LoggerFactory.getLogger(MyExceptionHandler.class);
    /**
     * @description 自定义的异常捕捉
     * @param request
     * @param verb
     * @return
     */
    @ExceptionHandler(value = VerbException.class)//这个注解是拦截的value中异常类型可以是多个当多个时格式是{A,B}中间以逗号间隔
    @ResponseBody//结果以json格式返回
    public ResultResponse verbExceptionHandler(HttpServletRequest request,VerbException verb){
     
        logger.error("业务出现异常错误原因:{}",verb.getErrorMsg());
        return ResultResponse.error(verb.getErrorCode(),verb.getErrorMsg());
    }

    /**
     * @description 空指针异常处理
     * @param request
     * @param e
     * @return
     */
    @ExceptionHandler(value = NullPointerException.class)//这个注解是拦截的value中异常类型可以是多个
    @ResponseBody//结果以json格式返回
    public ResultResponse nullExceptionHandler(HttpServletRequest request,NullPointerException e) {
     
        logger.error("空指针异常,异常原因:{}",e.getMessage());
        return ResultResponse.error(ExceptionEnum.NULL_ERROR);
    }

    /**
     * @description 捕捉其他的一些异常
     * @param request
     * @param e
     * @return
     */
    @ExceptionHandler(value = Exception.class)//这个注解是拦截的value中异常类型可以是多个
    @ResponseBody//结果以json格式返回
    public ResultResponse exceptionHandler(HttpServletRequest request,Exception e){
     
        logger.error("出现其他异常:{}",e.getMessage());
        return ResultResponse.error(ExceptionEnum.SYS_BUSY);
    }
}

最后就开始验证之前所写的异常捕获器是否有效了:

我在controller层进行测试:

@RestController
@RequestMapping("/order")
public class OrderController {
     
    //记录日志
    private static final Logger logger = LoggerFactory.getLogger(OrderController.class);

    @GetMapping("/findone/{id}")
    public ResultResponse findOnebyId(@PathVariable("id") String id) {
     
         //这里我人为的造出一个空指针异常
        String ss = null;
        ss.equals("ss");
        return ResultResponse.success();
    }

}

启动项目测试结果

全局异常捕获-SpringBoot如何优雅的写一个自己的异常捕获工具并使用日记进行记录_第2张图片

说明自己的异常捕获器生效!!

接下来再抛出一个自定义的异常:

@RestController
@RequestMapping("/order")
public class OrderController {
     
    //记录日志
    private static final Logger logger = LoggerFactory.getLogger(OrderController.class);

    @GetMapping("/findone/{id}")
    public ResultResponse findOnebyId(@PathVariable("id") String id) {
     
        //这里我人为的抛出一个人为异常
        if ("1".equals(id)) {
     
            throw new VerbException("-1", "业务出现错误");
        }
        return ResultResponse.success();
    }
}

测试结果:

全局异常捕获-SpringBoot如何优雅的写一个自己的异常捕获工具并使用日记进行记录_第3张图片

这样的错误信息即让自己能快速定位到错误,又能让别人看起来很舒服.

你可能感兴趣的:(java)