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

本文涉及的产品
云数据库 RDS MySQL,集群版 2核4GB 100GB
推荐场景:
搭建个人博客
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
RDS MySQL Serverless 高可用系列,价值2615元额度,1个月
简介: 🍅程序员小王的博客:程序员小王的博客🍅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天前
|
SQL 监控 Java
在IDEA 、springboot中使用切面aop实现日志信息的记录到数据库
这篇文章介绍了如何在IDEA和Spring Boot中使用AOP技术实现日志信息的记录到数据库的详细步骤和代码示例。
在IDEA 、springboot中使用切面aop实现日志信息的记录到数据库
|
4天前
|
XML Java 测试技术
Spring5入门到实战------17、Spring5新功能 --Nullable注解和函数式注册对象。整合JUnit5单元测试框架
这篇文章介绍了Spring5框架的三个新特性:支持@Nullable注解以明确方法返回、参数和属性值可以为空;引入函数式风格的GenericApplicationContext进行对象注册和管理;以及如何整合JUnit5进行单元测试,同时讨论了JUnit4与JUnit5的整合方法,并提出了关于配置文件加载的疑问。
Spring5入门到实战------17、Spring5新功能 --Nullable注解和函数式注册对象。整合JUnit5单元测试框架
|
3天前
|
Java 数据安全/隐私保护 Spring
揭秘Spring Boot自定义注解的魔法:三个实用场景让你的代码更加优雅高效
揭秘Spring Boot自定义注解的魔法:三个实用场景让你的代码更加优雅高效
|
5天前
|
存储 Ubuntu Apache
如何在 Ubuntu VPS 上配置 Apache 的日志记录和日志轮转
如何在 Ubuntu VPS 上配置 Apache 的日志记录和日志轮转
16 6
|
5天前
|
存储 Ubuntu 应用服务中间件
如何在 Ubuntu VPS 上配置 Nginx 的日志记录和日志轮转
如何在 Ubuntu VPS 上配置 Nginx 的日志记录和日志轮转
11 4
|
4天前
|
XML Java 数据库
Spring5入门到实战------15、事务操作---概念--场景---声明式事务管理---事务参数--注解方式---xml方式
这篇文章是Spring5框架的实战教程,详细介绍了事务的概念、ACID特性、事务操作的场景,并通过实际的银行转账示例,演示了Spring框架中声明式事务管理的实现,包括使用注解和XML配置两种方式,以及如何配置事务参数来控制事务的行为。
Spring5入门到实战------15、事务操作---概念--场景---声明式事务管理---事务参数--注解方式---xml方式
|
4天前
|
XML 数据库 数据格式
Spring5入门到实战------14、完全注解开发形式 ----JdbcTemplate操作数据库(增删改查、批量增删改)。具体代码+讲解 【终结篇】
这篇文章是Spring5框架的实战教程的终结篇,介绍了如何使用注解而非XML配置文件来实现JdbcTemplate的数据库操作,包括增删改查和批量操作,通过创建配置类来注入数据库连接池和JdbcTemplate对象,并展示了完全注解开发形式的项目结构和代码实现。
Spring5入门到实战------14、完全注解开发形式 ----JdbcTemplate操作数据库(增删改查、批量增删改)。具体代码+讲解 【终结篇】
|
4天前
|
XML Java 数据格式
Spring5入门到实战------8、IOC容器-Bean管理注解方式
这篇文章详细介绍了Spring5框架中使用注解进行Bean管理的方法,包括创建Bean的注解、自动装配和属性注入的注解,以及如何用配置类替代XML配置文件实现完全注解开发。
Spring5入门到实战------8、IOC容器-Bean管理注解方式
|
5天前
|
XML JSON Java
使用IDEA+Maven搭建整合一个Struts2+Spring4+Hibernate4项目,混合使用传统Xml与@注解,返回JSP视图或JSON数据,快来给你的SSH老项目翻新一下吧
本文介绍了如何使用IntelliJ IDEA和Maven搭建一个整合了Struts2、Spring4、Hibernate4的J2EE项目,并配置了项目目录结构、web.xml、welcome.jsp以及多个JSP页面,用于刷新和学习传统的SSH框架。
14 0
使用IDEA+Maven搭建整合一个Struts2+Spring4+Hibernate4项目,混合使用传统Xml与@注解,返回JSP视图或JSON数据,快来给你的SSH老项目翻新一下吧
|
5天前
|
XML Java Maven
logback在springBoot项目中的使用 springboot中使用日志进行持久化保存日志信息
这篇文章详细介绍了如何在Spring Boot项目中使用logback进行日志记录,包括Maven依赖配置、logback配置文件的编写,以及实现的日志持久化和控制台输出效果。
logback在springBoot项目中的使用 springboot中使用日志进行持久化保存日志信息

热门文章

最新文章