SpringBoot使用在控制层切面注解配置的方式将日志存储在mysql

本文涉及的产品
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
云数据库 RDS MySQL,高可用系列 2核4GB
简介: 🍅程序员小王的博客:程序员小王的博客🍅CSDN地址:程序员小王java🍅 欢迎点赞 👍 收藏 ⭐留言 📝🍅 如有编辑错误联系作者,如果有比较好的文章欢迎分享给我,我会取其精华去其糟粕🍅java自学的学习路线:java自学的学习路线

一、前言

我们写完一个项目,运维时,如果出现了bug,我们需要查看控制台的日志,但是那个日志无关方法太多,查找不是很方便,还有就是一个项目上线之后,我们需要记录谁操作了那些功能,以防出现矛盾知道是谁点了这个功能造成的问题,由谁来负责,为了解决这两个问题,我在SpringBoot项目中使用了对控制层切面+注解的方法来实现将日志存储在数据库里面


二、实现详细源码

1、相关依赖

springboot项目的依赖需要,还需要一个aop切面的依赖,mybatis的依赖

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.2.5.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
        <dependencies>
         <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
           <!-- aop -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-aop</artifactId>
        </dependency>     
       </dependencies>


2、配置文件

在application.properties文件里加这样一条配置

server.port: 8080
spring.aop.auto=true

3、我们首先需要准备mysql表

