从零搭建若依(Ruoyi-Vue)管理系统(5)--整合日志实现

本章结束后对应的节选代码文件:Gangbb-Vue-05-Log
项目地址:https://github.com/Gang-bb/Gangbb-Vue

历史遗留TODO:

  • 第三章
  1. mybatis缓存暂时没用到,后面整合redis后用redis做缓存(整合Redis完成)。
  2. 重写mybatis配置文件扫描mapper(日志整合章节完成)
  3. 整合暂时没有用到druid数据源,后续会用到

本章将留下TODO:

  • 第四章
  1. 登录日志还未实现。(到登录和权限模块完成)
  2. LogAspect从缓存获取当前的用户信息使用模拟的数据(到登录和权限模块完成)

本章将解决TODO:

  • 第三章
  1. 重写mybatis配置文件扫描mapper(日志整合章节完成)

本章只是简单的对日志工具进行引入和配置

整体思路:SLF4j+log4j2+Aop(若依的日志实现使用的是logback)

具体详细选型介绍可以查看我的文章:SpringBoot系列-- SpringBoot整合SLF4j+log4j2+aop记录web请求

原来文章的切点是设置在监听controller目录下,即所有请求。按照若依的做法是创建一个自定义@Log注解,切点设为该注解,如此设计更加灵活和扩展,决定采用它的方案!

1. 添加依赖

1.1 Gangbb-Vue的pom.xml

<properties>
	<fastjson.version>1.2.74</fastjson.version>
</properties>
<!--统一项目整体依赖版本-->
<dependencyManagement>
    <dependencies>
        <!-- 阿里JSON解析器 begin-->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>${fastjson.version}</version>
        </dependency>
        <!-- 阿里JSON解析器 end-->
    </dependencies>
</dependencyManagement>

1.2 Gangbb-core的pom.xml

<dependencies>
    <!-- SpringBoot Web容器 begin-->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
        <!--以下是排除的组件-->
        <exclusions>
            <!--排除默认自带的log组件-->
            <exclusion>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-logging</artifactId>
            </exclusion>
        </exclusions>
    </dependency>
    <!-- SpringBoot Web容器 end-->

    <!-- SpringBoot 拦截器  begin-->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-aop</artifactId>
    </dependency>
    <!-- SpringBoot 拦截器  end-->

    <!--log4j2日志相关  begin-->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-log4j2</artifactId>
    </dependency>
    <!--log4j2日志相关  end-->
    
    <!--项目common通用工具类 begin-->
    <dependency>
        <groupId>com.gangbb</groupId>
        <artifactId>Gangbb-common</artifactId>
    </dependency>
    <!--项目common通用工具类 end-->
</dependencies>

1.2 Gangbb-common的pom.xml

<dependencies>
    <!-- SpringBoot yml配置文件编写智能提示  begin-->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-configuration-processor</artifactId>
        <optional>true</optional>
    </dependency>
    <!-- SpringBoot yml配置文件编写智能提示  end-->
    
    <!-- 阿里JSON解析器 begin-->
    <dependency>
        <groupId>com.alibaba</groupId>
        <artifactId>fastjson</artifactId>
    </dependency>
    <!-- 阿里JSON解析器 end-->
    
    <!--常用工具类 begin-->
    <dependency>
        <groupId>org.apache.commons</groupId>
        <artifactId>commons-lang3</artifactId>
    </dependency>
    <!--常用工具类 end-->
    
	<!-- servlet包 begin-->
    <dependency>
        <groupId>javax.servlet</groupId>
        <artifactId>javax.servlet-api</artifactId>
    </dependency>
    <!-- servlet包 end-->
    
	<!-- Spring框架基本的核心工具 begin-->
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-context-support</artifactId>
    </dependency>
    <!-- Spring框架基本的核心工具 end-->

    <!-- SpringWeb模块 begin-->
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-web</artifactId>
    </dependency>
    <!-- SpringWeb模块 end-->
</dependencies>

1.3 Gangbb-admin的pom.xml

<dependencies>
    <!-- SpringBoot Web容器  begin-->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
        <!--以下是排除的组件-->
        <exclusions>
            <!--排除默认自带的log组件-->
            <exclusion>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-logging</artifactId>
            </exclusion>
        </exclusions>
    </dependency>
    <!-- SpringBoot Web容器  end-->
    
    <!--项目core核心类 begin-->
    <dependency>
        <groupId>com.gangbb</groupId>
        <artifactId>Gangbb-core</artifactId>
    </dependency>
    <!--项目core核心类 end-->
</dependencies>

注解要删除上节使用的:

