Java异常精确定位和责任人

通过自定义注解和切面,实现异常时精确显示代码责任人、方法及参数,提高开发效率。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

本文将告诉你一个让测试和开发 知道一个异常出现的时候,导致这个异常出现的原因是谁写的啥方法,入参是什么,达到不扯皮,精确定位的目的,但是如何知道是谁写的呢,我们需要自定义一个注解。

import static java.lang.annotation.RetentionPolicy.RUNTIME;

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;

@Documented
@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RUNTIME)
public @interface Author {
    String value() default "";
}

 

定义一个异常类

package javax.com.vanrui.exception;//必须以Java或者Javax开头包名,否则会出大事,因为我使用的是dubboX

import java.io.Serializable;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

/**
 * 自定义异常类(继承运行时异常)
 * @author yangjiangcai
 * @version 2019/01/07
 */
public class MyRuntimeException extends RuntimeException implements Serializable{

    private static Logger log = LogManager.getLogger(MyRuntimeException.class.getName());
    
    private static final long serialVersionUID = 1L;

    public String author;
    
    public String method;
    
    public  String paramJson;
   
    public String message;
    
    public String errorCode;
    
    public MyRuntimeException() {
        super();
    }
    
    public MyRuntimeException(String message) {
        super();
        log.error(message);
        this.message = message;
    }
    
    public MyRuntimeException(String code,String message) {
        super();
        log.error(message);
        this.message = message;
        this.errorCode=code;
    }
    
    public MyRuntimeException(String author, String method, String paramJson, String message) {
        super();
        this.author = author;
        this.method = method;
        this.paramJson = paramJson;
        this.message = message;
    }
    

    public MyRuntimeException(String author, String method, String paramJson, String message, String code) {
        super();
        this.author = author;
        this.method = method;
        this.paramJson = paramJson;
        this.message = message;
        this.errorCode = code;
    }


    public String getAuthor() {
        return author;
    }

    public void setAuthor(String author) {
        this.author = author;
    }

    public String getMethod() {
        return method;
    }

    public void setMethod(String method) {
        this.method = method;
    }

    public String getParamJson() {
        return paramJson;
    }

    public void setParamJson(String paramJson) {
        this.paramJson = paramJson;
    }

    public String getMessage() {
        return message;
    }

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

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

    @Override
    public String toString() {
        StringBuilder builder = new StringBuilder();
        builder.append("MyRuntimeException [author=");
        builder.append(author);
        builder.append(", method=");
        builder.append(method);
        builder.append(", paramJson=");
        builder.append(paramJson);
        builder.append(", message=");
        builder.append(message);
        builder.append(", errorCode=");
        builder.append(errorCode);
        builder.append("]");
        return builder.toString();
    }

    

}

 

定义一个切面 

import java.io.ByteArrayOutputStream;
import java.io.PrintStream;
import java.io.Serializable;
import java.lang.reflect.Method;

import javax.com.vanrui.exception.MyRuntimeException;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

import com.alibaba.fastjson.JSONObject;
import com.vanrui.common.annotation.Author;


/**
 * @author yangjiangcai
 */
@Aspect
@Component
public class ExceptionInterceptor {
    
    private static Logger log = LogManager.getLogger(ExceptionInterceptor.class.getName());
    

    @Pointcut("execution(* com.vanrui..*(..))")
    public void vanrui() {}

    @Around("vanrui()")
    public Object Interceptor(ProceedingJoinPoint pjp) throws Throwable {

        try {
            Object result = pjp.proceed();
            return result;
        } catch (RuntimeException e) {

            if (e instanceof MyRuntimeException) { //这段逻辑是想让异常直接抛出,因为这已经不是第一次补抓
                throw e;
            }

            MethodSignature signature = (MethodSignature) pjp.getSignature();
            Method method = signature.getMethod();

            if (method.isAnnotationPresent(Author.class)) {
                String message = getExceptionAllinformation(e);
                
                Author tagert = method.getAnnotationsByType(Author.class)[0];
                String author = tagert.value();
                Object target2 = pjp.getTarget();

                MyRuntimeException myRuntimeException = new MyRuntimeException();
                myRuntimeException.setAuthor(author);
                myRuntimeException.setMethod(target2.getClass() + "." + method.getName() + "()");
                myRuntimeException.setParamJson(getParam(pjp));
                myRuntimeException.setStackTrace(e.getStackTrace());
                myRuntimeException.setErrorCode(StringUtils.isEmpty(myRuntimeException.getErrorCode())?"1000":myRuntimeException.getErrorCode());
                myRuntimeException.setMessage(author+myRuntimeException.getMethod()+myRuntimeException.getParamJson()+message);
                log.error(message);
                throw myRuntimeException;

            } else {
                throw e;
            }

        }

    }
    
