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;
|
}
|
|
}
|