diff --git a/sql/ruoyi-vue-pro.sql b/sql/ruoyi-vue-pro.sql index a83584182..143dc7077 100644 --- a/sql/ruoyi-vue-pro.sql +++ b/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 +-- Table structure for sys_operate_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='操作日志记录'; +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 diff --git a/src/main/java/cn/iocoder/dashboard/framework/logger/operatelog/core/aop/OperateLogAspect.java b/src/main/java/cn/iocoder/dashboard/framework/logger/operatelog/core/aop/OperateLogAspect.java index 97a2d68a4..4ab43ad84 100644 --- a/src/main/java/cn/iocoder/dashboard/framework/logger/operatelog/core/aop/OperateLogAspect.java +++ b/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 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) { diff --git a/src/main/java/cn/iocoder/dashboard/framework/package-info.java b/src/main/java/cn/iocoder/dashboard/framework/package-info.java new file mode 100644 index 000000000..e8231cbf8 --- /dev/null +++ b/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; diff --git a/src/main/java/cn/iocoder/dashboard/modules/system/controller/logger/vo/SysOperateLogBaseVO.java b/src/main/java/cn/iocoder/dashboard/modules/system/controller/logger/vo/SysOperateLogBaseVO.java index 0fbf1ee05..31d734461 100644 --- a/src/main/java/cn/iocoder/dashboard/modules/system/controller/logger/vo/SysOperateLogBaseVO.java +++ b/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 javaMethodArgs; + private String javaMethodArgs; @ApiModelProperty(value = "开始时间", required = true) @NotNull(message = "开始时间不能为空") diff --git a/src/main/java/cn/iocoder/dashboard/modules/system/dal/mysql/dataobject/logger/SysOperateLogDO.java b/src/main/java/cn/iocoder/dashboard/modules/system/dal/mysql/dataobject/logger/SysOperateLogDO.java index fc807ce01..be835d006 100644 --- a/src/main/java/cn/iocoder/dashboard/modules/system/dal/mysql/dataobject/logger/SysOperateLogDO.java +++ b/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 + * 不使用 @TableField(typeHandler = FastjsonTypeHandler.class) 注解的原因是,数据库存储有长度限制,会进行裁剪,会导致 JSON 反序列化失败 + * 其中,key 为参数名,value 为参数值 */ - @TableField(typeHandler = FastjsonTypeHandler.class) - private Map javaMethodArgs; + private String javaMethodArgs; /** * 开始时间 */ diff --git a/src/main/java/cn/iocoder/dashboard/modules/system/service/logger/impl/SysOperateLogServiceImpl.java b/src/main/java/cn/iocoder/dashboard/modules/system/service/logger/impl/SysOperateLogServiceImpl.java index 9c5debfd3..4c7905da2 100644 --- a/src/main/java/cn/iocoder/dashboard/modules/system/service/logger/impl/SysOperateLogServiceImpl.java +++ b/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) { // 仅仅打印日志,不对外抛出。原因是,还是要保留现场数据。 diff --git a/src/main/java/cn/iocoder/dashboard/util/string/StrUtils.java b/src/main/java/cn/iocoder/dashboard/util/string/StrUtils.java new file mode 100644 index 000000000..5e98d915b --- /dev/null +++ b/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 的原因,是该方法会补充 ... 恰好 + } + +}