mitao
2025-02-21 31573d6180d15ef65ed0df9c2732495f40b12663
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
package com.panzhihua.service_user.config;
 
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
 
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
 
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.core.LocalVariableTableParameterNameDiscoverer;
import org.springframework.util.ObjectUtils;
 
import com.alibaba.fastjson.JSONObject;
import com.panzhihua.common.model.vos.R;
import com.panzhihua.common.utlis.DateUtils;
 
import lombok.extern.slf4j.Slf4j;
 
/**
 * 应用模块名称
 * <p>
 * 代码描述
 * <p>
 * 拦截controller,输出入参、响应内容和响应时间 Copyright: Copyright (C) 2021 XXX, Inc. All rights reserved.
 * <p>
 * Company: 成都呐喊信息技术有限公司
 * <p>
 *
 * @author manailin
 * @since 2021/8/24 15:30
 */
@Slf4j
// @Aspect
// @Component
public class ParamOutAspect {
 
    /**
     * 设定方法的执行时间限制毫秒数
     */
    private long maxReduceTime = 2000;
 
    @Pointcut("execution (public * com.panzhihua.service_user.api..* (..))||execution (public * com.panzhihua.service_user.service..* (..))")
    public void aspect() {}
 
    /**
     * [方法描述] 环绕通知,拦截controller,输出请求参数、响应内容和响应时间
     * 
     * @param joinPoint aspect()
     * @return java.lang.Object
     * @author manailin
     * @date 2021/8/24 17:04
     */
    @Around("aspect()")
    public Object processLog(ProceedingJoinPoint joinPoint) {
        log.info("进入方法性能检查方法");
        Method method = ((MethodSignature)joinPoint.getSignature()).getMethod();
        String className = joinPoint.getSignature().getDeclaringTypeName();
        // 获取方法名称
        String methodName = method.getName();
        // 获取参数名称
        LocalVariableTableParameterNameDiscoverer paramNames = new LocalVariableTableParameterNameDiscoverer();
        String[] params = paramNames.getParameterNames(method);
        // 获取参数
        Object[] args = joinPoint.getArgs();
        // 过滤掉request和response,不能序列化
        List<Object> filteredArgs = Arrays.stream(args)
            .filter(arg -> (!(arg instanceof HttpServletRequest) && !(arg instanceof HttpServletResponse)))
            .collect(Collectors.toList());
        JSONObject rqsJson = new JSONObject();
        rqsJson.put("rqsMethod", methodName);
        rqsJson.put("rqsTime", DateUtils.getCurrentDateStr_MS());
        if (ObjectUtils.isEmpty(filteredArgs)) {
            rqsJson.put("rqsParams", null);
        } else {
            // 拼接请求参数
            Map<String, Object> rqsParams = IntStream.range(0, filteredArgs.size()).boxed()
                .collect(Collectors.toMap(j -> params[j], j -> filteredArgs.get(j)));
            rqsJson.put("rqsParams", rqsParams);
        }
        log.info(className + ":" + methodName + "请求信息为:" + rqsJson.toJSONString());
        Object resObj = null;
        long startTime = System.currentTimeMillis();
        try {
            // 执行原方法
            resObj = joinPoint.proceed();
        } catch (Throwable e) {
            log.error(className + ":" + methodName + "方法执行异常!", e);
        }
        long endTime = System.currentTimeMillis();
        // 打印耗时的信息
        this.printExecTime(className + ":" + methodName, startTime, endTime);
        if (resObj != null) {
            // 打印返回消息
            log.info(className + ":" + methodName + "响应信息为:" + JSONObject.toJSON(resObj));
            return resObj;
        } else {
            return R.ok();
        }
    }
 
    /**
     * [方法描述] 打印方法执行耗时的信息,如果超过了一定的时间,才打印
     * 
     * @param classAndMethodName
     *            执行方法名
     * @param startTime
     *            执行开始时间
     * @param endTime
     *            执行结束时间
     * @author manailin
     * @date 2021/8/24 17:05
     */
    private void printExecTime(String classAndMethodName, long startTime, long endTime) {
        long diffTime = endTime - startTime;
        if (diffTime > maxReduceTime) {
            log.info(classAndMethodName + " 方法执行耗时:" + diffTime + " ms");
        }
        // TODO 可以集成redis,将每个controller的执行时间追加到redis中,再用定时每周一次同步到库中
    }
 
}