ludc
2025-01-16 5203081b68e3a8dc139d1807b2f8774e4a00a82a
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
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;
    }
 
}