    private String getParam(ProceedingJoinPoint pjp){
        Signature signature = pjp.getSignature(); 
        MethodSignature methodSignature = (MethodSignature) signature;
        JSONObject result = new  JSONObject();

        String[] parameterNames = methodSignature.getParameterNames();
        
        Object[] values = pjp.getArgs();
        if(parameterNames!=null&&parameterNames.length>0) {
            for(int i=0;i<parameterNames.length;i++) {
                if(values[i] instanceof Serializable) {
                    result.put(parameterNames[i], values[i]);
                }
            }
        }
        
        return result.toJSONString();
    }
    
    
     public static String getExceptionAllinformation(Exception ex) {
         ByteArrayOutputStream out = new ByteArrayOutputStream();
         PrintStream pout = new PrintStream(out);
         ex.printStackTrace(pout);
         String ret = new String(out.toByteArray());
         pout.close();
         try {
              out.close();
         } catch (Exception e) {
         }
         return ret;
 }

 

定义一个全局异常拦截器

import java.io.ByteArrayOutputStream;
import java.io.PrintStream;

import javax.com.vanrui.exception.Businessexception;
import javax.com.vanrui.exception.MyRuntimeException;
import javax.servlet.http.HttpServletResponse;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;

import com.vanrui.common.dto.ResponseDTO;
import com.vanrui.common.enums.ResponseEnum;

@ControllerAdvice
public class GlobalExceptionHandler {
    
    private static Logger log = LogManager.getLogger(GlobalExceptionHandler.class.getName());
    
    @ExceptionHandler(value = Exception.class)
    @ResponseBody
    public Object jsonExceptionHandler(HttpServletResponse rep, Exception e) { 
        String message = getExceptionAllinformation(e);
        log.error(message);  
        //e.printStackTrace();
        
        if(e instanceof Businessexception) {
            Businessexception businessexception =(Businessexception)e;
            return new ResponseDTO(businessexception.errorCode,"代码负责人:"+businessexception.getAuthor()+"; 方法:"+businessexception.getMethod()+"; 参数:"+businessexception.getParamJson()+message,null);
        }
        
        if(e instanceof MyRuntimeException) {
            MyRuntimeException myRuntimeException =(MyRuntimeException)e;
            return new ResponseDTO(myRuntimeException.errorCode,"代码负责人:"+myRuntimeException.getAuthor()+"; 方法:"+myRuntimeException.getMethod()+"; 参数:"+myRuntimeException.getParamJson()+message,null);
        }
        
        return new ResponseDTO(ResponseEnum.SYS_ERROR.getCode(),message,null);
    }
    
    
     public static String getExceptionAllinformation(Exception ex) {
         ByteArrayOutputStream out = new ByteArrayOutputStream();
         PrintStream pout = new PrintStream(out);
         ex.printStackTrace(pout);
         String ret = new String(out.toByteArray());
         pout.close();
         try {
              out.close();
         } catch (Exception e) {
         }
         return ret;
 }
 

到此,程序员在写业务逻辑的时候在他写的方法上加上@Author(your name)就可以了

打完收工,这出现异常,异常输出中将可以看到输出的异常中的第一行作者是谁,什么类的啥方法,入参是啥,错误,这样测试人员看到直接找那个人,或者开发人员看见就知道是谁的问题,并且可以直接调试,不用再等问题重现了,可以用这里的信息直接单元调试了,因为知道方法和入参了。

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值