业务需求-用AOP记录系统操作日志

简介: 全栈老司机 程序员林中酒 更新了本文详细介绍了如何使用AOP(面向切面编程)记录系统操作日志的业务需求,包括需求分析、技术实现分析、数据库设计和代码实现等各个环节。您将了解如何高效、规范地实现这一功能

嗨嗨嗨 全栈老司机 程序员林中酒(公众号同名) 来啦

业务分析

需求分析

要记录用户调用后端服务的每一次系统日志

技术实现分析

用Aop实现每次调用接口时记录相关信息

数据库设计

create table ***.s_api_log
(
    id          int auto_increment comment 'ID'
        primary key,
    ip          varchar(255)     null comment 'IP地址',
    uri         varchar(255)     null comment '请求地址',
    user_name   varchar(255)     null comment '用户名称',
    name        varchar(50)      null comment '操作名称',
    method      varchar(255)     null comment '请求方法',
    params      varchar(255)     null comment '请求参数',
    result      varchar(255)     null comment '返回结果',
    time        bigint           null comment '响应时间',
    ct          varchar(255)     null comment '创建时间',
    type        varchar(50)      null comment '操作类型',
    description varchar(255)     null comment '操作描述',
    del_flge    bit default b'0' not null comment '删除标记 0:未删除 1:已删除'
)
    comment '接口日志表' collate = utf8mb4_bin
                         row_format = DYNAMIC;

代码

1. 所需依赖

<!--      AOP切面编程-->  
<dependency>  
    <groupId>org.springframework.boot</groupId>  
    <artifactId>spring-boot-starter-aop</artifactId>  
</dependency>  
<!-- END     AOP切面编程-->

<!-- hutool工具包 -->  
<dependency>  
    <groupId>cn.hutool</groupId>  
    <artifactId>hutool-all</artifactId>  
    <version>5.8.3</version>  
</dependency>  
<!--END hutool工具包 -->

<!-- mybatis-plus -->  
<dependency>  
    <groupId>com.baomidou</groupId>  
    <artifactId>mybatis-plus-boot-starter</artifactId>  
    <version>3.4.1</version>  
</dependency>

2. 数据库实体类-ApiLog

package com.linzhongjiu.common.web.system.entity;  

import com.baomidou.mybatisplus.annotation.IdType;  
import com.baomidou.mybatisplus.annotation.TableId;  
import java.io.Serializable;  

import com.baomidou.mybatisplus.annotation.TableName;  
import lombok.Data;  
import lombok.EqualsAndHashCode;  

/**  
 * <p>  
 * 操作日志表  
 * </p>  
 * @since 2024-01-11  
 */@Data  
@EqualsAndHashCode(callSuper = false)  
@TableName("s_api_log")  
public class ApiLog implements Serializable {  

    private static final long serialVersionUID = 1L;  

    /**  
     * ID     */    @TableId(value = "id", type = IdType.AUTO)  
    private Integer id;  

    /**  
     * IP地址  
     */  
    private String ip;  

    /**  
     * 请求地址  
     */  
    private String uri;  

    /**  
     * 请求类型  
     */  
    private String type;  
    /**  
     * 请求名称  
     */  
    private String name;  
    /**  
     * 请求描述  
     */  
    private String description;  

    /**  
     * 用户名称  
     */  
    private String userName;  

    /**  
     * 请求方法  
     */  
    private String method;  

    /**  
     * 请求参数  
     */  
    private String params;  

    /**  
     * 返回结果  
     */  
    private String result;  

    /**  
     * 响应时间  
     */  
    private Long time;  

    /**  
     * 创建时间  
     */  
    private String ct;  

    /**  
     * 删除标记  
     * 0-未删除 1-已删除  
     */  
    private Boolean delFlag;  


}

3. Mapper 层-ApiLogMapper

package com.linzhongjiu.common.web.system.mapper;  

import com.linzhongjiu.common.web.system.entity.ApiLog;  
import com.baomidou.mybatisplus.core.mapper.BaseMapper;  

/**  
 * <p>  
 * 操作日志表 Mapper 接口  
 * </p>  
 *  
 * @since 2024-01-11  
 */public interface ApiLogMapper extends BaseMapper<ApiLog> {  

}

4. Service 层- IApiLogService

package com.linzhongjiu.common.web.system.service;  

import com.linzhongjiu.common.web.system.entity.ApiLog;  
import com.baomidou.mybatisplus.extension.service.IService;  

/**  
 * <p>  
 * 操作日志表 服务类  
 * </p>  
 *  
 * @author linzhongjiu  
 * @since 2024-01-11  
 */public interface IApiLogService extends IService<ApiLog> {  

}

5. 工具类-CommonUtil

public class CommonUtil {  

