springboot编写日志环境搭建过程

news2024/11/18 1:43:37

AOP记录日志

AOP记录日志的主要优点包括:

1、低侵入性:AOP记录日志不需要修改原有的业务逻辑代码,只需要新增一个切面即可。

2、统一管理:通过AOP记录日志可以将各个模块中需要记录日志的部分进行统一管理,降低了代码重复度,提高了代码可维护性和可扩展性。

3、提升效率:通过引入AOP记录日志,可以避免手动编写日志记录代码,减少了开发人员的工作量,提升了开发效率。

4、安全性:通过AOP记录日志,可以收集系统的操作日志,帮助管理员及时发现问题并进行调整,从而提高系统的安全性。

AOP记录日志的整体思想

1、基于自定义注解来确定切入点【优势:可以通过自定义注解携带一些变化的参数,比如模块名称】

2、基于环绕通知来完成日志记录

搭建之前,要明白AOP主要核心术语

下面:

切面类环境搭建

1.在common模块下创建一个独立的记录日志的模块【common-log】

在该模块下加入如下的依赖

2.自定义Log注解,如下所示:

代码如下:

import com.atguigu.spzx.common.log.enums.OperatorType;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * // 自定义操作日志记录注解
 */
@SuppressWarnings("all")
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface Log {
    // 模块名称
    public String title() ;
    // 操作人类别
    public OperatorType operatorType() default OperatorType.MANAGE;
    // 业务类型(0其它 1新增 2修改 3删除)
    public int businessType() ;
    //是否保存请求的参数
    public boolean isSaveRequestData() default true;

    // 是否保存响应的参数
    public boolean isSaveResponseData() default true;
}

//操作人类别

OperatorType定义

public enum OperatorType {        // 操作人类别
    OTHER,        // 其他
    MANAGE,        // 后台用户
    MOBILE        // 手机端用户
}

3.定义一个切面类,并且在该切面类中提供一个环绕通知方法

LogAspect

/**
 * 这个方法作为环绕通知,环绕通知方法中两个参数,ProceedingJoinPoint和Log
 * 1.ProceedingJoinPoint 表示能调用我们业务方法并且可以得到相关的参数等信息
 * 2.Log 方法上加了public @interface Log这个注解,
 * 加上@Around(value = "@annotation(sysLog)"),方法执行时就会执行环绕通知,就可以完成机制
 * 实现当方法上加上注解之后,就会实行环绕通知
 */

@Aspect
@Component
@Slf4j// 环绕通知切面类定义
public class LogAspect {            

    @Around(value = "@annotation(sysLog)")
    public Object doAroundAdvice(ProceedingJoinPoint joinPoint , Log sysLog) {
    
        Object proceed = null;
        try {

                  // 执行业务方法
            proceed = joinPoint.proceed();            
        } catch (Throwable e) {          

                // 代码执行进入到catch中,业务方法执行产生异常              
            throw new RuntimeException(e);
        }

          // 返回执行结果
        return proceed ;                              
    }
}

4.想让LogAspect这个切面类在其他的业务服务中进行使用,那么就需要该切面类纳入到Spring容器中。Spring Boot默认会扫描和启动类所在包相同包中的bean以及子包中的bean。而LogAspect切面类不满足扫描条件,因此无法直接在业务服务中进行使用。那么此时可以通过自定义注解进行实现

代码如下:

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Import(value = LogAspect.class)      

 // 通过Import注解导入日志切面类到Spring容器中    
public @interface EnableLogAspect {
    
}

5.在启动类pom.xml 引入依赖

<dependency>
    <groupId>org.liuliu</groupId>
    <artifactId>common-log</artifactId>
    <version>1.0-SNAPSHOT</version>
</dependency>

6.在ManagerApplication服务的启动类上添加@EnableLogAspect注解

7.创建Log工具类,代码如下

/**
 * 自定义注解搞完,切面环绕方法类方法创建完成,在manager引入common包依赖,在启动类添加注解@EnableLogAspect
 * 然后封装一个logutil工具类备用(切面环绕方法类执行时调用工具类)
 */
