瀏覽代碼

完成操作日志的存储

YunaiV 4 年之前
父節點
當前提交
30076f6472

+ 32 - 24
sql/ruoyi-vue-pro.sql

@@ -11,7 +11,7 @@
  Target Server Version : 50718
  File Encoding         : 65001
 
- Date: 14/01/2021 21:27:23
+ Date: 17/01/2021 01:21:15
 */
 
 SET NAMES utf8mb4;
@@ -262,28 +262,36 @@ CREATE TABLE `sys_notice` (
 ) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8mb4 COMMENT='通知公告表';
 
 -- ----------------------------
--- Table structure for sys_oper_log
--- ----------------------------
-DROP TABLE IF EXISTS `sys_oper_log`;
-CREATE TABLE `sys_oper_log` (
-  `oper_id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '日志主键',
-  `title` varchar(50) DEFAULT '' COMMENT '模块标题',
-  `business_type` int(2) DEFAULT '0' COMMENT '业务类型(0其它 1新增 2修改 3删除)',
-  `method` varchar(100) DEFAULT '' COMMENT '方法名称',
-  `request_method` varchar(10) DEFAULT '' COMMENT '请求方式',
-  `operator_type` int(1) 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(50) DEFAULT '' COMMENT '主机地址',
-  `oper_location` varchar(255) DEFAULT '' COMMENT '操作地点',
-  `oper_param` varchar(2000) DEFAULT '' COMMENT '请求参数',
-  `json_result` varchar(2000) DEFAULT '' COMMENT '返回参数',
-  `status` int(1) DEFAULT '0' COMMENT '操作状态(0正常 1异常)',
-  `error_msg` varchar(2000) DEFAULT '' COMMENT '错误消息',
-  `oper_time` datetime DEFAULT NULL COMMENT '操作时间',
-  PRIMARY KEY (`oper_id`)
-) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='操作日志记录';
+-- Table structure for sys_operate_log
+-- ----------------------------
+DROP TABLE IF EXISTS `sys_operate_log`;
+CREATE TABLE `sys_operate_log` (
+  `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '日志主键',
+  `trace_id` varchar(64) NOT NULL DEFAULT '' COMMENT '链路追踪编号',
+  `user_id` bigint(20) NOT NULL COMMENT '用户编号',
+  `module` varchar(50) NOT NULL COMMENT '模块标题',
+  `name` varchar(50) NOT NULL COMMENT '操作名',
+  `operate_type` bigint(4) NOT NULL DEFAULT '0' COMMENT '操作分类',
+  `content` varchar(2000) NOT NULL DEFAULT '' COMMENT '操作内容',
+  `exts` varchar(512) NOT NULL DEFAULT '' COMMENT '拓展字段',
+  `request_method` varchar(16) DEFAULT '' COMMENT '请求方法名',
+  `request_url` varchar(255) DEFAULT '' COMMENT '请求地址',
+  `user_ip` varchar(50) DEFAULT NULL COMMENT '用户 IP',
+  `user_agent` varchar(50) DEFAULT NULL COMMENT '浏览器 UA',
+  `java_method` varchar(512) NOT NULL DEFAULT '' COMMENT 'Java 方法名',
+  `java_method_args` varchar(8000) DEFAULT '' COMMENT 'Java 方法的参数',
+  `start_time` datetime NOT NULL COMMENT '操作时间',
+  `duration` int(11) NOT NULL COMMENT '执行时长',
+  `result_code` int(11) NOT NULL DEFAULT '0' COMMENT '结果码',
+  `result_msg` varchar(512) DEFAULT '' COMMENT '结果提示',
+  `result_data` varchar(4000) DEFAULT '' COMMENT '结果数据',
+  `create_by` varchar(64) DEFAULT '' COMMENT '创建者',
+  `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
+  `update_by` varchar(64) DEFAULT '' COMMENT '更新者',
+  `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
+  `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
+  PRIMARY KEY (`id`) USING BTREE
+) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8mb4 COMMENT='操作日志记录';
 
 -- ----------------------------
 -- Table structure for sys_post
@@ -367,7 +375,7 @@ CREATE TABLE `sys_user` (
   `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
   `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
   PRIMARY KEY (`id`) USING BTREE
-) ENGINE=InnoDB AUTO_INCREMENT=101 DEFAULT CHARSET=utf8mb4 COMMENT='用户信息表';
+) ENGINE=InnoDB AUTO_INCREMENT=104 DEFAULT CHARSET=utf8mb4 COMMENT='用户信息表';
 
 -- ----------------------------
 -- Table structure for sys_user_role

+ 2 - 2
src/main/java/cn/iocoder/dashboard/framework/logger/operatelog/core/aop/OperateLogAspect.java

@@ -272,7 +272,7 @@ public class OperateLogAspect {
         return ((MethodSignature) joinPoint.getSignature()).getMethod().getDeclaringClass().getAnnotation(annotationClass);
     }
 
-    private static Map<String, Object> obtainMethodArgs(ProceedingJoinPoint joinPoint) {
+    private static String obtainMethodArgs(ProceedingJoinPoint joinPoint) {
         // TODO 提升:参数脱敏和忽略
         MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
         String[] argNames = methodSignature.getParameterNames();
@@ -285,7 +285,7 @@ public class OperateLogAspect {
             // 被忽略时,标记为 ignore 字符串,避免和 null 混在一起
             args.put(argName, !isIgnoreArgs(argValue) ? argValue : "[ignore]");
         }
-        return args;
+        return JSON.toJSONString(argValues);
     }
 
     private static String obtainResultData(Object result) {

+ 10 - 0
src/main/java/cn/iocoder/dashboard/framework/package-info.java

@@ -0,0 +1,10 @@
+/**
+ * 该包是技术组件,每个子包,代表一个组件。每个组件包括两部分:
+ * 1. core 包:是该组件的核心分装
+ * 2. config 包:是该组件基于 Spring 的配置
+ *
+ * 技术组件,也分成两类:
+ * 1. 框架组件:和我们熟悉的 MyBatis、Redis 等等的拓展
+ * 2. 业务组件:和业务相关的组件的封装,例如说数据字典、操作日志等等。
+ */
+package cn.iocoder.dashboard.framework;

+ 1 - 2
src/main/java/cn/iocoder/dashboard/modules/system/controller/logger/vo/SysOperateLogBaseVO.java

@@ -6,7 +6,6 @@ import lombok.Data;
 import javax.validation.constraints.NotEmpty;
 import javax.validation.constraints.NotNull;
 import java.util.Date;
-import java.util.Map;
 
 /**
  * 操作日志 Base VO,提供给添加、修改、详细的子 VO 使用
@@ -56,7 +55,7 @@ public class SysOperateLogBaseVO {
     private String javaMethod;
 
     @ApiModelProperty(value = "Java 方法的参数")
-    private Map<String, Object> javaMethodArgs;
+    private String javaMethodArgs;
 
     @ApiModelProperty(value = "开始时间", required = true)
     @NotNull(message = "开始时间不能为空")

+ 16 - 2
src/main/java/cn/iocoder/dashboard/modules/system/dal/mysql/dataobject/logger/SysOperateLogDO.java

@@ -24,6 +24,16 @@ import java.util.Map;
 @EqualsAndHashCode(callSuper = true)
 public class SysOperateLogDO extends BaseDO {
 
+    /**
+     * {@link #javaMethodArgs} 的最大长度
+     */
+    public static final Integer JAVA_METHOD_ARGS_MAX_LENGTH = 8000;
+
+    /**
+     * {@link #resultData} 的最大长度
+     */
+    public static final Integer RESULT_MAX_LENGTH = 4000;
+
     /**
      * 日志主键
      */
@@ -54,6 +64,7 @@ public class SysOperateLogDO extends BaseDO {
      *
      * 枚举 {@link SysOperateLogTypeEnum}
      */
+    @TableField("operate_type")
     private Integer type;
     /**
      * 操作内容,记录整个操作的明细
@@ -94,9 +105,12 @@ public class SysOperateLogDO extends BaseDO {
     private String javaMethod;
     /**
      * Java 方法的参数
+     *
+     * 实际格式为 Map<String, Object>
+     *     不使用 @TableField(typeHandler = FastjsonTypeHandler.class) 注解的原因是,数据库存储有长度限制,会进行裁剪,会导致 JSON 反序列化失败
+     *     其中,key 为参数名,value 为参数值
      */
-    @TableField(typeHandler = FastjsonTypeHandler.class)
-    private Map<String, Object> javaMethodArgs;
+    private String javaMethodArgs;
     /**
      * 开始时间
      */

+ 6 - 1
src/main/java/cn/iocoder/dashboard/modules/system/service/logger/impl/SysOperateLogServiceImpl.java

@@ -5,12 +5,15 @@ import cn.iocoder.dashboard.modules.system.convert.logger.SysOperateLogConvert;
 import cn.iocoder.dashboard.modules.system.dal.mysql.dao.logger.SysOperateLogMapper;
 import cn.iocoder.dashboard.modules.system.dal.mysql.dataobject.logger.SysOperateLogDO;
 import cn.iocoder.dashboard.modules.system.service.logger.SysOperateLogService;
+import cn.iocoder.dashboard.util.string.StrUtils;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.scheduling.annotation.Async;
 import org.springframework.stereotype.Service;
 
 import javax.annotation.Resource;
 
+import static cn.iocoder.dashboard.modules.system.dal.mysql.dataobject.logger.SysOperateLogDO.*;
+
 @Service
 @Slf4j
 public class SysOperateLogServiceImpl implements SysOperateLogService {
@@ -21,8 +24,10 @@ public class SysOperateLogServiceImpl implements SysOperateLogService {
     @Override
     @Async
     public void createOperateLogAsync(SysOperateLogCreateReqVO reqVO) {
-        SysOperateLogDO logDO = SysOperateLogConvert.INSTANCE.convert(reqVO);
         try {
+            SysOperateLogDO logDO = SysOperateLogConvert.INSTANCE.convert(reqVO);
+            logDO.setJavaMethodArgs(StrUtils.maxLength(logDO.getJavaMethodArgs(), JAVA_METHOD_ARGS_MAX_LENGTH));
+            logDO.setResultData(StrUtils.maxLength(logDO.getResultData(), RESULT_MAX_LENGTH));
             operateLogMapper.insert(logDO);
         } catch (Throwable throwable) {
             // 仅仅打印日志,不对外抛出。原因是,还是要保留现场数据。

+ 16 - 0
src/main/java/cn/iocoder/dashboard/util/string/StrUtils.java

@@ -0,0 +1,16 @@
+package cn.iocoder.dashboard.util.string;
+
+import cn.hutool.core.util.StrUtil;
+
+/**
+ * 字符串工具类
+ *
+ * @author 芋道源码
+ */
+public class StrUtils {
+
+    public static String maxLength(CharSequence str, int maxLength) {
+        return StrUtil.maxLength(str, maxLength - 3); // -3 的原因,是该方法会补充 ... 恰好
+    }
+
+}