    /**  
     * 创建时间更新时间  
     *  
     * @return yyyy-MM-dd HH:mm:ss  
     */    
     public static String CtUt() {  
        return DateUtil.formatDateTime(DateUtil.date(System.currentTimeMillis()));  
    }
}

6. 定义注解-OperationLog

package com.linzhongjiu.common.aop.note;  


import java.lang.annotation.*;  


@Target(ElementType.METHOD) //注解放置的目标位置,METHOD是可注解在方法级别上  
@Retention(RetentionPolicy.RUNTIME) //注解在哪个阶段执行  
@Documented //生成文档  
public @interface OperationLog {  
    String type() default "OP";//操作类型 LN-登录日志  OP-操作日志  
    String name() default "";//操作名称  
    String description() default "";//操作描述  
}

7. 编写切面-OperationLogAspect

package com.linzhongjiu.common.aop.handle;  

import com.alibaba.fastjson.JSON;  
import com.google.gson.Gson;  
import com.linzhongjiu.common.aop.note.OperationLog;  
import com.linzhongjiu.common.utils.CommonUtil;  
import com.linzhongjiu.common.web.system.entity.ApiLog;  
import com.linzhongjiu.common.web.system.service.IApiLogService;  
import lombok.extern.slf4j.Slf4j;  
import org.aspectj.lang.JoinPoint;  
import org.aspectj.lang.ProceedingJoinPoint;  
import org.aspectj.lang.annotation.*;  

import org.springframework.core.annotation.Order;  
import org.springframework.stereotype.Component;  
import org.springframework.web.context.request.RequestContextHolder;  
import org.springframework.web.context.request.ServletRequestAttributes;  

import javax.annotation.Resource;  
import javax.servlet.http.HttpServletRequest;  
import java.util.Arrays;  

@Aspect//这个注解的作用是:将一个类定义为一个切面类  
@Component//这个注解的作用:把切面类加入到IOC容器中  
@Order(1)//这个注解的作用是:标记切面类的处理优先级,i值越小,优先级别越高.PS:可以注解类,也能注解到方法上  
@Slf4j  
public class OperationLogAspect {  

    @Resource  
    private IApiLogService apiLogService;  

    private Gson gson = new Gson();  

    //申明一个切点 里面是@annotation  
    @Pointcut("@annotation(operationLog)")  
    public  void annotationPointCut(OperationLog operationLog) {  

    }  
    @Around("annotationPointCut(operationLog)")  
    public void arounding(ProceedingJoinPoint joinPoint, OperationLog operationLog) {  
        ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();  
        HttpServletRequest request = requestAttributes.getRequest();  
        String path = request.getRequestURL() == null ? "" :request.getRequestURL().toString();  
        ApiLog apiLog = new ApiLog();  
        apiLog.setType(operationLog.type());  
        apiLog.setName(operationLog.name());  
        apiLog.setDescription(operationLog.description());  
        apiLog.setUri(path);  
        apiLog.setMethod(request.getMethod());  
        apiLog.setParams(gson.toJson(request.getParameterMap()));  
        apiLog.setIp(request.getRemoteAddr());  
        apiLog.setUserName(request.getRemoteUser());  
        apiLog.setCt(CommonUtil.CtUt());  

        Object result = null;  
        long beginTime = System.currentTimeMillis();  
        try {  
            // 执行方法  
            result = joinPoint.proceed();  
        } catch (Throwable e) {  
            e.printStackTrace();  
        }  
        // 执行时长(毫秒)  
        long time = System.currentTimeMillis() - beginTime;  
        apiLog.setTime(time);  
        apiLog.setResult(JSON.toJSONString(result));  
        apiLogService.save(apiLog);  
    }  

}

知识点

AOP

  1. @Aspect: 用于定义一个切面,类似于 Java 中的类定义。

  2. @Pointcut: 用于定义一个切入点,表示在哪些连接点上应用切面的通知。

  3. @Before: 在目标方法执行前执行的通知。

  4. @After: 在目标方法执行后(无论正常返回还是异常返回)执行的通知。

  5. @AfterReturning: 在目标方法正常返回后执行的通知。

  6. @AfterThrowing: 在目标方法抛出异常后执行的通知。

  7. @Around: 环绕通知,包围目标方法执行。