<!--项目common通用工具类 begin(下一章该文件删除该依赖)-->
<dependency>
    <groupId>com.gangbb</groupId>
    <artifactId>Gangbb-common</artifactId>
</dependency>
<!--项目common通用工具类 end-->

因为导入的Gangbb-core中已经有Gangbb-common,不删除会导致循环依赖。

2. 创建数据库表

表名和其中一些字段名和若依的不一样

CREATE TABLE `sys_operation_log` (
  `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '日志主键id',
  `title` varchar(255) DEFAULT '' COMMENT '操作模块',
  `business_type` tinyint(4) unsigned DEFAULT '0' COMMENT '业务类型(0其它 1新增 2修改 3删除)',
  `class_method` varchar(255) DEFAULT '' COMMENT '请求处理方法',
  `request_method` varchar(255) DEFAULT '' COMMENT '请求方式',
  `operator_type` tinyint(4) unsigned DEFAULT '0' COMMENT '操作类别(0其它 1后台用户 2手机端用户)',
  `operation_name` varchar(50) DEFAULT '' COMMENT '操作人员',
  `operation_url` varchar(150) DEFAULT '' COMMENT '请求url',
  `operation_ip` varchar(20) DEFAULT '' COMMENT '操作ip',
  `operation_location` varchar(255) DEFAULT '' COMMENT '操作地点',
  `operation_param` varchar(255) DEFAULT '' COMMENT '请求参数',
  `json_result` varchar(255) DEFAULT '' COMMENT '返回参数',
  `operation_status` tinyint(4) unsigned DEFAULT '0' COMMENT '操作状态(0正常 1异常)',
  `error_msg` varchar(255) DEFAULT '' COMMENT '错误消息',
  `operation_time` datetime DEFAULT NULL COMMENT '操作时间',
  `creator` varchar(100) DEFAULT '' COMMENT '创建者',
  `createTime` datetime DEFAULT NULL COMMENT '创建时间',
  `reviser` varchar(100) DEFAULT '' COMMENT '更新者',
  `updateTime` datetime DEFAULT NULL COMMENT '更新时间',
  `isDel` tinyint(4) unsigned DEFAULT '0' COMMENT '是否删除 0-未删除  1-已删除',
  `remark` varchar(255) DEFAULT '' COMMENT '备注',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=12 DEFAULT CHARSET=utf8;

3. 自定义注解@Log及相关枚举

在 common通用工具模块 中定义:

在这里插入图片描述

一、Log

@Target({ ElementType.PARAMETER, ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Log
{
    /**
     * 模块
     */
    public String title() default "";

    /**
     * 功能
     */
    public BusinessType businessType() default BusinessType.OTHER;

    /**
     * 操作人类别
     */
    public OperatorType operatorType() default OperatorType.MANAGE;

    /**
     * 是否保存请求的参数
     */
    public boolean isSaveRequestData() default true;
}

二、BusinessType

public enum BusinessType
{
    /**
     * 其它
     */
    OTHER,

    /**
     * 新增
     */
    INSERT,

    /**
     * 修改
     */
    UPDATE,

    /**
     * 删除
     */
    DELETE,

    /**
     * 授权
     */
    GRANT,

    /**
     * 导出
     */
    EXPORT,

    /**
     * 导入
     */
    IMPORT,

    /**
     * 强退
     */
    FORCE,

    /**
     * 生成代码
     */
    GENCODE,

    /**
     * 清空数据
     */
    CLEAN,
}

三、OperatorType

public enum OperatorType
{
    /**
     * 其它
     */
    OTHER,

    /**
     * 后台用户
     */
    MANAGE,

    /**
     * 手机端用户
     */
    MOBILE
}

3. AOP切面处理请求操作日志

本节代码涉及过长不再贴出

整体思路:切入带有@Log的Controller,记录相应的请求信息。

需要先定义本节需要的一些实体类、枚举和工具类:

(其中有互相引用的,全部引入项目就不会错)

  • BaseEntity所有entity实体类都要继承的基类,

  • SysOperationLog操作日志记录表 对应数据库(sys_operation_log)表

  • BusinessStatus 操作状态枚举

  • BusinessType业务操作类型 枚举

  • OperatorType操作人类别 枚举

  • StringUtils字符串工具类

  • CharsetKit字符集工具类

  • Convert类型转换器

  • StrFormatter字符串格式化工具

  • IpUtils获取IP工具类

  • EscapeUtil转义和反转义工具类

  • HTMLFilterHTML过滤器,用于去除XSS漏洞隐患

  • ServletUtils客户端工具类

  • AddressUtils获取地址类

  • HttpUtils通用http发送方法

  • Constants通用常量信息

  • GangbbConfig读取项目相关配置

  • AsyncManager异步任务管理器

  • Threads线程相关工具类

  • SpringUtilsspring工具类 方便在非spring管理环境中获取bean

  • ThreadPoolConfig线程池配置

  • AsyncFactory异步工厂,产生任务用(目前只定义了 记录操作日志信息recordOperation方法,记录登录信息recordLogininfor方法后面到登录再涉及)

核心的LogAspect切面处理类中的保存Log具体处理方法handleLog主要逻辑:

  1. 获得注解
  2. 从缓存获取当前的用户信息(暂缺,先模拟一个)
  3. 获取请求各项需要记录的基本信息
  4. 判断请求是否有异常
  5. 保存到数据库
  6. 打印到控制台

既然最后一步要操数据库当然需要各层的文件:

在这里插入图片描述

5. log4j2的配置文件

<?xml version="1.0" encoding="UTF-8"?>
<!--
    6个优先级从高到低依次为:OFF、FATAL、ERROR、WARN、INFO、DEBUG、TRACE、 ALL。
    如果设置优先级为WARN,那么OFF、FATAL、ERROR、WARN 4个级别的log能正常输出
    设置为OFF 表示不记录log4j2本身的日志,
 -->
<!-- status:用来指定log4j本身的打印日志级别,monitorInterval:指定log4j自动重新配置的监测间隔时间 -->
<Configuration status="fatal">
  <Properties>
    <Property name="baseDir" value="${sys:user.home}/logs/Gangbb_Vue"/>
  </Properties>

  <Appenders>
    <Console name="Console" target="SYSTEM_OUT">
      <!--控制台只输出level及以上级别的信息(onMatch),其他的直接拒绝(onMismatch) -->
      <ThresholdFilter level="debug" onMatch="ACCEPT"
        onMismatch="DENY"/>
      <PatternLayout
        pattern="[%d{MM:dd HH:mm:ss.SSS}] [%level] [%logger{36}] - %msg%n"/>
    </Console>

    <!--debug级别日志文件输出-->
    <RollingFile name="debug_appender" fileName="${baseDir}/debug.log"
      filePattern="${baseDir}/debug_%i.log.%d{yyyy-MM-dd}">
      <!-- 过滤器 -->
      <Filters>
        <!-- 限制日志级别在debug及以上在info以下 -->
        <ThresholdFilter level="debug"/>
        <ThresholdFilter level="info" onMatch="DENY" onMismatch="NEUTRAL"/>
      </Filters>
      <!-- 日志格式 -->
      <PatternLayout pattern="[%d{HH:mm:ss:SSS}] [%p] - %l - %m%n"/>
      <!-- 策略 -->
      <Policies>
        <!-- 每隔一天转存 -->
        <TimeBasedTriggeringPolicy interval="1" modulate="true"/>
        <!-- 文件大小 -->
        <SizeBasedTriggeringPolicy size="100 MB"/>
      </Policies>
      <!-- DefaultRolloverStrategy属性如不设置,则默认为最多同一文件夹下7个文件开始覆盖-->
      <DefaultRolloverStrategy max="15"/>
    </RollingFile>

    <!-- info级别日志文件输出 -->
    <RollingFile name="info_appender" fileName="${baseDir}/info.log"
      filePattern="${baseDir}/info_%i.log.%d{yyyy-MM-dd}">
      <!-- 过滤器 -->
      <Filters>
        <!-- 限制日志级别在info及以上在error以下 -->
        <ThresholdFilter level="info"/>
        <ThresholdFilter level="error" onMatch="DENY" onMismatch="NEUTRAL"/>
      </Filters>
      <!-- 日志格式 -->
      <PatternLayout pattern="[%d{HH:mm:ss:SSS}] [%p] - %l - %m%n"/>
      <!-- 策略 -->
      <Policies>
        <!-- 每隔一天转存 -->
        <TimeBasedTriggeringPolicy interval="1" modulate="true"/>
        <!-- 文件大小 -->
        <SizeBasedTriggeringPolicy size="100 MB"/>
      </Policies>
      <!-- DefaultRolloverStrategy属性如不设置,则默认为最多同一文件夹下7个文件开始覆盖-->
      <DefaultRolloverStrategy max="15"/>
    </RollingFile>

    <!-- error级别日志文件输出 -->
    <RollingFile name="error_appender" fileName="${baseDir}/error.log"
      filePattern="${baseDir}/error_%i.log.%d{yyyy-MM-dd}">
      <!-- 过滤器 -->
      <Filters>
        <!-- 限制日志级别在error及以上 -->
        <ThresholdFilter level="error"/>
      </Filters>
      <!-- 日志格式 -->
      <PatternLayout pattern="[%d{HH:mm:ss:SSS}] [%p] - %l - %m%n"/>
      <Policies>
        <!-- 每隔一天转存 -->
        <TimeBasedTriggeringPolicy interval="1" modulate="true"/>
        <!-- 文件大小 -->
        <SizeBasedTriggeringPolicy size="100 MB"/>
      </Policies>
      <!-- DefaultRolloverStrategy属性如不设置,则默认为最多同一文件夹下7个文件开始覆盖-->
      <DefaultRolloverStrategy max="15"/>
    </RollingFile>
  </Appenders>
  <!--Logger节点用来单独指定日志的形式,比如要为指定包下的class指定不同的日志级别等。-->
  <!--然后定义loggers,只有定义了logger并引入的appender,appender才会生效-->
  <!--监控系统信息-->
  <!--若是additivity设为false,则 子Logger 只会在自己的appender里输出,而不会在 父Logger 的appender里输出。-->
  <Loggers>
    <!--过滤掉spring和mybatis的一些无用的DEBUG信息-->
    <logger name="org.mybatis" level="info" additivity="false">
      <AppenderRef ref="Console"/>
    </logger>

    <Logger name="org.springframework" level="WARN" additivity="false">
      <AppenderRef ref="Console"/>
    </Logger>

    <!-- 设置com.zaxxer.hikari包下的日志只打印WARN及以上级别的日志 -->
    <logger name="com.zaxxer.hikari" level="WARN" additivity="false">
      <appender-ref ref="Console"/>
    </logger>

    <!-- 设置org.hibernate.validator包下的日志只打印WARN及以上级别的日志 -->
    <logger name="org.hibernate.validator" level="WARN" additivity="false">
      <appender-ref ref="Console"/>
    </logger>

    <!-- 设置org.apache包下的日志只打印WARN及以上级别的日志 -->
<!--    <logger name="org.apache" level="WARN" additivity="false">-->
<!--      <appender-ref ref="Console"/>-->
<!--    </logger>-->

    <Root level="debug">
      <AppenderRef ref="Console"/>
      <AppenderRef ref="debug_appender"/>
      <AppenderRef ref="info_appender"/>
      <AppenderRef ref="error_appender"/>
    </Root>

  </Loggers>
</Configuration>

看到控制台有什么不爽的打印信息,在 标签对内再写一个<logger …>过滤就行了!

6. 修改Mybatis配置

  • 添加:MyBatisConfig使 Mybatis支持*匹配扫描包

  • Gangbb-admin的application.yml:

mybatis:
  configuration:
    # 实体类驼峰命名转成数据库中的下划线命名
    map-underscore-to-camel-case: true
    # 指定 MyBatis 所用日志的具体实现
    log-impl: org.apache.ibatis.logging.slf4j.Slf4jImpl
    # 全局映射器启用缓存
    cache-enabled: true
    # 允许 JDBC 支持自动生成主键
    use-generated-keys: true
    # 配置默认的执行器
    default-executor-type: reuse
  # 配置mapper的扫描,找到所有的mapper.xml映射文件
  mapper-locations: classpath*:mapper/**/*Mapper.xml
  # 扫描实体类路径(搜索指定包别名)
  type-aliases-package: com.gangbb.**.entity
  • ApplicationConfig配置对dao层mapper的扫描。
@Configuration
// 表示通过aop框架暴露该代理对象,AopContext能够访问
@EnableAspectJAutoProxy(exposeProxy = true)
// 指定要扫描的Mapper类的包的路径
@MapperScan("com.gangbb.**.dao")
public class ApplicationConfig
{
    /**
     * 时区配置
     */
    @Bean
    public Jackson2ObjectMapperBuilderCustomizer jacksonObjectMapperCustomization()
    {
        return jacksonObjectMapperBuilder -> jacksonObjectMapperBuilder.timeZone(TimeZone.getDefault());
    }
}

6. 测试日志记录

新建测试TestLogAnnotationController

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-CmYOHPyp-1628818991043)(http://img.gangbb.cn/image-20210308104540292.png#pic_center)]

@RestController
@RequestMapping("log")
public class TestLogAnnotationController {

    @Log(title = "测试@Log注解", businessType = BusinessType.OTHER)
    @GetMapping("/hello")
    public String HelloLog(){
        return "测试@Log注解,记录操作日志";
    }
}

发送请求:

image-20210308104605888

日志控制台打印信息:

在这里插入图片描述

(是不是十分清晰明了,i了i了!)

数据库中也有相应的数据:
在这里插入图片描述

  • 7
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 6
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值