自定义注解监控接口并记录操作日志到数据库

java 复制代码
package io.renren.ascept;

import io.annotation.LogOperation;
import io.common.utils.HttpContextUtils;
import io.common.utils.IpUtils;
import io.common.utils.JsonUtils;
import io.entity.TokenEntity;
import io.renren.entity.mianchong.ApiLogOperationEntity;
import io.renren.enums.OperationStatusEnum;
import io.renren.service.TokenService;
import io.renren.service.mianchong.ApiLogOperationService;
import org.apache.commons.lang3.StringUtils;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
import java.util.Date;

/**
 * @describe 记录操作日志
 */
@Aspect
@Component
public class LogOperationAspect {
    @Resource
    private ApiLogOperationService apiLogOperationService;
    @Resource
    private TokenService tokenService;

    @Pointcut("@annotation(io.renren.annotation.LogOperation)")
    public void logPointCut() {
    }

    @Around("logPointCut()")
    public Object around(ProceedingJoinPoint point) throws Throwable {
        long beginTime = System.currentTimeMillis();
        try {
            //执行方法
            Object result = point.proceed();
            //执行时长(毫秒)
            long time = System.currentTimeMillis() - beginTime;
            //保存日志
            saveLog(point, time, OperationStatusEnum.SUCCESS.value());
            return result;
        } catch (Exception e) {
            //执行时长(毫秒)
            long time = System.currentTimeMillis() - beginTime;
            //保存日志
            saveLog(point, time, OperationStatusEnum.FAIL.value());
            throw e;
        }
    }

    private void saveLog(ProceedingJoinPoint joinPoint, long time, Integer status) throws Exception {
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        Method method = joinPoint.getTarget().getClass().getDeclaredMethod(signature.getName(), signature.getParameterTypes());
        LogOperation annotation = method.getAnnotation(LogOperation.class);

        ApiLogOperationEntity log = new ApiLogOperationEntity();
        if (annotation != null) {
            //注解上的描述
            log.setOperation(annotation.value());
        }

        log.setStatus(status);
        log.setRequestTime((int) time);

        //请求相关信息
        HttpServletRequest request = HttpContextUtils.getHttpServletRequest();
        assert request != null;

        //客户端ip
        log.setIp(IpUtils.getClientIpAddress(request));

        //从header中获取token
        String token = request.getHeader("token");
        //token为空
        if (StringUtils.isBlank(token)) {
            log.setUserAgent("未登录操作");
        } else {
            //查询token信息
            TokenEntity tokenEntity = tokenService.getByToken(token);
            //登录用户信息
            log.setUserAgent(tokenEntity.getUserId().toString());
        }
        log.setRequestUri(request.getRequestURI());
        log.setRequestMethod(request.getMethod());

        //请求参数
        Object[] args = joinPoint.getArgs();
        try {
            String params = JsonUtils.toJsonString(args[0]);
            log.setRequestParams(params);
        } catch (Exception ignored) {
        }

        log.setCreateDate(new Date());
        //保存到DB
        apiLogOperationService.save(log);
    }
}
java 复制代码
package io.annotation;

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * 操作日志注解
 *
 */
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface LogOperation {

    String value() default "";
}

使用方法

java 复制代码
@PostMapping("xxxxx")
    @LogOperation("接口描述")
    public ResponseEntity<?> xxxxxxxx(@RequestBody DTO dto) throws IOException {
    ..............
    }

操作日志表:

sql 复制代码
CREATE TABLE `db_name`.`log_operation`  (
  `id` bigint(0) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT 'id',
  `operation` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '用户操作',
  `request_uri` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '请求URI',
  `request_method` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '请求方式',
  `request_params` text CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL COMMENT '请求参数',
  `request_time` int(0) UNSIGNED NOT NULL COMMENT '请求时长(毫秒)',
  `user_agent` varchar(500) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '用户代理',
  `ip` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '操作IP',
  `status` tinyint(0) UNSIGNED NOT NULL COMMENT '状态  0:失败   1:成功',
  `creator_name` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '用户名',
  `creator` bigint(0) NULL DEFAULT NULL COMMENT '创建者',
  `create_date` datetime(0) NULL DEFAULT NULL COMMENT '创建时间',
  PRIMARY KEY (`id`) USING BTREE,
  INDEX `idx_create_date`(`create_date`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci COMMENT = '操作日志' ROW_FORMAT = Dynamic;
相关推荐
Leo.yuan5 分钟前
不同数据仓库模型有什么不同?企业如何选择适合的数据仓库模型?
大数据·数据库·数据仓库·信息可视化·spark
麦兜*22 分钟前
MongoDB 6.0 新特性解读:时间序列集合与加密查询
数据库·spring boot·mongodb·spring·spring cloud·系统架构
chat2tomorrow25 分钟前
数据采集平台的起源与演进:从ETL到数据复制
大数据·数据库·数据仓库·mysql·低代码·postgresql·etl
a5876925 分钟前
消息队列(MQ)初级入门:详解RabbitMQ与Kafka
java·分布式·microsoft·面试·kafka·rabbitmq
稻草人想看远方28 分钟前
关系型数据库和非关系型数据库
数据库
考虑考虑28 分钟前
Postgerssql格式化时间
数据库·后端·postgresql
千里码aicood37 分钟前
【springboot+vue】党员党建活动管理平台(源码+文档+调试+基础修改+答疑)
java·数据库·spring boot
Chan1641 分钟前
【智能协同云图库】基于统一接口架构构建多维度分析功能、结合 ECharts 可视化与权限校验实现用户 / 管理员图库统计、通过 SQL 优化与流式处理提升数据
java·spring boot·后端·sql·spring·intellij-idea·echarts
先做个垃圾出来………1 小时前
差分数组(Difference Array)
java·数据结构·算法
TDengine (老段)1 小时前
TDengine 选择函数 Max() 用户手册
大数据·数据库·物联网·时序数据库·tdengine·涛思数据