相关实践学习
【涂鸦即艺术】基于云应用开发平台CAP部署AI实时生图绘板
【涂鸦即艺术】基于云应用开发平台CAP部署AI实时生图绘板
相关文章
WGLOG日志管理系统是怎么收集日志的
WGLOG通过部署Agent客户端采集日志,Agent持续收集指定日志文件并上报Server,Server负责展示与分析。Agent与Server需保持相同版本。官网下载地址:www.wgstart.com
|
3月前
|
Prometheus 监控 Cloud Native
基于docker搭建监控系统&日志收集
Prometheus 是一款由 SoundCloud 开发的开源监控报警系统及时序数据库(TSDB),支持多维数据模型和灵活查询语言,适用于大规模集群监控。它通过 HTTP 拉取数据,支持服务发现、多种图表展示(如 Grafana),并可结合 Loki 实现日志聚合。本文介绍其架构、部署及与 Docker 集成的监控方案。
406 122
基于docker搭建监控系统&日志收集
|
6月前
|
监控 API 开发工具
HarmonyOS Next的HiLog日志系统完全指南:从入门到精通
本文深入解析HarmonyOS Next的HiLog日志系统,涵盖日志级别、核心API、隐私保护与高级回调功能,助你从入门到精通掌握这一重要开发工具。
405 1
|
3月前
|
Ubuntu
在Ubuntu系统上设置syslog日志轮替与大小限制
请注意,在修改任何系统级别配置之前,请务必备份相应得原始档案并理解每项变更可能带来得影响。
350 2
|
5月前
|
存储
WGLOG日志管理系统可以采集网络设备的日志吗
WGLOG日志审计系统提供开放接口,支持外部获取日志内容后发送至该接口,实现日志的存储与分析。详情请访问:https://www.wgstart.com/wglog/docs9.html
|
10月前
|
存储 前端开发 数据可视化
Grafana Loki,轻量级日志系统
本文介绍了基于Grafana、Loki和Alloy构建的轻量级日志系统。Loki是一个由Grafana Labs开发的日志聚合系统,具备高可用性和多租户支持,专注于日志而非指标,通过标签索引而非内容索引实现高效存储。Alloy则是用于收集和转发日志至Loki的强大工具。文章详细描述了系统的架构、组件及其工作流程,并提供了快速搭建指南,包括准备步骤、部署命令及验证方法。此外,还展示了如何使用Grafana查看日志,以及一些基本的LogQL查询示例。最后,作者探讨了Loki架构的独特之处,提出了“巨型单体模块化”的概念,即一个应用既可单体部署也可分布式部署,整体协同实现全部功能。
3809 70
Grafana Loki,轻量级日志系统
|
9月前
|
存储 消息中间件 缓存
MiniMax GenAI 可观测性分析 :基于阿里云 SelectDB 构建 PB 级别日志系统
基于阿里云SelectDB,MiniMax构建了覆盖国内及海外业务的日志可观测中台,总体数据规模超过数PB,日均新增日志写入量达数百TB。系统在P95分位查询场景下的响应时间小于3秒,峰值时刻实现了超过10GB/s的读写吞吐。通过存算分离、高压缩比算法和单副本热缓存等技术手段,MiniMax在优化性能的同时显著降低了建设成本,计算资源用量降低40%,热数据存储用量降低50%,为未来业务的高速发展和技术演进奠定了坚实基础。
394 1
MiniMax GenAI 可观测性分析 :基于阿里云 SelectDB 构建 PB 级别日志系统
|
9月前
|
存储 JSON Go
PHP 日志系统的最佳搭档:一个 Go 写的远程日志收集服务
为了不再 SSH 上去翻日志,我写了个 Go 小脚本,用来接收远程日志。PHP 负责记录日志,Go 负责存储和展示,按天存储、支持 API 访问、可远程管理,终于能第一时间知道项目炸了。
199 10
|
存储 监控 安全
5款 Syslog集中系统日志常用工具对比推荐
集中管理Syslog有助于持续监控网络中的恶意活动,确保日志的搜索和分析更为便捷。常用工具包括Rsyslog、Syslog-ng、Logstash和Fluentd,它们各有优劣。Rsyslog通过多种协议确保日志传输的安全性;Syslog-ng支持高效收集和转发日志;Logstash能解析多源日志并索引;Fluentd将日志转换为JSON格式。卓豪EventLog Analyzer则提供一体化的日志管理,支持日志分析、报表生成、用户行为分析及实时告警,是全面的日志管理解决方案。
187 0
|
11月前
|
存储 安全 Java
Spring Boot 3 集成Spring AOP实现系统日志记录
本文介绍了如何在Spring Boot 3中集成Spring AOP实现系统日志记录功能。通过定义`SysLog`注解和配置相应的AOP切面,可以在方法执行前后自动记录日志信息,包括操作的开始时间、结束时间、请求参数、返回结果、异常信息等,并将这些信息保存到数据库中。此外,还使用了`ThreadLocal`变量来存储每个线程独立的日志数据,确保线程安全。文中还展示了项目实战中的部分代码片段,以及基于Spring Boot 3 + Vue 3构建的快速开发框架的简介与内置功能列表。此框架结合了当前主流技术栈,提供了用户管理、权限控制、接口文档自动生成等多项实用特性。
845 8

热门文章

最新文章