程序员scholar 程序员scholar
首页
  • Java 基础

    • JavaSE
    • JavaIO
    • JavaAPI速查
  • Java 高级

    • JUC
    • JVM
    • Java新特性
    • 设计模式
  • Web 开发

    • Servlet
    • Java网络编程
  • Web 标准

    • HTML
    • CSS
    • JavaScript
  • 前端框架

    • Vue2
    • Vue3
    • 微信小程序
    • uni-app
  • 工具与库

    • jQuery
    • Ajax
    • Axios
    • Webpack
    • Vuex
    • WebSocket
    • 第三方登录
  • 后端与语言扩展

    • ES6
    • Typescript
    • node.js
  • Element-UI
  • Apache ECharts
  • 数据结构
  • HTTP协议
  • HTTPS协议
  • 计算机网络
  • Linux常用命令
  • Windows常用命令
  • SQL数据库

    • MySQL
    • MySQL速查
  • NoSQL数据库

    • Redis
    • ElasticSearch
  • 数据库

    • MyBatis
    • MyBatis-Plus
  • 消息中间件

    • RabbitMQ
  • 服务器

    • Nginx
  • Spring框架

    • Spring6
    • SpringMVC
    • SpringBoot
    • SpringSecurity
  • SpringCould微服务

    • SpringCloud基础
    • 微服务之DDD架构思想
  • 日常必备

    • 开发常用工具包
    • Hutoll工具包
    • IDEA常用配置
    • 开发笔记
    • 若依框架
    • 日常记录
    • 项目部署
    • 网站导航
    • 产品学习
    • 英语学习
  • 代码管理

    • Maven
    • Git教程
    • Git小乌龟教程
  • 运维工具

    • Docker
    • Jenkins
    • Kubernetes
  • 算法笔记

    • 算法思想
    • 刷题笔记
  • 面试问题常见

    • 十大经典排序算法
    • 面试常见问题集锦
关于
GitHub (opens new window)
首页
  • Java 基础

    • JavaSE
    • JavaIO
    • JavaAPI速查
  • Java 高级

    • JUC
    • JVM
    • Java新特性
    • 设计模式
  • Web 开发

    • Servlet
    • Java网络编程
  • Web 标准

    • HTML
    • CSS
    • JavaScript
  • 前端框架

    • Vue2
    • Vue3
    • 微信小程序
    • uni-app
  • 工具与库

    • jQuery
    • Ajax
    • Axios
    • Webpack
    • Vuex
    • WebSocket
    • 第三方登录
  • 后端与语言扩展

    • ES6
    • Typescript
    • node.js
  • Element-UI
  • Apache ECharts
  • 数据结构
  • HTTP协议
  • HTTPS协议
  • 计算机网络
  • Linux常用命令
  • Windows常用命令
  • SQL数据库

    • MySQL
    • MySQL速查
  • NoSQL数据库

    • Redis
    • ElasticSearch
  • 数据库

    • MyBatis
    • MyBatis-Plus
  • 消息中间件

    • RabbitMQ
  • 服务器

    • Nginx
  • Spring框架

    • Spring6
    • SpringMVC
    • SpringBoot
    • SpringSecurity
  • SpringCould微服务

    • SpringCloud基础
    • 微服务之DDD架构思想
  • 日常必备

    • 开发常用工具包
    • Hutoll工具包
    • IDEA常用配置
    • 开发笔记
    • 若依框架
    • 日常记录
    • 项目部署
    • 网站导航
    • 产品学习
    • 英语学习
  • 代码管理

    • Maven
    • Git教程
    • Git小乌龟教程
  • 运维工具

    • Docker
    • Jenkins
    • Kubernetes
  • 算法笔记

    • 算法思想
    • 刷题笔记
  • 面试问题常见

    • 十大经典排序算法
    • 面试常见问题集锦
关于
GitHub (opens new window)
npm

(进入注册为作者充电)

  • 快速入门

  • 后端手册

    • 分页实现
    • 导入导出功能
    • 文件上传与下载
    • 权限注解实现
    • 事务管理详解
    • 全局异常处理
    • 参数验证详解
    • 数据脱敏详解
    • 系统日志功能实现
      • 一、@Log 注解参数说明
        • 1. title 参数
        • 2. businessType 参数
        • 3. operatorType 参数
        • 4. isSaveRequestData 参数
        • 5. isSaveResponseData 参数
        • 6. excludeParamNames 参数
      • 二、自定义操作功能类型
        • 1. 在 BusinessType 枚举中新增业务操作类型
        • 2. 在数据库字典表中初始化操作业务类型
        • 3. 在 Controller 中使用自定义的操作类型
      • 三、操作日志记录逻辑实现
        • 1. LogAspect 切面类的基本实现
        • 2. 操作日志的异步保存
      • 四、系统日志查询
        • 1. 日志查询接口
      • 五、总结
    • 数据权限控制
    • 多数据源实现
    • 代码生成功能
    • 定时任务实现
    • 系统接口文档生成
    • 防重复提交实现
    • 国际化支持
    • 新建子模块
  • 前端手册

  • 组件文档

  • 数据库分析

  • 若依框架
  • 后端手册
