自定义全局处理异常,并将报错的类名、方法名和行数 返回给前端

背景说明

之前在开发项目时,项目时一边开发 ,一边在生产环境中提供服务。由于处于开发前期,项目代码不是很健壮,再加上生产环境多变(不可控)和人员操作不当,导致异常频频发生。二生产环境 只能看到部分日志 和db,虽然可排查,但是耗时耗力,定位错误的成本非常大。于是 就想 :程序在报错时,如果可以把报错所在的类、方法、以及行数 返回给前端,这样的话,排查与定位 就会变得非常轻松,只需要根据返回的信息 ,直接找到那行代码即可。

原理

根据jvm的运行机制可知, 一个线程的执行,它所有的链路信息,都会存储在堆栈当中,包括调用关系,如:谁调用谁

开发

springboot + 自定义异常 + RestControllerAdvice全局异常处理
注: 本文的代码 , 均为模拟代码,点到为止。

自定义异常类

本文的堆栈信息获取 放在了 自定义异常类里。如需放在其它位置 ,则需要 debug : StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace();
这行代码 ,查看 你需要的信息 在堆栈信息数组中的位置

package com.example.myexception.excetion;

public class MyException  extends  RuntimeException{

    private String message;

    @Override
    public String getMessage() {
        return message;
    }

    public MyException() {

    }
    public MyException(String message) {
        //获取当前线程的堆栈信息 (里面包含整个链路的调用信息 ,包括谁调用谁的关系信息)  
        StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace();
        //拿到 调用 此 构造方法的 上层方法的堆栈信息 下面获取数组的下标 2  ,这个下标2是经过多次debug 查找自己所需的数据在哪个位置后 才确定下来的。如果需要在其它地方获取堆栈信息 ,则请自行debug寻找下标。
        StackTraceElement father = stackTrace[2];
        int lineNumber = father.getLineNumber();
        String className = father.getClassName();
        String methodName = father.getMethodName();
        String messageOfClass=",异常定位辅助信息:{类名:"+className+",方法名:"+methodName+",行数:"+lineNumber+"}";
        this.message=message + messageOfClass;
      

    }

}

返回体

package com.example.myexception.excetion;

public class RespsonseResult
{
    private String CODE="异常处理状态";

    private String message;

    public RespsonseResult(String message) {
        this.message = message;
    }

    public String getMessage() {
        return message;
    }

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

    public String getCODE() {
        return CODE;
    }
}

全局异常处理器

package com.example.myexception.excetion;


import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;

@RestControllerAdvice
public class GloadExceptionHandle {

    @ExceptionHandler(MyException.class)
    public  RespsonseResult handle(MyException mex){


        return  new RespsonseResult(mex.getMessage());
    }
}

controller

controller层设置的返回为空,当发生异常 且被捕获时 ,则返回的对象 上面定义的返回体,差异化处理 方便做对比

package com.example.myexception.controller;


import com.example.myexception.excetion.MyException;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/test")
public class TestController {

    @GetMapping("/test")
    public  void test(){
        try {
        //模拟异常
            int a=10/0;
        } catch (Exception e) {
            System.out.println(e);
            throw new MyException(e.getMessage());
        }
    }
}

实测

通过postman 调用该接口 : loalhost:8080/test/test

返回体

{
    "message": "/ by zero,异常定位辅助信息:{类名:com.example.myexception.controller.TestController,方法名:test,行数:19}",
    "code": "异常处理状态"
}

测试结果成功反悔了 具体是代码哪一行报的问题 ,这样我们变成快速在开发环境或本地定位到问题原因, 从此告别排查难问题 ()

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值