update 优化操作日志

This commit is contained in:
AprilWind
2026-04-03 14:49:46 +08:00
parent ef3fa714bb
commit bcc11dcc12
11 changed files with 433 additions and 124 deletions

View File

@@ -1,7 +1,8 @@
package org.dromara.common.log.annotation;
import org.dromara.common.log.enums.BusinessType;
import org.dromara.common.log.enums.OperatorType;
import org.dromara.common.log.enums.OperateChannel;
import org.springframework.core.annotation.AliasFor;
import java.lang.annotation.*;
@@ -14,20 +15,44 @@ import java.lang.annotation.*;
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Log {
/**
* 模块
* 模块【已废弃,请使用 module】
*
* @deprecated 请使用 {@link #module()}
*/
@Deprecated
String title() default "";
/**
* 功能
* 业务模块名称(必填,如:用户管理、订单管理)
*/
String module() default "";
/**
* 操作功能名称(必填,如:新增用户、导出订单)
*/
String name() default "";
/**
* 操作描述(备注)
*/
String remark() default "";
/**
* 标签(用于检索/分类)
*/
String[] tags() default {};
/**
* 业务类型(查询/新增/修改/删除/导入/导出等)
*/
BusinessType businessType() default BusinessType.OTHER;
/**
* 操作人类别
* 操作渠道WEB / APP / MINI_APP / OPEN_API 等
*/
OperatorType operatorType() default OperatorType.MANAGE;
OperateChannel channel() default OperateChannel.WEB;
/**
* 是否保存请求的参数
@@ -39,7 +64,6 @@ public @interface Log {
*/
boolean isSaveResponseData() default true;
/**
* 排除指定的请求参数
*/

View File

@@ -4,6 +4,8 @@ import cn.hutool.core.lang.Dict;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.http.useragent.UserAgent;
import cn.hutool.http.useragent.UserAgentUtil;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
@@ -48,7 +50,7 @@ public class LogAspect {
/**
* 在目标方法执行前启动耗时统计。
*
* @param joinPoint 切点
* @param joinPoint 切点
* @param controllerLog 日志注解
*/
@Before(value = "@annotation(controllerLog)")
@@ -61,9 +63,9 @@ public class LogAspect {
/**
* 在目标方法正常返回后记录操作日志。
*
* @param joinPoint 切点
* @param joinPoint 切点
* @param controllerLog 日志注解
* @param jsonResult 返回结果
* @param jsonResult 返回结果
*/
@AfterReturning(pointcut = "@annotation(controllerLog)", returning = "jsonResult")
public void doAfterReturning(JoinPoint joinPoint, Log controllerLog, Object jsonResult) {
@@ -73,9 +75,9 @@ public class LogAspect {
/**
* 在目标方法抛出异常后记录操作日志。
*
* @param joinPoint 切点
* @param joinPoint 切点
* @param controllerLog 日志注解
* @param e 异常
* @param e 异常
*/
@AfterThrowing(value = "@annotation(controllerLog)", throwing = "e")
public void doAfterThrowing(JoinPoint joinPoint, Log controllerLog, Exception e) {
@@ -85,35 +87,42 @@ public class LogAspect {
/**
* 组装并发布操作日志事件。
*
* @param joinPoint 切点
* @param joinPoint 切点
* @param controllerLog 日志注解
* @param e 异常信息
* @param jsonResult 返回结果
* @param e 异常信息
* @param jsonResult 返回结果
*/
protected void handleLog(final JoinPoint joinPoint, Log controllerLog, final Exception e, Object jsonResult) {
try {
// *========数据库日志=========*//
OperLogEvent operLog = new OperLogEvent();
operLog.setStatus(BusinessStatus.SUCCESS.ordinal());
// 请求的地址
String ip = ServletUtils.getClientIP();
operLog.setOperIp(ip);
operLog.setOperUrl(StringUtils.substring(ServletUtils.getRequest().getRequestURI(), 0, 255));
LoginUser loginUser = LoginHelper.getLoginUser();
operLog.setOperName(loginUser.getUsername());
operLog.setUsername(loginUser.getUsername());
operLog.setDeptName(loginUser.getDeptName());
operLog.setUserType(loginUser.getUserType());
operLog.setDeviceType(loginUser.getDeviceType());
operLog.setOperIp(ServletUtils.getClientIP());
HttpServletRequest request = ServletUtils.getRequest();
operLog.setOperUrl(StringUtils.substring(request.getRequestURI(), 0, 255));
UserAgent userAgent = UserAgentUtil.parse(request.getHeader("User-Agent"));
operLog.setBrowser(userAgent.getBrowser().getName());
operLog.setOs(userAgent.getOs().getName());
if (e != null) {
operLog.setStatus(BusinessStatus.FAIL.ordinal());
operLog.setErrorMsg(StringUtils.substring(e.getMessage(), 0, 3800));
} else {
operLog.setStatus(BusinessStatus.SUCCESS.ordinal());
}
// 设置方法名称
String className = joinPoint.getTarget().getClass().getName();
String methodName = joinPoint.getSignature().getName();
operLog.setMethod(className + "." + methodName + "()");
// 设置请求方式
operLog.setRequestMethod(ServletUtils.getRequest().getMethod());
operLog.setRequestMethod(request.getMethod());
// 处理设置注解上的参数
getControllerMethodDescription(joinPoint, controllerLog, operLog, jsonResult);
// 设置消耗时间
@@ -133,19 +142,19 @@ public class LogAspect {
/**
* 获取注解中对方法的描述信息 用于Controller层注解
*
* @param joinPoint 切点
* @param log 日志
* @param operLog 操作日志
* @param joinPoint 切点
* @param log 日志
* @param operLog 操作日志
* @param jsonResult 返回结果
* @throws Exception 异常
*/
public void getControllerMethodDescription(JoinPoint joinPoint, Log log, OperLogEvent operLog, Object jsonResult) throws Exception {
// 设置action动作
operLog.setBusinessType(log.businessType().ordinal());
// 设置标题
operLog.setTitle(log.title());
// 设置操作人类别
operLog.setOperatorType(log.operatorType().ordinal());
operLog.setModule(StringUtils.isBlank(log.title()) ? log.module() : log.title());
operLog.setName(log.name());
operLog.setRemark(log.remark());
operLog.setTags(JsonUtils.toJsonString(log.tags()));
operLog.setBusinessType(log.businessType().getCode());
operLog.setChannel(log.channel().getCode());
// 是否需要保存request参数和值
if (log.isSaveRequestData()) {
// 获取参数的信息,传入到数据库中。
@@ -160,8 +169,8 @@ public class LogAspect {
/**
* 获取请求的参数放到log中
*
* @param joinPoint 切点
* @param operLog 操作日志
* @param joinPoint 切点
* @param operLog 操作日志
* @param excludeParamNames 排除参数名
* @throws Exception 异常
*/
@@ -181,7 +190,7 @@ public class LogAspect {
/**
* 将方法参数序列化为日志字符串。
*
* @param paramsArray 参数数组
* @param paramsArray 参数数组
* @param excludeParamNames 排除字段名
* @return 参数字符串
*/
@@ -242,6 +251,6 @@ public class LogAspect {
}
}
return o instanceof MultipartFile || o instanceof HttpServletRequest || o instanceof HttpServletResponse
|| o instanceof BindingResult;
|| o instanceof BindingResult;
}
}

View File

@@ -1,58 +1,195 @@
package org.dromara.common.log.enums;
import lombok.AllArgsConstructor;
import lombok.Getter;
/**
* 业务操作类型
*
* @author ruoyi
* @author AprilWind
*/
@Getter
@AllArgsConstructor
public enum BusinessType {
/**
* 其它
* 其它操作
*/
OTHER,
OTHER(0, "其它操作"),
/**
* 查询
*/
QUERY(1, "查询"),
/**
* 新增
*/
INSERT,
INSERT(2, "新增"),
/**
* 修改
*/
UPDATE,
UPDATE(3, "修改"),
/**
* 删除
*/
DELETE,
/**
* 授权
*/
GRANT,
/**
* 导出
*/
EXPORT,
DELETE(4, "删除"),
/**
* 导入
*/
IMPORT,
IMPORT(5, "导入"),
/**
* 强退
* 导出
*/
FORCE,
EXPORT(6, "导出"),
/**
* 生成代码
* 授权/赋权
*/
GENCODE,
GRANT(7, "授权"),
/**
* 清空数据
*/
CLEAN,
CLEAN(8, "清空数据"),
/**
* 强制退出(用户登出)
*/
FORCE_LOGOUT(9, "强制退出"),
/**
* 状态修改(启用/禁用/冻结/解冻)
*/
CHANGE_STATUS(10, "状态修改"),
/**
* 重置密码
*/
RESET_PASSWORD(11, "重置密码"),
/**
* 批量删除
*/
BATCH_DELETE(12, "批量删除"),
/**
* 批量导入
*/
BATCH_IMPORT(13, "批量导入"),
/**
* 批量导出
*/
BATCH_EXPORT(14, "批量导出"),
/**
* 批量操作(通用)
*/
BATCH_OPERATE(15, "批量操作"),
/**
* 审核操作(通过/驳回)
*/
AUDIT(16, "审核"),
/**
* 发布/上线
*/
PUBLISH(17, "发布"),
/**
* 撤回/下线
*/
REVOKE(18, "撤回"),
/**
* 同步数据
*/
SYNC(19, "同步数据"),
/**
* 生成数据(生成编码、生成报表等)
*/
GENERATE(20, "生成数据"),
/**
* 上传文件
*/
UPLOAD(21, "上传文件"),
/**
* 下载文件
*/
DOWNLOAD(22, "下载文件"),
/**
* 定时任务执行
*/
TASK_EXECUTE(23, "定时任务执行"),
/**
* 接口调用(第三方/开放API
*/
API_CALL(24, "接口调用"),
/**
* 登录
*/
LOGIN(25, "登录"),
/**
* 登出
*/
LOGOUT(26, "登出"),
/**
* 注册
*/
REGISTER(27, "注册"),
/**
* 作废/取消
*/
CANCEL(28, "作废/取消"),
/**
* 归档
*/
ARCHIVE(29, "归档"),
/**
* 配置修改
*/
CONFIG_UPDATE(30, "配置修改"),
/**
* 打印单据/报表
*/
PRINT(31, "打印"),
/**
* 复制数据/克隆
*/
COPY(32, "复制"),
/**
* 生成代码
*/
GENCODE(33, "生成代码");
/**
* 业务类型编码
*/
private final Integer code;
/**
* 业务类型描述
*/
private final String desc;
}

View File

@@ -0,0 +1,54 @@
package org.dromara.common.log.enums;
import lombok.AllArgsConstructor;
import lombok.Getter;
/**
* 操作渠道
*
* @author AprilWind
*/
@Getter
@AllArgsConstructor
public enum OperateChannel {
/**
* 管理后台
*/
WEB(0, "管理后台"),
/**
* 移动端APP
*/
APP(1, "移动端APP"),
/**
* 小程序
*/
MINI_APP(2, "小程序"),
/**
* 开放接口
*/
OPEN_API(3, "开放接口"),
/**
* 定时任务
*/
TASK(4, "定时任务"),
/**
* 第三方调用
*/
THIRD(5, "第三方调用");
/**
* 操作渠道编码
*/
private final Integer code;
/**
* 操作渠道描述
*/
private final String desc;
}

View File

@@ -1,23 +0,0 @@
package org.dromara.common.log.enums;
/**
* 操作人类别
*
* @author ruoyi
*/
public enum OperatorType {
/**
* 其它
*/
OTHER,
/**
* 后台用户
*/
MANAGE,
/**
* 手机端用户
*/
MOBILE
}

View File

@@ -11,7 +11,6 @@ import java.time.LocalDateTime;
*
* @author Lion Li
*/
@Data
public class OperLogEvent implements Serializable {
@@ -19,24 +18,34 @@ public class OperLogEvent implements Serializable {
private static final long serialVersionUID = 1L;
/**
* 日志主键
* 业务模块名称
*/
private Long operId;
private String module;
/**
* 操作模块
* 操作功能名称
*/
private String title;
private String name;
/**
* 业务类型0其它 1新增 2修改 3删除
* 操作描述(备注
*/
private String remark;
/**
* 标签(用于检索/分类)
*/
private String tags;
/**
* 业务类型
*/
private Integer businessType;
/**
* 业务类型数组
* 操作渠道
*/
private Integer[] businessTypes;
private Integer channel;
/**
* 请求方法
@@ -49,20 +58,20 @@ public class OperLogEvent implements Serializable {
private String requestMethod;
/**
* 操作类别0其它 1后台用户 2手机端用户
* 用户名
*/
private Integer operatorType;
/**
* 操作人员
*/
private String operName;
private String username;
/**
* 部门名称
*/
private String deptName;
/**
* 用户类型
*/
private String userType;
/**
* 请求url
*/
@@ -74,9 +83,19 @@ public class OperLogEvent implements Serializable {
private String operIp;
/**
* 操作地点
* 设备类型
*/
private String operLocation;
private String deviceType;
/**
* 浏览器类型
*/
private String browser;
/**
* 操作系统
*/
private String os;
/**
* 请求参数