scholar
2024-08-31
目录

系统日志功能实现

# 系统日志功能实现

在企业级应用中,记录系统日志是保障系统安全性、审计操作行为、定位问题的重要手段。通过记录用户操作的内容,我们可以追溯系统中的关键业务活动。若依框架提供了使用注解的方式来简化日志记录,只需在 Controller 方法上添加 @Log 注解,即可自动记录操作日志。

# 一、@Log 注解参数说明

若依框架中的 @Log 注解用于标注需要记录日志的 Controller 方法,开发者可以通过设置注解参数来自定义日志的记录内容和方式。以下是 @Log 注解的详细参数说明:

参数 类型 默认值 描述
title String 空 操作模块的名称,例如“用户管理”
businessType BusinessType OTHER 操作功能类型(如:新增、修改、删除等)
operatorType OperatorType MANAGE 操作人类别(如:后台用户、手机端用户等)
isSaveRequestData boolean true 是否保存请求的参数
isSaveResponseData boolean true 是否保存响应的参数
excludeParamNames String[] {} 排除指定的请求参数,不记录这些参数到日志中

# 1. title 参数

title 参数用于指定操作模块的名称,通常是业务模块的名称。例如,在“用户管理”模块中新增用户操作时,可以将 title 设置为“用户管理”。

@Log(title = "用户管理", businessType = BusinessType.INSERT)
public AjaxResult addSave(User user)
{
    return success(userService.insertUser(user));
}
1
2
3
4
5

# 2. businessType 参数

businessType 参数用于指定操作的功能类型,若依框架内置了多种常见的业务操作类型,如新增(INSERT)、修改(UPDATE)、删除(DELETE)等。开发者也可以自定义业务操作类型。

@Log(title = "用户管理", businessType = BusinessType.UPDATE)
public AjaxResult editSave(User user)
{
    return success(userService.updateUser(user));
}
1
2
3
4
5

# 3. operatorType 参数

operatorType 参数用于指定操作人的类别,常见的类别有后台用户(MANAGE)和手机端用户(MOBILE)。在不同的场景下,可以根据需要设置不同的操作人类别。

@Log(title = "用户管理", businessType = BusinessType.DELETE, operatorType = OperatorType.MANAGE)
public AjaxResult remove(Long userId)
{
    return success(userService.deleteUserById(userId));
}
1
2
3
4
5

# 4. isSaveRequestData 参数

isSaveRequestData 参数用于控制是否保存请求的参数。默认情况下,若依会自动记录请求参数,但在某些场景下(如涉及敏感信息)可以选择不保存。

@Log(title = "用户管理", businessType = BusinessType.INSERT, isSaveRequestData = false)
public AjaxResult addSave(User user)
{
    return success(userService.insertUser(user));
}
1
2
3
4
5

# 5. isSaveResponseData 参数

isSaveResponseData 参数用于控制是否保存响应的数据。默认情况下,若依会自动记录响应数据,如果不需要记录响应数据,可以将此参数设置为 false。

@Log(title = "用户管理", businessType = BusinessType.INSERT, isSaveResponseData = false)
public AjaxResult addSave(User user)
{
    return success(userService.insertUser(user));
}
1
2
3
4
5

# 6. excludeParamNames 参数

excludeParamNames 参数用于指定不记录的请求参数,避免将某些敏感信息记录到日志中。

@Log(title = "用户管理", businessType = BusinessType.INSERT, excludeParamNames = {"password", "salt"})
public AjaxResult addSave(User user)
{
    return success(userService.insertUser(user));
}
1
2
3
4
5

# 二、自定义操作功能类型

若依框架允许开发者根据业务需求自定义操作功能类型。以下是如何添加自定义业务操作类型的步骤:

# 1. 在 BusinessType 枚举中新增业务操作类型

首先,打开 BusinessType 枚举类,添加新的操作类型。例如,添加一个用于测试的操作类型 TEST。

package com.ruoyi.common.enums;

/**
 * 业务操作类型
 * 
 * @author ruoyi
 */
public enum BusinessType
{
    // 其他操作类型省略...

    /**
     * 测试操作
     */
    TEST,
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

# 2. 在数据库字典表中初始化操作业务类型

接着,在 sys_dict_data 字典表中初始化操作业务类型,以便在日志管理中正确显示自定义操作类型。

INSERT INTO sys_dict_data (dict_code, dict_sort, dict_label, dict_value, dict_type, css_class, list_class, is_default, status, create_by, create_time, update_by, update_time, remark) 
VALUES (100, 10, '测试', '10', 'sys_oper_type', '', 'primary', 'N', '0', 'admin', NOW(), 'admin', NOW(), '测试操作');
1
2

# 3. 在 Controller 中使用自定义的操作类型

在需要记录日志的 Controller 方法中使用自定义的 BusinessType。

@Log(title = "测试模块", businessType = BusinessType.TEST)
public AjaxResult testOperation(User user)
{
    return success(userService.testOperation(user));
}
1
2
3
4
5

# 三、操作日志记录逻辑实现

操作日志的记录逻辑通常通过 AOP(面向切面编程)来实现,若依框架通过 LogAspect 切面类来拦截标记了 @Log 注解的方法,并将操作日志记录到数据库中。

# 1. LogAspect 切面类的基本实现

LogAspect 是日志记录的切面类,负责拦截所有标记了 @Log 注解的方法,并根据注解参数执行日志记录操作。

package com.ruoyi.framework.aspectj;

import com.ruoyi.common.annotation.Log;
import com.ruoyi.common.enums.BusinessStatus;
import com.ruoyi.common.utils.ServletUtils;
import com.ruoyi.framework.manager.AsyncManager;
import com.ruoyi.framework.manager.factory.AsyncFactory;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;

@Aspect
@Component
public class LogAspect
{
    // 定义切点,拦截所有标记了@Log注解的方法
    @Pointcut("@annotation(com.ruoyi.common.annotation.Log)")
    public void logPointCut() {}

