package com.vci.starter.common.log; import com.vci.starter.web.annotation.log.VciUnLog; import com.vci.starter.common.log.autoconfigure.VciAutoLogConfigure; import com.vci.starter.web.enumpck.LogLevelEnum; import com.vci.starter.web.util.LangBaseUtil; import org.aspectj.lang.JoinPoint; import org.aspectj.lang.annotation.*; import org.aspectj.lang.reflect.MethodSignature; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.core.DefaultParameterNameDiscoverer; import org.springframework.core.ParameterNameDiscoverer; import org.springframework.stereotype.Component; import java.lang.reflect.Method; import java.util.Arrays; import java.util.Collection; import java.util.Map; /** * 日志记录切面 * @author weidy * @date 2020/4/10 */ @Aspect @Component public class VciComponentLogAspect { /** * 当前类的日志输出 */ private Logger logger = LoggerFactory.getLogger(getClass()); /** * 日志的配置 */ @Autowired private VciAutoLogConfigure logConfigure; /** * 所有的controller,component,service都监控 */ @Pointcut("execution(public * com.vci..*.*(..)) && (@target(org.springframework.web.bind.annotation.RestController) " + "|| @target(org.springframework.stereotype.Controller) || @target(org.springframework.stereotype.Service)" + "|| @target(org.springframework.stereotype.Component)) && !(@target(com.vci.starter.web.annotation.log.VciUnLog)) ") public void vciComponentLog(){} /** * 在切入点的方法执行之前,获取方法的参数 * @param joinPoint 切入点 */ @Before("vciComponentLog()") public void enterMethodLog(JoinPoint joinPoint){ Method method = getMethod(joinPoint); try { if (logConfigure.isShowLog() && !checkIsUnLog(method)) { //说明要记录日志 Logger beforeLogger = LoggerFactory.getLogger(joinPoint.getTarget().getClass()); //要把参数打印出来 ParameterNameDiscoverer pnd = new DefaultParameterNameDiscoverer(); if (method != null) { String[] parameterNames = pnd.getParameterNames(method); Object[] args = joinPoint.getArgs(); String logMsg = "调用了" + joinPoint.getSignature().getName() + "方法"; if (parameterNames != null && parameterNames.length > 0) { logMsg += ",参数为空"; } else { for (int i = 0; i < parameterNames.length; i++) { logMsg += parameterNames[i] + "=" + getParamString(args[i]) + ";"; } } if (LogLevelEnum.INFO.name().equalsIgnoreCase(logConfigure.getVciLogLevel()) && beforeLogger.isInfoEnabled()) { beforeLogger.info(logMsg); } if (LogLevelEnum.DEBUG.name().equalsIgnoreCase(logConfigure.getVciLogLevel()) && beforeLogger.isDebugEnabled()) { beforeLogger.debug(logMsg); } } else { if (logger.isInfoEnabled()) { logger.info(joinPoint.getTarget().getClass() + "." + joinPoint.getSignature().getName() + "这个方法没有找到Method对象,此处程序可能有问题"); } } } }catch (Throwable e1){ //日志错误了不要影响别的 } } /** * 在抛出异常时记录 * @param joinPoint 切入点 * @param e 异常的变量 */ @AfterThrowing(pointcut = "vciComponentLog()",throwing = "e") public void exceptionMethodLog(JoinPoint joinPoint,Throwable e){ Method method = getMethod(joinPoint); try { if (logConfigure.isShowLog() && !checkIsUnLog(method)) { //说明要记录日志 Logger exceptionLogger = LoggerFactory.getLogger(joinPoint.getTarget().getClass()); //要把异常打印出来 if (exceptionLogger.isErrorEnabled()) { exceptionLogger.error("调用了" + joinPoint.getSignature().getName() + "方法,出现了错误:" + LangBaseUtil.getErrorMsg(e), e); } } }catch (Throwable e1){ //日志错误了不要影响别的 } } /** * 在调用成功后时记录 * @param joinPoint 切入点 * @param returnVal 返回值 */ @AfterReturning(pointcut = "vciComponentLog()",returning = "returnVal") public void returnMethodLog(JoinPoint joinPoint,Object returnVal){ Method method = getMethod(joinPoint); try { if (logConfigure.isShowLog() && !checkIsUnLog(method)) { //说明要记录日志 Logger returnLogger = LoggerFactory.getLogger(joinPoint.getTarget().getClass()); //把返回结果打印出来 String logMsg = "调用" + joinPoint.getSignature().getName() + "方法成功," + getParamString(returnVal); if (LogLevelEnum.INFO.name().equalsIgnoreCase(logConfigure.getVciLogLevel()) && returnLogger.isInfoEnabled()) { returnLogger.info(logMsg); } if (LogLevelEnum.DEBUG.name().equalsIgnoreCase(logConfigure.getVciLogLevel()) && returnLogger.isDebugEnabled()) { returnLogger.debug(logMsg); } } }catch (Throwable e){ //日志错误了不要影响别的 } } /** * 获取被调用的方法 * @param joinPoint 切入点 * @return 调用的方法 */ public Method getMethod(JoinPoint joinPoint){ MethodSignature signature = (MethodSignature) joinPoint.getSignature(); Method method = signature.getMethod(); return method; } /** * 获取参数的内容字符串 * @param obj 参数对象 * @return 参数转成字符串 */ public String getParamString(Object obj){ if(obj == null){ return "没有返回值"; }else{ //看看是否集合 if(obj instanceof Collection){ final String[] paStr = {"["}; ((Collection)obj).stream().limit(10).forEach(s->{ if(s!=null) { paStr[0] += s.toString() + ","; }else{ paStr[0] += "null,"; } }); return paStr[0] + "]"; }else if(obj instanceof Map){ final String[] paStr = {"{"}; ((Map)obj).forEach((k,v)->{ if(v!=null) { paStr[0] += k + ":" + v.toString() + ","; }else{ paStr[0] += k + ":null,"; } }); return paStr[0] + "}"; }else if(obj.getClass().isArray()){ //说明是数组 final String[] paStr = {"["}; Arrays.stream(((Object[]) obj)).limit(10).forEach( s->{ if(s instanceof String) { if (s != null ) { paStr[0] += s.toString() + ","; } else { paStr[0] += "null,"; } } }); return paStr[0] + "]"; }else { return obj.toString(); } } } /** * 获取方法是否记录日志 * @param method 被调用的方法 * @return true 表示不记录日志 */ private boolean checkIsUnLog(Method method){ //如果整个类添加了vciUnLog注解时,不会进入到这个方法中 if(method != null && method.isAnnotationPresent(VciUnLog.class)){ return true; } return false; } }