Kevin's blog Kevin's blog
首页
  • AI基础
  • RAG技术
  • 提示词工程
  • Wireshark抓包
  • 常见问题
  • 数据库
  • 代码技巧
  • 浏览器
  • 手册教程
  • 技术应用
  • 流程规范
  • github技巧
  • git笔记
  • vpn笔记
  • 知识概念
  • 学习笔记
  • 环境搭建
  • linux&运维
  • 微服务
  • 经验技巧
  • 实用手册
  • arthas常用
  • spring应用
  • javaAgent技术
  • 网站
友情链接
  • 分类
  • 标签
  • 归档

Kevin

你可以迷茫,但不可以虚度
首页
  • AI基础
  • RAG技术
  • 提示词工程
  • Wireshark抓包
  • 常见问题
  • 数据库
  • 代码技巧
  • 浏览器
  • 手册教程
  • 技术应用
  • 流程规范
  • github技巧
  • git笔记
  • vpn笔记
  • 知识概念
  • 学习笔记
  • 环境搭建
  • linux&运维
  • 微服务
  • 经验技巧
  • 实用手册
  • arthas常用
  • spring应用
  • javaAgent技术
  • 网站
友情链接
  • 分类
  • 标签
  • 归档
  • 常见问题

  • 数据库

  • 代码技巧

    • mybatis

      • mybatis技巧
    • 几分钟处理完30亿个数据
    • AOP实现请求日志
      • JSON处理
      • 枚举类型的全面处理
      • httpClientUtil
      • 如何优雅的写 Controller 层代码
      • 看源码技巧
      • http-curl例子
      • 动态的添加注解信息
      • 手动安装jar到maven仓库
    • 浏览器

    • spring应用

    • 使用Java Agent字节码技术扩展
    • 什么是AP,什么是CP,什么是CAP
    • RabbitMq相关
    • ELK查询技巧
    • 性能优化手段
    • 经验技巧
    • 代码技巧
    kevin
    2022-06-13
    目录

    AOP实现请求日志

    使用AOP实现请求和返回日志打印

    # 一、自定义注解

    /***
     * @Description: 接口日志注解
     */
    @Target(ElementType.METHOD)
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    public @interface ApiLog {
    
        /**
         * 日志描述
         *
         * @return
         */
        String value() default "";
    
        /**
         * kafka 主题
         *
         * @return
         */
        String topic() default "";
    
    }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23

    # 二、AOP拦截处理

    import com.alibaba.fastjson.JSONObject;
    import com.cloudwarehouse.core.log.annotation.ApiLog;
    import com.cloudwarehouse.core.log.kafka.KafkaSender;
    import lombok.extern.slf4j.Slf4j;
    import org.aspectj.lang.JoinPoint;
    import org.aspectj.lang.ProceedingJoinPoint;
    import org.aspectj.lang.annotation.AfterThrowing;
    import org.aspectj.lang.annotation.Around;
    import org.aspectj.lang.annotation.Aspect;
    import org.aspectj.lang.annotation.Pointcut;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Component;
    import org.springframework.web.context.request.RequestContextHolder;
    import org.springframework.web.context.request.ServletRequestAttributes;
    
    import javax.servlet.http.HttpServletRequest;
    import java.lang.reflect.Method;
    import java.text.SimpleDateFormat;
    import java.util.Date;
    import java.util.UUID;
    
    /***
     * @Description: 系统接口日志切片
     */
    @Aspect
    @Component
    @Slf4j
    public class ApiLogAspect {
    
        @Autowired
        private KafkaSender<JSONObject> kafkaSender;
    
        // 申明一个切点 里面是 annotation
        @Pointcut("@annotation(com.XXX.ApiLog)")
        private void serviceAspect() {
        }
    
        @Around(value = "serviceAspect()")
        public Object methodAround(ProceedingJoinPoint joinPoint) throws Throwable {
    
            ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
            HttpServletRequest request = requestAttributes.getRequest();
    
            JSONObject jsonObject = new JSONObject();
    
            // 接口描述
            String value = getSystemApiLogMethodAnnotation((ProceedingJoinPoint) joinPoint, "value");
            // kafka消息主题
            String topic = getSystemApiLogMethodAnnotation((ProceedingJoinPoint) joinPoint, "topic");
            // 请求时间 // 设置日期格式
            SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            jsonObject.put("request_time", df.format(new Date()));
            // 请求URL
            jsonObject.put("request_url", request.getRequestURL().toString());
            // 请求的方法
            jsonObject.put("request_method", request.getMethod());
            // 请求类方法
            jsonObject.put("signature", joinPoint.getSignature().getName());
            // 请求参数
            jsonObject.put("request_args", getRequestParams(joinPoint));
            // 请求时间
            long beginTime = System.currentTimeMillis();
            // 执行目标方法
            Object result = joinPoint.proceed();
            // 执行时长(毫秒)
            long total_time = System.currentTimeMillis() - beginTime;
    
            JSONObject requestJsonObject = new JSONObject();
            requestJsonObject.put("description", value);
            requestJsonObject.put("request", jsonObject);
            requestJsonObject.put("response", result);
            requestJsonObject.put("total_time", total_time);
    
            // 打印日志到本地
            printLocalLog((ProceedingJoinPoint) joinPoint, JSONObject.toJSONString(result), total_time);
    //        if (!topic.isEmpty()) {
    //            // 发送到MQ Kafka消息中间件
    //            kafkaSender.send(topic, requestJsonObject);
    //        }
            return result;
        }
    
        @AfterThrowing(pointcut = "serviceAspect()", throwing = "e")
        public void logAfterThrowing(JoinPoint joinPoint, Throwable e) throws Exception {
            ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
            HttpServletRequest request = requestAttributes.getRequest();
    
            JSONObject jsonObject = new JSONObject();
    
            // 接口描述
            String value = getSystemApiLogMethodAnnotation((ProceedingJoinPoint) joinPoint, "value");
            // kafka消息主题
            String topic = getSystemApiLogMethodAnnotation((ProceedingJoinPoint) joinPoint, "topic");
            // 请求时间
            SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            jsonObject.put("request_time", df.format(new Date()));
            // 请求URL
            jsonObject.put("request_url", request.getRequestURL().toString());
            // 请求的方法
            jsonObject.put("request_method", request.getMethod());
            // 请求类方法
            jsonObject.put("signature", joinPoint.getSignature().getName());
            // 请求参数
            jsonObject.put("request_args", getRequestParams(joinPoint));
            // 请求时间
            long beginTime = System.currentTimeMillis();
    
            Object result = e.getMessage();
    
            // 执行时长(毫秒)
            long total_time = System.currentTimeMillis() - beginTime;
    
            JSONObject requestJsonObject = new JSONObject();
            requestJsonObject.put("description", value);
            requestJsonObject.put("request", jsonObject);
            requestJsonObject.put("response", result);
            requestJsonObject.put("total_time", total_time);
    
            // 打印日志到本地
            printLocalLog((ProceedingJoinPoint) joinPoint, JSONObject.toJSONString(result), total_time);
    
    //        if (!topic.isEmpty()) {
    //            // 发送到MQ Kafka消息中间件
    //            kafkaSender.send(topic, requestJsonObject);
    //        }
    
        }
    
        public void printLocalLog(ProceedingJoinPoint joinPoint, String response_result, long total_time) throws Exception {
            String value = getSystemApiLogMethodAnnotation(joinPoint, "value");
            String method = joinPoint.getSignature().getName();
            StringBuilder request_params = new StringBuilder();
            if(joinPoint.getArgs().length > 0){
                for (int i = 0; i <joinPoint.getArgs().length; i++) {
                    request_params.append(JSONObject.toJSONString(joinPoint.getArgs()[i]));
                }
            }
            log.info("{},调用[{}] 方法开始", value, method);
            log.info("{},请求参数:{}", value, request_params);
            log.info("{},响应结果:{}", value, response_result);
            log.info("{},调用[{}] 方法结束,耗时{}毫秒", value, method, total_time);
        }
    
    
        /**
         * 获取请求参数
         *
         * @param joinPoint
         * @return
         */
        public Object getRequestParams(JoinPoint joinPoint) {
            StringBuilder request_params = new StringBuilder();
            if(joinPoint.getArgs().length > 0){
                for (int i = 0; i <joinPoint.getArgs().length; i++) {
                    request_params.append(JSONObject.toJSONString(joinPoint.getArgs()[i]));
                }
            }
            return  request_params;
        }
    
        /**
         * 获取注解内容
         *
         * @param point
         * @param attribute
         * @return
         * @throws Exception
         */
        public String getSystemApiLogMethodAnnotation(ProceedingJoinPoint point, String attribute) throws Exception {
            //获取连接点目标类名
            String targetName = point.getTarget().getClass().getName();
            //获取连接点签名的方法名
            String methodName = point.getSignature().getName();
            //获取连接点参数
            Object[] args = point.getArgs();
            //根据连接点类的名字获取指定类
            Class targetClass = Class.forName(targetName);
            //获取类里面的方法
            Method[] methods = targetClass.getMethods();
            String result = "";
            for (Method method : methods) {
                if (method.getName().equals(methodName)) {
                    Class[] clazzs = method.getParameterTypes();
                    if (clazzs.length == args.length) {
                        if ("value".equals(attribute)) {
                            result = method.getAnnotation(ApiLog.class).value();
                        } else if ("topic".equals(attribute)) {
                            result = method.getAnnotation(ApiLog.class).topic();
                        }
                        break;
                    }
                }
            }
            return result;
        }
    }
    
    
    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

    # 三、kafka

    import com.alibaba.fastjson.JSON;
    import lombok.extern.slf4j.Slf4j;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.kafka.core.KafkaTemplate;
    import org.springframework.kafka.support.SendResult;
    import org.springframework.scheduling.annotation.Async;
    import org.springframework.stereotype.Component;
    import org.springframework.util.concurrent.ListenableFuture;
    import org.springframework.util.concurrent.ListenableFutureCallback;
    
    /***
     * @Description: 日志采集  Kafka生产者
     */
    @Component
    @Slf4j
    public class KafkaSender<T> {
    
        @Autowired
        private KafkaTemplate<String, Object> kafkaTemplate;
    
        /**
         * kafka 发送消息
         * @param log_topic 主题
         * @param obj       消息对象
         */
        @Async
        public void send(String log_topic, T obj) {
            String jsonObj = JSON.toJSONString(obj);
            // log.info("Produce: 消息发送到Kafka:{}", jsonObj);
            // 发送消息 实现可配置化 主题是可配置化
            ListenableFuture<SendResult<String, Object>> future = kafkaTemplate.send(log_topic, jsonObj);
            future.addCallback(new ListenableFutureCallback<SendResult<String, Object>>() {
                @Override
                public void onFailure(Throwable throwable) {
                    log.info("Produce: 消息发送到Kafka失败:" + throwable.getMessage());
                }
    
                @Override
                public void onSuccess(SendResult<String, Object> stringObjectSendResult) {
                    // TODO 业务处理
                    log.info("Produce: 消息发送到Kafka成功:{}", stringObjectSendResult.toString());
                }
            });
        }
    }
    
    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
    上次更新: 2022/08/30, 13:59:56
    几分钟处理完30亿个数据
    JSON处理

    ← 几分钟处理完30亿个数据 JSON处理→

    最近更新
    01
    AI是如何学习的
    06-05
    02
    chatGpt提示原则
    06-05
    03
    提示词工程实践指南
    06-05
    更多文章>
    | Copyright © 2022-2025 Kevin | MIT License
    • 跟随系统
    • 浅色模式
    • 深色模式
    • 阅读模式