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
package com.panzhihua.service_bracelet.config;
 
import com.alibaba.fastjson.JSONObject;
import com.panzhihua.common.model.vos.R;
import com.panzhihua.common.utlis.DateUtils;
import lombok.extern.slf4j.Slf4j;
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 javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
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;
 
/**
 * 应用模块名称
 * <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中,再用定时每周一次同步到库中
    }
 
}