import com.alibaba.fastjson.JSON;
import com.atguigu.spzx.common.log.annotation.Log;
import com.atguigu.spzx.model.entity.system.SysOperLog;
import com.atguigu.spzx.utils.AuthContextUtil;
import jakarta.servlet.http.HttpServletRequest;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.http.HttpMethod;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import java.lang.reflect.Method;
import java.util.Arrays;
public class LogUtil {

    //操作执行之后调用
    public static void afterHandlLog(Log sysLog, Object proceed,
                                     SysOperLog sysOperLog, int status ,
                                     String errorMsg) {
        if(sysLog.isSaveResponseData()) {
            sysOperLog.setJsonResult(JSON.toJSONString(proceed));
        }
        sysOperLog.setStatus(status);
        sysOperLog.setErrorMsg(errorMsg);
    }

    //操作执行之前调用
    public static void beforeHandleLog(Log sysLog,
                                       ProceedingJoinPoint joinPoint,
                                       SysOperLog sysOperLog) {

        // 设置操作模块名称
        sysOperLog.setTitle(sysLog.title());
        sysOperLog.setOperatorType(sysLog.operatorType().name());

        // 获取目标方法信息
        MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature() ;
        Method method = methodSignature.getMethod();
        sysOperLog.setMethod(method.getDeclaringClass().getName());

        // 获取请求相关参数
        ServletRequestAttributes requestAttributes = (ServletRequestAttributes)
                RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = requestAttributes.getRequest();
        sysOperLog.setRequestMethod(request.getMethod());
        sysOperLog.setOperUrl(request.getRequestURI());
        sysOperLog.setOperIp(request.getRemoteAddr());

        // 设置请求参数
        if(sysLog.isSaveRequestData()) {
            String requestMethod = sysOperLog.getRequestMethod();
            if (HttpMethod.PUT.name().equals(requestMethod) || HttpMethod.POST.name().equals(requestMethod)) {
                String params = Arrays.toString(joinPoint.getArgs());
                sysOperLog.setOperParam(params);
            }
        }
        sysOperLog.setOperName(AuthContextUtil.get().getUserName());
    }
}

8.在common-log模块中定义保存日志数据的service接口,然后在具体的业务服务中给出实现。分析图如下:

1)common-log 模块下创建service包

上代码:

import com.atguigu.spzx.model.entity.system.SysOperLog;

/**
 * // 异步操作日志记录服务接口
 */
public interface AsyncOperLogService {
  
}

2)启动类项目中的serviceImpl包中实现日志记录服务接口,创建Mapper和mapper.xml

(创建过程自动脑补,继续实现项目),都创建完成,接下来去保存日志操作:

        2.1)修改切面类,调用封装工具

        

import com.atguigu.spzx.common.log.annotation.Log;
import com.atguigu.spzx.common.log.service.AsyncOperLogService;
import com.atguigu.spzx.common.log.utils.LogUtil;
import com.atguigu.spzx.model.entity.system.SysOperLog;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

/**
 * 定义一个切面类,并且在该切面类中提供一个环绕通知方法
 * // 环绕通知切面类定义
 */

@Aspect
@Component
@Slf4j

public class LogAspect {
    /**    
     * 封装工具类Logutil 后,日志切面类代码修改 调用工具类实现环绕方法,标红代码,首先引入        AsyncOperLogService
     */

    @Autowired
    private AsyncOperLogService asyncOperLogService ;

    @Around(value = "@annotation(sysLog)")
    public Object doAroundAdvice(ProceedingJoinPoint joinPoint, Log sysLog){


        // 构建前置参数
        SysOperLog sysOperLog = new SysOperLog() ;

        LogUtil.beforeHandleLog(sysLog , joinPoint , sysOperLog) ;

        Object proceed=null;
        try {
            // 执行业务方法
            proceed = joinPoint.proceed();
                // 构建响应结果参数
            LogUtil.afterHandlLog(sysLog , proceed, sysOperLog,0,null);

        } catch (Throwable e) {
            e.printStackTrace();
            LogUtil.afterHandlLog(sysLog , proceed, sysOperLog,1, e.getMessage());
            // 代码执行进入到catch中,业务方法执行产生异常
            throw new RuntimeException();
        }

        // 保存日志数据
        asyncOperLogService.saveSysOperLog(sysOperLog);

        // 返回执行结果
        return proceed;
    }
}

        2.2)执行上述切面类保存日志方法:

