java服务-常用技术-在切面中应用统一日志记录器

 java服务-在切面中应用统一日志记录器

在springboot springmvc springcloud 等程序中,我们经常会要记录一些日志信息,但是每次我们都需要每个action单独建立对应的异常捕捉机制,这里就非常麻烦;

所以笔者这里专门制作了一套通用的拦截器和统一的日志记录器,用于在程序入口处卡点,记录用户请求的接口、包名、类名、方法名、入参、出参、请求完整耗时,用于日志记录;

希望能帮助到入门的朋友们;


package com.ikong.aop.log;

import com.alibaba.fastjson.JSON;
import com.ikong.result.Result;
import com.ikong.utils.IkExceptionUtil;
import com.ikong.utils.IkLogger;
import org.aspectj.lang.ProceedingJoinPoint;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class IkLogAspect {
    private boolean logSuccess = false;
    private Boolean logInfo;
    private boolean logErr;
    private static final String ErrorInfo = "统一日志拦截器异常";
    private static final Logger logger = LoggerFactory.getLogger("ikongApectLogger");

    public IkLogAspect(boolean logSuccess) {
        this.logSuccess = logSuccess;
        this.logErr = Boolean.TRUE;
        this.logInfo = Boolean.TRUE;
    }

    public IkLogAspect(Boolean logInfo, boolean logErr, boolean logResult) {
        this.logSuccess = logResult;
        this.logErr = logErr;
        this.logInfo = logInfo;
    }

    public IkLogAspect() {
        this.logErr = Boolean.TRUE;
        this.logInfo = Boolean.TRUE;
        this.logSuccess = Boolean.TRUE;
    }

    public Object proceedWithEx(ProceedingJoinPoint jp) throws Throwable {
        Object ret = null;
        long startTime = System.currentTimeMillis();

        try {
            ret = jp.proceed();
            this.logCompleted(jp, ret, startTime);
            return ret;
        } catch (Throwable var7) {
            String exInfo = this.logException(jp, startTime, var7);
            if (this.logErr) {
                IkLogger.error(exInfo);
            }

            throw var7;
        }
    }

    //统一日志拦截器异常,返回统一的处理信息
    private Object getExceptionResult(String exInfo) {
        Result result = new Result();
        result.setCode(500);
        result.setMessage("统一日志拦截器异常");
        result.setData(exInfo);
        return result;
    }

    //切面执行正常的时候:记录切面完成的请求入参出参日志
    private void logCompleted(ProceedingJoinPoint jp, Object ret, long startTime) {
        StringBuilder sb = new StringBuilder();
        this.logBasic(sb, jp, startTime);
        this.logSuccessResult(sb, ret);
        if (this.logInfo) {
            logger.info(sb.toString());
        }

    }

    //切面执行异常的时候:记录切面请求入参、异常信息和错误日志
    private String logException(ProceedingJoinPoint jp, long startTime, Throwable throwable) {
        StringBuilder sb = new StringBuilder();
        this.logBasic(sb, jp, startTime);
        this.logExceptionResult(sb, throwable);
        String message = sb.toString();
        if (this.logErr) {
            logger.error(message);
        }

        return message;
    }

    //记录类名.方法名.耗时.参数列表
    private void logBasic(StringBuilder sb, ProceedingJoinPoint jp, long startTime) {
        String params = "";

        try {
            if (jp.getArgs() != null) {
                params = JSON.toJSONString(jp.getArgs());
            }
        } catch (Exception var7) {
            if (this.logErr) {
                logger.warn("aop序列化参数失败", var7);
            }
        }

        this.buildPrefix(sb, jp, startTime);
        sb.append("#parameter:");
        sb.append(params);
        sb.append("#result:");
    }

    //组装异常日志信息,将堆栈的信息一并记录
    private void logExceptionResult(StringBuilder sb, Throwable throwable) {
        String result = throwable.toString();
        sb.append(result);
        sb.append("###stack:");
        sb.append(MyExceptionUtil.getStackTrace(throwable));
    }

    //根据日志记录logSuccess标识,来记录成功的日志
    private void logSuccessResult(StringBuilder sb, Object ret) {
        String result = "";

        try {
            if (ret != null && this.logSuccess) {
                result = JSON.toJSONString(ret);
            }
        } catch (Exception var5) {
            if (this.logErr) {
                logger.warn("aop序列化结果失", var5);
            }
        }

        sb.append(result);
    }

    //这里组装类名.方法名.请求耗时
    private void buildPrefix(StringBuilder sb, ProceedingJoinPoint jp, long startTime) {
        long cost = System.currentTimeMillis() - startTime;
        String clazz = jp.getTarget().getClass().getSimpleName();
        String method = jp.getSignature().getName();
        sb.append("class:");
        sb.append(clazz);
        sb.append("#method:");
        sb.append(method);
        sb.append("#cost:");
        sb.append(cost);
    }

    //获取全路径下的方法名
    public String getMethodName(ProceedingJoinPoint jp) {
        StringBuilder sb = new StringBuilder();
        String clazz = jp.getTarget().getClass().getName();
        String method = jp.getSignature().getName();
        sb.append(clazz);
        sb.append(".");
        sb.append(method);
        return sb.toString();
    }
}

日志拦截器的应用

package com.ikong.aop.log;

import com.ikong.aop.log.IkLogAspect;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

/**
 * @author ikong
 */
@Aspect
@Component
@Order(1)
public class RequestLogAspectHandler {

    private final static String POINT = "execution (* com.ikong.web.api.controller..*.*(..))";

    private final IkLogAspect handler = new IkLogAspect(false, false, false);

    private static final Logger LOG = LoggerFactory.getLogger(RequestLogAspectHandler.class);

    @Around(value = POINT)
    public Object printLog(ProceedingJoinPoint jp) {
        Object ret = null;
        try {
            String key = handler.getMethodName(jp);
            ret = handler.proceedWithEx(jp);
        } catch (Throwable throwable) {
            LOG.error("error:{}",throwable.getMessage());
        } finally {
        }
        return ret;
    }
}

补充涉及到的代码


public class MyExceptionUtil {

    public MyExceptionUtil() {}

    public static String getStackTrace(Throwable throwable) {
        StringWriter sw = new StringWriter();
        PrintWriter pw = new PrintWriter(sw);

        String var3;
        try {
            throwable.printStackTrace(pw);
            var3 = sw.toString();
        } finally {
            pw.close();

            try {
                sw.close();
            } catch (IOException var10) {
                var10.printStackTrace();
            }
        }
        return var3;
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

码者人生

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值