SpringBoot使用在控制层切面注解配置的方式将日志存储在mysql
创始人
2024-03-31 05:56:47
0次

🍅程序员小王的博客:程序员小王的博客
🍅CSDN地址:程序员小王java
🍅 欢迎点赞 👍 收藏 ⭐留言 📝
🍅 如有编辑错误联系作者,如果有比较好的文章欢迎分享给我,我会取其精华去其糟粕
🍅java自学的学习路线:java自学的学习路线

一、前言

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

二、实现详细源码

1、相关依赖

  • springboot项目的依赖需要,还需要一个aop切面的依赖,mybatis的依赖
    org.springframework.bootspring-boot-starter-parent2.2.5.RELEASE org.springframework.bootspring-boot-starter-weborg.springframework.bootspring-boot-starter-aop     

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;

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;  //我用的UUITprivate 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层



insert into syslog(id, username, operation, method, createDate)values (#{id}, #{username}, #{operation}, #{method}, #{createDate})

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 {@Autowiredpublic SysLogMapper sysLogMapper;//写入日志@Overridepublic 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 {@Autowiredprivate SysLogService sysLogService;//将数据写入数据库的操作@Autowiredprivate UserDao userDao;@Autowiredprivate 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);//保存获取的操作}//设置idString 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 请求头中取出 tokenString token = request.getHeader("authorization");// 解析token并获取token中的用户信息Map 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 {@Autowiredprivate EnumService enumService;@Mylog(value = "获取枚举")@GetMapping("/selectAll")public Result selectAll() {return enumService.selectAll();}
}

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

相关内容

热门资讯

前端-session、jwt 目录:   (1)session (2&#x...
linux入门---制作进度条 了解缓冲区 我们首先来看看下面的操作: 我们首先创建了一个文件并在这个文件里面添加了...
关于测试,我发现了哪些新大陆 关于测试 平常也只是听说过一些关于测试的术语,但并没有使用过测试工具。偶然看到编程老师...
前缀和与对数器与二分法 1. 前缀和 假设有一个数组,我们想大量频繁的去访问L到R这个区间的和,...
nodejs:本地安装nvm实... 一、背景-使用不同版本node的原因 vue3+ts、nuxt3版本,node...
JAVA集合知识整理 Java集合知识整理 HashMap相关 HashMap的底层数据结构:jdk1.8之...
无刷直流电机介绍及单片机控制实... 无刷直流电机介绍及单片机控制实例前言基本概念优势与劣势使用寿命基本结构使用单片机控制实例电子调速器&...
fwdiary(2) dp2 1.传纸条  AcWing 275. 传纸条 - AcWing 走两条路,走一条最大的...
常用的DOS命令 常用的DOS命令 DOS(Disk Operating System,磁...
<C++> 类和对象(下) 1.const成员函数将const修饰的“成员函数”称之为const成员函数,cons...