// 保存日志数据 asyncOperLogService.saveSysOperLog(sysOperLog);

//service接口

import com.atguigu.spzx.model.entity.system.SysOperLog;

/**
 * // 异步操作日志记录服务接口
 */
public interface AsyncOperLogService {
     保存日志数据
    public abstract void saveSysOperLog(SysOperLog sysOperLog) ;
}

//service实现类

import com.atguigu.spzx.common.log.service.AsyncOperLogService;
import com.atguigu.spzx.manager.mapper.SysOperLogMapper;
import com.atguigu.spzx.model.entity.system.SysOperLog;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;


@Service
public class AsyncOperLogServiceImpl implements AsyncOperLogService {
    @Autowired
    private SysOperLogMapper sysOperLogMapper;
    @Override
    public void saveSysOperLog(SysOperLog sysOperLog) {

        // 异步执行保存日志操作
        sysOperLogMapper.insert(sysOperLog);

    }
}

//mapper接口

import com.atguigu.spzx.model.entity.system.SysOperLog;
import org.apache.ibatis.annotations.Mapper;

@Mapper
public interface SysOperLogMapper {

    //保存日志操作
    void insert(SysOperLog sysOperLog);
}

//mapper.xml

<?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.atguigu.spzx.manager.mapper.SysOperLogMapper">

    <sql id="columns">
        id,title,method,request_method,operator_type,oper_name,oper_url,oper_ip,oper_param,json_result
        ,status,error_msg,create_time,update_time,is_deleted
    </sql>
    <insert id="insert">
        insert into sys_oper_log (
            id,
            title,
            method,
            request_method,
            operator_type,
            oper_name,
            oper_url,
            oper_ip,
            oper_param,
            json_result,
            status,
            error_msg
        ) values (
                     #{id},
                     #{title},
                     #{method},
                     #{requestMethod},
                     #{operatorType},
                     #{operName},
                     #{operUrl},
                     #{operIp},
                     #{operParam},
                     #{jsonResult},
                     #{status},
                     #{errorMsg}
                 )
    </insert>
</mapper>

        2.3)一切准备就绪,在需要添加操作日志的接口方法上添加@Log注解进行测试。(添加红色表示框内容),启动器启动

//查询列表
@Log(title = "品牌管理",businessType = 0,operatorType = OperatorType.OTHER)
@GetMapping("/{page}/{limit}")
public Result<PageInfo<Brand>> list(@PathVariable(value = "page") Integer page, @PathVariable(value = "limit") Integer limit){
    PageInfo<Brand> brandList=brandService.findByPage(page, limit);
    return Result.build(brandList, ResultCodeEnum.SUCCESS);
}

结果:

创作不易,谢谢大家

补充:附上日志数据表结构,方便理解