    // 前置通知,执行方法前记录日志
    @Before("logPointCut()")
    public void doBefore(JoinPoint joinPoint)
    {
        handleLog(joinPoint, null);
    }

    // 异常通知,记录异常信息
    @AfterThrowing(value = "logPointCut()", throwing = "e")
    public void doAfterThrowing(JoinPoint joinPoint, Exception e)
    {
        handleLog(joinPoint, e);
    }

    // 日志处理逻辑
    protected void handleLog(final JoinPoint joinPoint, final Exception e)
    {
        try
        {
            Log controllerLog = getAnnotationLog(joinPoint);
            if (controllerLog == null)
            {
                return;
            }

            // 获取当前用户信息
            String username = SecurityUtils.getUsername();
            
            // 获取请求方法、参数等信息
            String className = joinPoint.getTarget().getClass().getName();
            String methodName = joinPoint.getSignature().getName();

            // 异步保存日志
            AsyncManager.me().execute(AsyncFactory.recordOperLog(username, className, methodName, controllerLog, e));
        }
        catch (Exception exp)
        {
            // 记录日志异常
        }
    }

    // 获取注解
    private Log getAnnotationLog(JoinPoint joinPoint) throws Exception
    {
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        Method method = signature.getMethod();

        if (method != null)
        {
            return method.getAnnotation(Log.class);
        }
        return null;
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73

# 2. 操作日志的异步保存

为了避免影响业务操作的性能,若依框架将日志记录的操作放到异步任务中执行。AsyncFactory 工厂类用于创建异步任务,AsyncManager 管理这些任务的执行。

package com.ruoyi.framework.manager.factory;

import com.ruoyi.system.domain.SysOperLog;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;

@Component
public class AsyncFactory
{
    @Async
    public static void recordOperLog(String username, String className, String methodName, Log log, Exception e)
    {
        SysOperLog operLog = new SysOperLog();
        operLog.setOperName(username

);
        operLog.setOperMethod(className + "." + methodName);
        operLog.setBusinessType(log.businessType().ordinal());
        operLog.setStatus(e == null ? BusinessStatus.SUCCESS.ordinal() : BusinessStatus.FAIL.ordinal());

        // 异步保存日志到数据库
        SpringUtils.getBean(ISysOperLogService.class).insertOperLog(operLog);
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24

# 四、系统日志查询

若依框架提供了完善的系统日志查询功能,管理员可以通过“系统管理-操作日志”模块查看所有操作日志的详细信息,包括操作时间、操作人、操作类型、请求参数、响应结果等。

# 1. 日志查询接口

系统日志查询的后端接口通常位于 SysOperLogController 控制器中,支持分页查询、日志详情查看等功能。

@RestController
@RequestMapping("/system/operlog")
public class SysOperLogController extends BaseController
{
    @Autowired
    private ISysOperLogService operLogService;

    @GetMapping("/list")
    public TableDataInfo list(SysOperLog operLog)
    {
        startPage();
        List<SysOperLog> list = operLogService.selectOperLogList(operLog);
        return getDataTable(list);
    }

    @DeleteMapping("/{operIds}")
    public AjaxResult remove(@PathVariable Long[] operIds)
    {
        return toAjax(operLogService.deleteOperLogByIds(operIds));
    }

    @GetMapping("/detail/{operId}")
    public AjaxResult detail(@PathVariable Long operId)
    {
        return success(operLogService.selectOperLogById(operId));
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27

# 五、总结

通过 @Log 注解和 AOP 技术,若依框架简化了系统日志的记录过程,使开发者能够专注于业务逻辑而无需担心日志的记录细节。

  • 日志记录: 通过 @Log 注解,轻松记录操作日志,支持自定义操作类型、操作人类别、请求和响应数据等。
  • 异步保存: 通过异步任务的方式保存日志,确保日志记录不会影响业务操作的性能。
  • 日志查询: 提供完善的日志查询功能,支持分页查询、日志详情查看等,方便管理员追踪系统操作记录。
编辑此页 (opens new window)
上次更新: 2024/12/28, 18:32:08
数据脱敏详解
数据权限控制

← 数据脱敏详解 数据权限控制→

Theme by Vdoing | Copyright © 2019-2025 程序员scholar
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式