异常统一处理

一、背景

在实际的工作中,在服务与服务之间的交互中,异常是一个很重要的点,这里的异常有的是正常的业务异常,而有些确实程序本身抛出的异常,例如:服务A依赖服务B,服务B出现了NullPointerException,作为调用方,一定要做好异常的处理。下面是小弟在工作过程中,总结出来的一个统一处理异常的工具。

二、代码实现

1、定义服务返回结果DemoResult

public class DemoResult<T> implements Serializable {
    private String errorCode;
    private String message;
    private T t;
    private boolean isSuccess = true;

    public void setDemoResult(boolean isSuccess, String errorCode, String message) {
        this.isSuccess = isSuccess;
        this.errorCode = errorCode;
        this.message = message;
    }

    public String getErrorCode() {
        return errorCode;
    }

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

    public String getMessage() {
        return message;
    }

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

    public T getT() {
        return t;
    }

    public void setT(T t) {
        this.t = t;
    }

    public boolean isSuccess() {
        return isSuccess;
    }

    public void setSuccess(boolean success) {
        isSuccess = success;
    }

    public String toString() {
        return ToStringBuilder.reflectionToString(this, ToStringStyle.SHORT_PREFIX_STYLE);
    }
}

 2、定义自己的异常DemoException

public class DemoException extends RuntimeException {
    private String errorCode;
    private int code;

    public DemoException(String message) {
        super(message);
    }

    public DemoException(String message, String exceptionCode) {
        super(message);
        this.errorCode = exceptionCode;
    }

    public String getErrorCode() {
        return errorCode;
    }

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

    public int getCode() {
        return this.code;
    }

    public void setCode(int code) {
        this.code = code;
    }
}

 3、定义日志上下文LogContext

public class LogContext {

    private String bizLog;

    private long userId;

    public long getUserId() {
        return userId;
    }

    public void setUserId(long userId) {
        this.userId = userId;
    }

    public String getBizLog() {
        return bizLog;
    }

    public void setBizLog(String bizLog) {
        this.bizLog = bizLog;
    }

    public static LogContext build(String bizLog) {
        LogContext logContext = new LogContext();
        logContext.setBizLog(bizLog);
        return logContext;
    }
}

 4、定义日志上下文的Holder

public class LogContextHolder {
    private static final ThreadLocal<LogContext> holder = new ThreadLocal<>();

    public static void set(LogContext context) {
        if (context != null) {
            holder.set(context);
        }
    }

    public static LogContext getContext() {
        return holder.get();
    }

    public static void remove() {
        holder.remove();
    }

    public static String bizLog() {
        LogContext context = getContext();
        if (context == null) {
            return "";
        }
        return context.getBizLog();
    }

    public static long userId() {
        LogContext context = getContext();
        if (context == null) {
            return 0L;
        }
        return context.getUserId();
    }
}

 5、定义异常处理的executor

public class DemoExecutor {
    private static final Logger logger = LoggerFactory.getLogger(DemoExecutor.class);

    public static <T extends DemoResult> T execut(Supplier<T> fn, Class<T> c, String bizCall, Object... param) {
        T result = null;
        String uuid = UUID.randomUUID().toString();
        String logBiz = bizCall + "-" + uuid;
        try {
            logger.info("bizCall={},param={}", bizCall, param);
            Stopwatch stopwatch = Stopwatch.createStarted();
            LogContextHolder.set(LogContext.build(uuid));
            result = c.newInstance();
            result = fn.get();
            long costs = stopwatch.elapsed(TimeUnit.MILLISECONDS);
            result.setDemoResult(true, result.getErrorCode(), result.getMessage());
            logger.info("BizCall={},result={}, costs={}ms", bizCall, result, costs);
        } catch (DemoException e) {
            if (e.getErrorCode() == null) {
                result.setDemoResult(false, e.getCode(), e.getMessage());
            }
            if (e.getErrorCode() != null) {
                logger.error("error occurred at [" + logBiz + "] result=[" + result + "]", e);
                result.setDemoResult(false, e.getCode(), e.getMessage());
            } else {
                logger.error("error occurred at [" + logBiz + "] result=[" + result + "]", e);
            }
        } catch (Throwable e) {
            if (result != null) {
                logger.error("error occurred at [" + logBiz + "] result=[" + result + "]", e);
                result.setDemoResult(false, e.getCode(), e.getMessage());
            } else {
                logger.error("error occurred at [" + logBiz + "], error={}", e);
            }
        } finally {
            LogContextHolder.remove();
        }
        return result;
    }
}

 6、说明:

       此处只是一个简单的demo,具体的业务异常的定义,还要根据系统的业务要求。此外,使用的JDK版本最好是1.8以上,如果你的工作环境还没有用到JDK1.8,自己可以对该工具进行修改,满足自己的需求就行。

猜你喜欢

转载自zh-workhard-java.iteye.com/blog/2347889