CREATE TABLE `sys_oper_log` (
  `id` bigint NOT NULL AUTO_INCREMENT COMMENT '日志主键',
  `title` varchar(50) DEFAULT '' COMMENT '模块标题',
  `business_type` varchar(20) DEFAULT '0' COMMENT '业务类型(0其它 1新增 2修改 3删除)',
  `method` varchar(100) DEFAULT '' COMMENT '方法名称',
  `request_method` varchar(10) DEFAULT '' COMMENT '请求方式',
  `operator_type` varchar(20) DEFAULT '0' COMMENT '操作类别(0其它 1后台用户 2手机端用户)',
  `oper_name` varchar(50) DEFAULT '' COMMENT '操作人员',
  `dept_name` varchar(50) DEFAULT '' COMMENT '部门名称',
  `oper_url` varchar(255) DEFAULT '' COMMENT '请求URL',
  `oper_ip` varchar(128) DEFAULT '' COMMENT '主机地址',
  `oper_param` varchar(2000) DEFAULT '' COMMENT '请求参数',
  `json_result` varchar(2000) DEFAULT '' COMMENT '返回参数',
  `status` int DEFAULT '0' COMMENT '操作状态(0正常 1异常)',
  `error_msg` varchar(2000) DEFAULT '' COMMENT '错误消息',
  `oper_time` datetime DEFAULT NULL COMMENT '操作时间',
  `create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  `update_time` timestamp NULL DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP,
  `is_deleted` tinyint NOT NULL DEFAULT '0' COMMENT '删除标记(0:不可用 1:可用)',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=67 DEFAULT CHARSET=utf8mb3 COMMENT='操作日志记录';

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1721283.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Linux 深入讲解自动化构建工具

各位大佬好 &#xff0c;这里是阿川的博客 &#xff0c; 祝您变得更强 个人主页&#xff1a;在线OJ的阿川 大佬的支持和鼓励&#xff0c;将是我成长路上最大的动力 阿川水平有限&#xff0c;如有错误&#xff0c;欢迎大佬指正 Linux一系列的文章&#xff08;质量分均在93分…

水滴式粉碎机:多功能饲料粉碎设备

饲料粉碎机是一种专门用于将各种饲料原料进行粉碎处理的机械设备。无论是玉米、小麦等谷物&#xff0c;还是豆粕、鱼粉等动物性原料&#xff0c;甚至是一些粗纤维含量较高的秸秆、牧草等&#xff0c;都可以经过饲料粉碎机的处理&#xff0c;变成适合畜禽消化吸收的精细饲料。这…

solr-8.11.3

https://solr.apache.org/downloads.html https://archive.apache.org/dist/solr/solr/ F:\Document_Solr.apache.org\solr-8.11.3\bin Microsoft Windows [版本 10.0.19045.2965] (c) Microsoft Corporation。保留所有权利。 C:\Users\Administrator>F: F:\> F:\>…

AI播客下载:a16z (主题为AI、web3、生物技术等风险投资)

a16z播客是一个综合性的科技和创新领域的媒体平台&#xff0c;通过多种节目形式和丰富的内容&#xff0c;为广大听众提供了一个了解最新科技趋势和创新思维的窗口。a16z播客是由安德里森霍罗威茨&#xff08;Andreessen Horowitz&#xff0c;简称a16z&#xff09;推出的一个科技…

计算机毕业设计hadoop+spark知识图谱课程推荐系统 课程预测系统 课程大数据 课程数据分析 课程大屏 mooc慕课推荐系统 大数据毕业设计

本科毕业设计&#xff08;论文&#xff09; 题目&#xff1a;基于 Hadoop和Spark的课程推荐系统的设计与实现 烟台南山学院教务处 二〇二四年六月 院 系&#xff1a;科技与数据学院数据科学与软件工程系 专 业&#xff1a;数据科学与大数据技术 班 级&#xff1a;数…

11Linux学习笔记

Linux 实操篇 目录 文章目录 Linux 实操篇1.rtm包&#xff08;软件&#xff09;1.1 基本命令1.2 基本格式1.3安装rtm包1.4卸载rtm包 2.apt包2.1 基本命令结构2.2 常用选项2.3常用命令 1.rtm包&#xff08;软件&#xff09; 1.1 基本命令 1.2 基本格式 1.3安装rtm包 1.4卸载r…

Golang | Leetcode Golang题解之第123题买卖股票的最佳时机III

题目&#xff1a; 题解&#xff1a; func maxProfit(prices []int) int {buy1, sell1 : -prices[0], 0buy2, sell2 : -prices[0], 0for i : 1; i < len(prices); i {buy1 max(buy1, -prices[i])sell1 max(sell1, buy1prices[i])buy2 max(buy2, sell1-prices[i])sell2 m…

如何让数据标注

1.用Anacoda创建一个新的虚拟环境 2.进入虚拟环境 conda activate stu_data&#xff08;就是刚才创建的虚拟变量的名称&#xff09; 3.在此环境中安装labelimg pip install labelimg 4.进入labelimg 直接输入 labelimg 快捷键&#xff1a;D&#xff1a;下一个图片 A&#xff1a…

深度学习设计模式之装饰器模式

文章目录 前言一、介绍二、详细分析1.核心组成2.实现步骤3.代码示例4.优缺点优点缺点 5.使用场景 总结 前言 装饰器模式属于结构型模式&#xff0c;又叫包装设计模式&#xff0c;动态的将责任添加到对象上。 一、介绍 装饰器模式又叫包装设计模式&#xff0c;为现有的类的一个…

四川音盛佳云电子商务有限公司引领抖音电商新风潮

在数字化浪潮席卷全球的今天&#xff0c;电商行业已成为推动经济发展的重要力量。作为这一领域的佼佼者&#xff0c;四川音盛佳云电子商务有限公司凭借其在抖音电商服务领域的专业实力和独特视角&#xff0c;正引领着行业的新风潮&#xff0c;助力品牌实现快速增长和腾飞。 四…

淘宝镜像的https证书过期

错误原因&#xff1a; 淘宝镜像过期 早在 2021 年&#xff0c;淘宝就发文称&#xff0c;npm 淘宝镜像已经从 http://registry.npm.taobao.org 切换到了 http://registry.npmmirror.com。旧域名也将于 2022 年 5 月 31 日停止服务&#xff08;直到 HTTPS 证书到期才真正不能用了…

用例与系统顺序图

习题 问题 考察点 1.Use Cases 用例绘制 列出8个Use Cases, 按优先权分成三个档次, 并分别用Fully dressed、Causual和Brief方式描述 建议:用Fully dressed方式描述的Use Cases应该是项目比较核心,而且需要尽快研制的功能模块;该功能模块的内容比较充实;不要采用如登陆验…

【百度之星比赛】

新材料 直接模拟&#xff1a;因为要考虑上次出现的位置&#xff0c;所以使用map映射最好&#xff0c;如果没有出现过就建立新映射&#xff0c;如果出现过但是已经反应过就跳过&#xff0c;如果出现过但是不足以反应&#xff0c;就建立新映射&#xff0c;如果能反应就反应&#…

攻防实战 | 邮件高级威胁检测与自动化响应

历经三个月的时间&#xff0c;年度重磅直播节目Fortinet 2024年度“Demo季”近日终于迎来了备受瞩目的压轴大戏——Demo Day第三期&#xff0c;主题为《新邮件安全下的高级威胁检测与自动化响应》。继成功举办了前两期《企业网络中的多源威胁情报自动化整合与集成》和《应急响应…

20.Redis之缓存

1.什么是缓存&#xff1f; Redis 最主要的用途,三个方面:1.存储数据(内存数据库)2.缓存 【redis 最常用的场景】3.消息队列【很少见】 缓存 (cache) 是计算机中的⼀个经典的概念. 在很多场景中都会涉及到. 核⼼思路就是把⼀些常⽤的数据放到触⼿可及(访问速度更快)的地⽅, ⽅…

Windows 11 Beta 22635.3646 预览版发布:中国大陆地区新增“微软电脑管家”应用

微软今天面向 Beta 频道的 Windows Insider 项目成员&#xff0c;发布了适用于 Windows 11 的 KB5037858 更新&#xff0c;用户安装后版本号升至 Build 22635.3646&#xff0c;该版本主要为中国大陆设备新增“微软电脑管家”应用。 IT之家 5 月 24 日消息&#xff0c;微软今天…

从零自制docker-15-【实现 mydocker run -d 支持后台运行容器】

文章目录 实现目的莫名奇妙的问题对之前upper层出现root补充对run某些命令出现找不到文件或目录的原因代码效果 实现目的 docker run -d时容器在后台运行&#xff0c;而不会进入命令行交互形式 首先是需要添加-d选项然后设置当添加-d选项时候主进程不会等待子进程&#xff0c…

ollama入门系列教程简介与目录

教程简介 Ollama教程系列是为那些希望深入了解并掌握Ollama框架的开发者设计的。通过这一系列的教程,用户将学习如何从基础设置到高级功能的各个方面,有效地在Ollama平台上开发和部署大型语言模型。本系列包括如何将模型导入Ollama框架、利用与OpenAI兼容的API、以及如何使用…

关于ida如何进行远程linux调试(详解)

首先我们需要安装工具软件VMware虚拟机和finalshell&#xff0c;并在虚拟机中安装centos 7系统&#xff0c;还要将finalshell连接到该系统中&#xff0c;具体操作可以去b站搜黑马Linux学习&#xff0c;学完该课程的p5&#xff0c;p6&#xff0c;p8即可&#xff0c;我接下来讲的…