DROP TABLE IF EXISTS `syslog`;
CREATE TABLE `syslog`  (
  `id` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '主键',
  `username` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '用户名',
  `operation` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '操作',
  `method` varchar(250) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '方法名',
  `createDate` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '时间',
  PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '日志' ROW_FORMAT = Dynamic;
SET FOREIGN_KEY_CHECKS = 1;

SET FOREIGN_KEY_CHECKS = 1;



4、创建数据库表之后就需要写实体类了

package com.sgsg.verification.entity;
/**
 * @author 王恒杰
 * @date 2022/10/25 14:54
 * @Description:
 */
import java.io.Serializable;
public class Syslog implements Serializable {
    private String id;  //我用的UUIT
    private String username; //用户名
    private String operation; //操作
    private String method; //方法名
    private String createDate; //操作时间,这里可以使用Date来实现。我写的有个工具类。用的String接收
    public String getId() {
        return id;
    }
    public void setId(String id) {
        this.id = id;
    }
    public String getUsername() {
        return username;
    }
    public void setUsername(String username) {
        this.username = username;
    }
    public String getOperation() {
        return operation;
    }
    public void setOperation(String operation) {
        this.operation = operation;
    }
    public String getMethod() {
        return method;
    }
    public void setMethod(String method) {
        this.method = method;
    }
    public String getCreateDate() {
        return createDate;
    }
    public void setCreateDate(String createDate) {
        this.createDate = createDate;
    }
}

这里如果用lombok的话,只需要一个@Data注解

@Data
public class Syslog implements Serializable {
    private String id;  //我用的全宇宙唯一的子串串、也是直接用的工具类
    private String username; //用户名
    private String operation; //操作
    private String method; //方法名
    private String createDate; //操作时间,这里可以使用Date来实现。我写的有个工具类。用的String接收
}


5、先写dao层和mapper层

(1)dao层

/**
 * @author 王恒杰
 * @date 2022/10/25 14:59
 * @Description:
 */
@Mapper
public interface SysLogMapper {
    /**
     * 写入日志
     * @param syslog
     * @return
     */
    int addLog(Syslog syslog);
}


(2)mapper层

 

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.sgsg.verification.dao.SysLogMapper">
    <insert id="addLog" parameterType="com.sgsg.verification.entity.Syslog">
        insert into syslog(id, username, operation, method, createDate)
        values (#{id}, #{username}, #{operation}, #{method}, #{createDate})
    </insert>
</mapper>


6、写业务层

接口层

import com.sgsg.verification.entity.Syslog;
/**
 * @author 王恒杰
 * @date 2022/10/25 14:58
 * @Description:
 */
public interface SysLogService {
    //写入日志
    int addLog(Syslog syslog);
}


实现类

/**
 * @author 王恒杰
 * @date 2022/10/25 14:58
 * @Description:
 */
@Service
public class SysLogServiceImpl implements SysLogService {
    @Autowired
    public SysLogMapper sysLogMapper;
        //写入日志
        @Override
        public int addLog(Syslog syslog) {
            return sysLogMapper.addLog(syslog);
        }
}


7、切面核心方法

package com.sgsg.verification.aspect;
/**
 * @author 王恒杰
 * @date 2022/10/25 14:57
 * @Description:
 */
import com.auth0.jwt.interfaces.Claim;
import com.sgsg.verification.dao.UserDao;
import com.sgsg.verification.entity.Result;
import com.sgsg.verification.entity.Syslog;
import com.sgsg.verification.entity.UserInfoEntity;
import com.sgsg.verification.log.Mylog;
import com.sgsg.verification.service.SysLogService;
import com.sgsg.verification.service.UserService;
import com.sgsg.verification.utils.JwtUtil;
import com.sgsg.verification.utils.UserInfoUtils;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
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.Map;
import java.util.UUID;
/**
 * 系统日志:切面处理类
 */
@Aspect
@Component
public class SysLogAspect {
    @Autowired
    private SysLogService sysLogService;//将数据写入数据库的操作
    @Autowired
    private UserDao userDao;
    @Autowired
    private JwtUtil jwtUtil;
    //定义切点 @Pointcut
    //在注解的位置切入代码
    @Pointcut("@annotation(com.sgsg.verification.log.Mylog ))")
    public void logPoinCut() {
    }
    //切面 配置通知
    @AfterReturning("logPoinCut()")
    public void saveSysLog(JoinPoint joinPoint) {
        System.out.println("切面。。。。。");
        //保存日志
        Syslog sysLog = new Syslog();
        //从切面织入点处通过反射机制获取织入点处的方法
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        //获取切入点所在的方法
        Method method = signature.getMethod();
        //获取操作
        Mylog myLog = method.getAnnotation(Mylog.class);
        if (myLog != null) {
            String value = myLog.value();
            sysLog.setOperation(value);//保存获取的操作
        }
        //设置id
        String id = UUID.randomUUID().toString();
        sysLog.setId(id);
        //获取请求的类名
        String className = joinPoint.getTarget().getClass().getName();
        //获取请求的方法名
        String methodName = method.getName();
        sysLog.setMethod(className + "." + methodName);
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy年MM月dd日");
        sysLog.setCreateDate(simpleDateFormat.format(new Date()));
        //获取用户名
        //拿到当前用户的信息、我这里使用的Token。直接从Token中获取当前用户信息
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        assert attributes != null;
        HttpServletRequest request = attributes.getRequest();
        // 从 http 请求头中取出 token
        String token = request.getHeader("authorization");
        // 解析token并获取token中的用户信息
        Map<String, Claim> claims = jwtUtil.verity(token);
        Claim userId = claims.get("userId");
        //获取用户
        UserInfoEntity user = userDao.getInfoById(userId.asInt());
        sysLog.setUsername(user.getCname());
        //调用service保存SysLog实体类到数据库
        sysLogService.addLog(sysLog);
    }
}


8、我们自己定义注解类

package com.sgsg.verification.log;
/**
 * @author 王恒杰
 * @date 2022/10/25 14:56
 * @Description: 自定义注解类
 */
import java.lang.annotation.*;
@Target(ElementType.METHOD) //注解放置的目标位置,METHOD是可注解在方法级别上
@Retention(RetentionPolicy.RUNTIME) //注解在哪个阶段执行
@Documented //生成文档
public @interface  Mylog {
    String value() default "";
}

9、在控制层使用我们自定义的注解

package com.sgsg.verification.controller;
import com.sgsg.verification.entity.Result;
import com.sgsg.verification.log.Mylog;
import com.sgsg.verification.service.EnumService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
 * @author 王恒杰
 * @date 2022/10/6 12:30
 * @Description:
 */
@Slf4j
@RestController
@RequestMapping("/enums")
public class EnumController {
    @Autowired
    private EnumService enumService;
    @Mylog(value = "获取枚举")
    @GetMapping("/selectAll")
    public Result selectAll() {
        return enumService.selectAll();
    }
}




10、启动项目之后我们的日志就存储在数据库里面了


相关实践学习
日志服务之使用Nginx模式采集日志
本文介绍如何通过日志服务控制台创建Nginx模式的Logtail配置快速采集Nginx日志并进行多维度分析。
相关文章
|
6天前
|
Java 开发者 微服务
手写模拟Spring Boot自动配置功能
【11月更文挑战第19天】随着微服务架构的兴起,Spring Boot作为一种快速开发框架,因其简化了Spring应用的初始搭建和开发过程,受到了广大开发者的青睐。自动配置作为Spring Boot的核心特性之一,大大减少了手动配置的工作量,提高了开发效率。
23 0
|
30天前
|
SQL 关系型数据库 MySQL
mysql主从复制概述和配置
【10月更文挑战第22天】MySQL 主从复制是一种将主服务器的数据复制到一个或多个从服务器的技术,实现读写分离,提高系统性能和可用性。主服务器记录变更日志,从服务器通过 I/O 和 SQL 线程读取并应用这些变更。适用于读写分离、数据备份和恢复、数据分析等场景。配置步骤包括修改配置文件、创建复制用户、配置从服务器连接主服务器并启动复制进程。
|
30天前
|
Java API 数据库
Spring Boot框架因其简洁的配置、快速的启动特性及丰富的功能集而备受开发者青睐
本文通过在线图书管理系统案例,详细介绍如何使用Spring Boot构建RESTful API。从项目基础环境搭建、实体类与数据访问层定义,到业务逻辑实现和控制器编写,逐步展示了Spring Boot的简洁配置和强大功能。最后,通过Postman测试API,并介绍了如何添加安全性和异常处理,确保API的稳定性和安全性。
36 0
|
10天前
|
缓存 IDE Java
SpringBoot入门(7)- 配置热部署devtools工具
SpringBoot入门(7)- 配置热部署devtools工具
23 2
 SpringBoot入门(7)- 配置热部署devtools工具
|
9天前
|
Java 数据库连接
SpringBoot配置多数据源实战
第四届光学与机器视觉国际学术会议(ICOMV 2025) 2025 4th International Conference on Optics and Machine Vision
37 8
|
7天前
|
Java 数据库连接 数据库
springboot启动配置文件-bootstrap.yml常用基本配置
以上是一些常用的基本配置项,在实际应用中可能会根据需求有所变化。通过合理配置 `bootstrap.yml`文件,可以确保应用程序在启动阶段加载正确的配置,并顺利启动运行。
13 2
|
11天前
|
分布式计算 关系型数据库 MySQL
SpringBoot项目中mysql字段映射使用JSONObject和JSONArray类型
SpringBoot项目中mysql字段映射使用JSONObject和JSONArray类型 图像处理 光通信 分布式计算 算法语言 信息技术 计算机应用
34 8
|
12天前
|
SQL 前端开发 关系型数据库
SpringBoot使用mysql查询昨天、今天、过去一周、过去半年、过去一年数据
SpringBoot使用mysql查询昨天、今天、过去一周、过去半年、过去一年数据
44 9
|
18天前
|
Java Spring 容器
SpringBoot读取配置文件的6种方式,包括:通过Environment、@PropertySource、@ConfigurationProperties、@Value读取配置信息
SpringBoot读取配置文件的6种方式,包括:通过Environment、@PropertySource、@ConfigurationProperties、@Value读取配置信息
43 3
|
19天前
|
存储 SQL 关系型数据库
2024Mysql And Redis基础与进阶操作系列(1)作者——LJS[含MySQL的下载、安装、配置详解步骤及报错对应解决方法]
Mysql And Redis基础与进阶操作系列(1)之[MySQL的下载、安装、配置详解步骤及报错对应解决方法]

热门文章

最新文章