From e68d4f54f73dd853e69b6c20dee20c29e4ef69c5 Mon Sep 17 00:00:00 2001 From: YunaiV Date: Mon, 13 Jun 2022 23:05:13 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BC=98=E5=8C=96=20yudao-spring-boot-starter-?= =?UTF-8?q?biz-operatelog=20=E7=9A=84=E5=B0=81=E8=A3=85=EF=BC=8C=E5=92=8C?= =?UTF-8?q?=20yudao-cloud=20=E4=BF=9D=E6=8C=81=E4=B8=80=E8=87=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../pom.xml | 7 + .../YudaoOperateLogAutoConfiguration.java | 8 ++ .../operatelog/core/aop/OperateLogAspect.java | 121 +++++++++-------- .../core/dto/OperateLogCreateReqDTO.java | 87 ------------- .../operatelog/core/service/OperateLog.java | 110 ++++++++++++++++ .../service/OperateLogFrameworkService.java | 16 +-- .../OperateLogFrameworkServiceImpl.java | 28 ++++ .../system/api/logger/OperateLogApi.java | 21 +++ .../logger/dto/OperateLogCreateReqDTO.java | 123 ++++++++++++++++++ .../system/api/logger/OperateLogApiImpl.java | 27 ++++ .../admin/sms/SmsTemplateController.http | 3 +- .../convert/logger/OperateLogConvert.java | 2 +- .../service/logger/OperateLogService.java | 13 +- .../service/logger/OperateLogServiceImpl.java | 23 +--- .../logger/OperateLogServiceImplTest.java | 11 +- 15 files changed, 423 insertions(+), 177 deletions(-) delete mode 100644 yudao-framework/yudao-spring-boot-starter-biz-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelog/core/dto/OperateLogCreateReqDTO.java create mode 100644 yudao-framework/yudao-spring-boot-starter-biz-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelog/core/service/OperateLog.java create mode 100644 yudao-framework/yudao-spring-boot-starter-biz-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelog/core/service/OperateLogFrameworkServiceImpl.java create mode 100644 yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/logger/OperateLogApi.java create mode 100644 yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/logger/dto/OperateLogCreateReqDTO.java create mode 100644 yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/api/logger/OperateLogApiImpl.java diff --git a/yudao-framework/yudao-spring-boot-starter-biz-operatelog/pom.xml b/yudao-framework/yudao-spring-boot-starter-biz-operatelog/pom.xml index a35c51365..01deef06f 100644 --- a/yudao-framework/yudao-spring-boot-starter-biz-operatelog/pom.xml +++ b/yudao-framework/yudao-spring-boot-starter-biz-operatelog/pom.xml @@ -34,6 +34,13 @@ provided + + + cn.iocoder.boot + yudao-module-system-api + ${revision} + + com.google.guava diff --git a/yudao-framework/yudao-spring-boot-starter-biz-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelog/config/YudaoOperateLogAutoConfiguration.java b/yudao-framework/yudao-spring-boot-starter-biz-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelog/config/YudaoOperateLogAutoConfiguration.java index c4e784bf0..bd78d2464 100644 --- a/yudao-framework/yudao-spring-boot-starter-biz-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelog/config/YudaoOperateLogAutoConfiguration.java +++ b/yudao-framework/yudao-spring-boot-starter-biz-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelog/config/YudaoOperateLogAutoConfiguration.java @@ -1,6 +1,9 @@ package cn.iocoder.yudao.framework.operatelog.config; import cn.iocoder.yudao.framework.operatelog.core.aop.OperateLogAspect; +import cn.iocoder.yudao.framework.operatelog.core.service.OperateLogFrameworkService; +import cn.iocoder.yudao.framework.operatelog.core.service.OperateLogFrameworkServiceImpl; +import cn.iocoder.yudao.module.system.api.logger.OperateLogApi; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @@ -12,4 +15,9 @@ public class YudaoOperateLogAutoConfiguration { return new OperateLogAspect(); } + @Bean + public OperateLogFrameworkService operateLogFrameworkService(OperateLogApi operateLogApi) { + return new OperateLogFrameworkServiceImpl(operateLogApi); + } + } diff --git a/yudao-framework/yudao-spring-boot-starter-biz-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelog/core/aop/OperateLogAspect.java b/yudao-framework/yudao-spring-boot-starter-biz-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelog/core/aop/OperateLogAspect.java index ee26efbb2..05c45f0f5 100644 --- a/yudao-framework/yudao-spring-boot-starter-biz-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelog/core/aop/OperateLogAspect.java +++ b/yudao-framework/yudao-spring-boot-starter-biz-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelog/core/aop/OperateLogAspect.java @@ -9,9 +9,8 @@ import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.framework.common.util.json.JsonUtils; import cn.iocoder.yudao.framework.common.util.monitor.TracerUtils; import cn.iocoder.yudao.framework.common.util.servlet.ServletUtils; -import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog; -import cn.iocoder.yudao.framework.operatelog.core.dto.OperateLogCreateReqDTO; import cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum; +import cn.iocoder.yudao.framework.operatelog.core.service.OperateLog; import cn.iocoder.yudao.framework.operatelog.core.service.OperateLogFrameworkService; import cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils; import com.google.common.collect.Maps; @@ -57,13 +56,13 @@ public class OperateLogAspect { /** * 用于记录操作内容的上下文 * - * @see OperateLogCreateReqDTO#getContent() + * @see OperateLog#getContent() */ private static final ThreadLocal CONTENT = new ThreadLocal<>(); /** * 用于记录拓展字段的上下文 * - * @see OperateLogCreateReqDTO#getExts() + * @see OperateLog#getExts() */ private static final ThreadLocal> EXTS = new ThreadLocal<>(); @@ -73,16 +72,20 @@ public class OperateLogAspect { @Around("@annotation(apiOperation)") public Object around(ProceedingJoinPoint joinPoint, ApiOperation apiOperation) throws Throwable { // 可能也添加了 @ApiOperation 注解 - OperateLog operateLog = getMethodAnnotation(joinPoint, OperateLog.class); + cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog operateLog = getMethodAnnotation(joinPoint, + cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog.class); return around0(joinPoint, operateLog, apiOperation); } @Around("!@annotation(io.swagger.annotations.ApiOperation) && @annotation(operateLog)") // 兼容处理,只添加 @OperateLog 注解的情况 - public Object around(ProceedingJoinPoint joinPoint, OperateLog operateLog) throws Throwable { + public Object around(ProceedingJoinPoint joinPoint, + cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog operateLog) throws Throwable { return around0(joinPoint, operateLog, null); } - private Object around0(ProceedingJoinPoint joinPoint, OperateLog operateLog, ApiOperation apiOperation) throws Throwable { + private Object around0(ProceedingJoinPoint joinPoint, + cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog operateLog, + ApiOperation apiOperation) throws Throwable { // 目前,只有管理员,才记录操作日志!所以非管理员,直接调用,不进行记录 Integer userType = WebFrameworkUtils.getLoginUserType(); if (!Objects.equals(userType, UserTypeEnum.ADMIN.getValue())) { @@ -121,7 +124,9 @@ public class OperateLogAspect { EXTS.remove(); } - private void log(ProceedingJoinPoint joinPoint, OperateLog operateLog, ApiOperation apiOperation, + private void log(ProceedingJoinPoint joinPoint, + cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog operateLog, + ApiOperation apiOperation, Date startTime, Object result, Throwable exception) { try { // 判断不记录的情况 @@ -136,113 +141,119 @@ public class OperateLogAspect { } } - private void log0(ProceedingJoinPoint joinPoint, OperateLog operateLog, ApiOperation apiOperation, + private void log0(ProceedingJoinPoint joinPoint, + cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog operateLog, + ApiOperation apiOperation, Date startTime, Object result, Throwable exception) { - OperateLogCreateReqDTO operateLogDTO = new OperateLogCreateReqDTO(); + OperateLog operateLogObj = new OperateLog(); // 补全通用字段 - operateLogDTO.setTraceId(TracerUtils.getTraceId()); - operateLogDTO.setStartTime(startTime); + operateLogObj.setTraceId(TracerUtils.getTraceId()); + operateLogObj.setStartTime(startTime); // 补充用户信息 - fillUserFields(operateLogDTO); + fillUserFields(operateLogObj); // 补全模块信息 - fillModuleFields(operateLogDTO, joinPoint, operateLog, apiOperation); + fillModuleFields(operateLogObj, joinPoint, operateLog, apiOperation); // 补全请求信息 - fillRequestFields(operateLogDTO); + fillRequestFields(operateLogObj); // 补全方法信息 - fillMethodFields(operateLogDTO, joinPoint, operateLog, startTime, result, exception); + fillMethodFields(operateLogObj, joinPoint, operateLog, startTime, result, exception); // 异步记录日志 - operateLogFrameworkService.createOperateLogAsync(operateLogDTO); + operateLogFrameworkService.createOperateLog(operateLogObj); } - private static void fillUserFields(OperateLogCreateReqDTO operateLogDTO) { - operateLogDTO.setUserId(WebFrameworkUtils.getLoginUserId()); - operateLogDTO.setUserType(WebFrameworkUtils.getLoginUserType()); + private static void fillUserFields(OperateLog operateLogObj) { + operateLogObj.setUserId(WebFrameworkUtils.getLoginUserId()); + operateLogObj.setUserType(WebFrameworkUtils.getLoginUserType()); } - private static void fillModuleFields(OperateLogCreateReqDTO operateLogDTO, - ProceedingJoinPoint joinPoint, OperateLog operateLog, ApiOperation apiOperation) { + private static void fillModuleFields(OperateLog operateLogObj, + ProceedingJoinPoint joinPoint, + cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog operateLog, + ApiOperation apiOperation) { // module 属性 if (operateLog != null) { - operateLogDTO.setModule(operateLog.module()); + operateLogObj.setModule(operateLog.module()); } - if (StrUtil.isEmpty(operateLogDTO.getModule())) { + if (StrUtil.isEmpty(operateLogObj.getModule())) { Api api = getClassAnnotation(joinPoint, Api.class); if (api != null) { // 优先读取 @API 的 name 属性 if (StrUtil.isNotEmpty(api.value())) { - operateLogDTO.setModule(api.value()); + operateLogObj.setModule(api.value()); } // 没有的话,读取 @API 的 tags 属性 - if (StrUtil.isEmpty(operateLogDTO.getModule()) && ArrayUtil.isNotEmpty(api.tags())) { - operateLogDTO.setModule(api.tags()[0]); + if (StrUtil.isEmpty(operateLogObj.getModule()) && ArrayUtil.isNotEmpty(api.tags())) { + operateLogObj.setModule(api.tags()[0]); } } } // name 属性 if (operateLog != null) { - operateLogDTO.setName(operateLog.name()); + operateLogObj.setName(operateLog.name()); } - if (StrUtil.isEmpty(operateLogDTO.getName()) && apiOperation != null) { - operateLogDTO.setName(apiOperation.value()); + if (StrUtil.isEmpty(operateLogObj.getName()) && apiOperation != null) { + operateLogObj.setName(apiOperation.value()); } // type 属性 if (operateLog != null && ArrayUtil.isNotEmpty(operateLog.type())) { - operateLogDTO.setType(operateLog.type()[0].getType()); + operateLogObj.setType(operateLog.type()[0].getType()); } - if (operateLogDTO.getType() == null) { + if (operateLogObj.getType() == null) { RequestMethod requestMethod = obtainFirstMatchRequestMethod(obtainRequestMethod(joinPoint)); OperateTypeEnum operateLogType = convertOperateLogType(requestMethod); - operateLogDTO.setType(operateLogType != null ? operateLogType.getType() : null); + operateLogObj.setType(operateLogType != null ? operateLogType.getType() : null); } // content 和 exts 属性 - operateLogDTO.setContent(CONTENT.get()); - operateLogDTO.setExts(EXTS.get()); + operateLogObj.setContent(CONTENT.get()); + operateLogObj.setExts(EXTS.get()); } - private static void fillRequestFields(OperateLogCreateReqDTO operateLogDTO) { + private static void fillRequestFields(OperateLog operateLogObj) { // 获得 Request 对象 HttpServletRequest request = ServletUtils.getRequest(); if (request == null) { return; } // 补全请求信息 - operateLogDTO.setRequestMethod(request.getMethod()); - operateLogDTO.setRequestUrl(request.getRequestURI()); - operateLogDTO.setUserIp(ServletUtil.getClientIP(request)); - operateLogDTO.setUserAgent(ServletUtils.getUserAgent(request)); + operateLogObj.setRequestMethod(request.getMethod()); + operateLogObj.setRequestUrl(request.getRequestURI()); + operateLogObj.setUserIp(ServletUtil.getClientIP(request)); + operateLogObj.setUserAgent(ServletUtils.getUserAgent(request)); } - private static void fillMethodFields(OperateLogCreateReqDTO operateLogDTO, - ProceedingJoinPoint joinPoint, OperateLog operateLog, + private static void fillMethodFields(OperateLog operateLogObj, + ProceedingJoinPoint joinPoint, + cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog operateLog, Date startTime, Object result, Throwable exception) { MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature(); - operateLogDTO.setJavaMethod(methodSignature.toString()); + operateLogObj.setJavaMethod(methodSignature.toString()); if (operateLog == null || operateLog.logArgs()) { - operateLogDTO.setJavaMethodArgs(obtainMethodArgs(joinPoint)); + operateLogObj.setJavaMethodArgs(obtainMethodArgs(joinPoint)); } if (operateLog == null || operateLog.logResultData()) { - operateLogDTO.setResultData(obtainResultData(result)); + operateLogObj.setResultData(obtainResultData(result)); } - operateLogDTO.setDuration((int) (System.currentTimeMillis() - startTime.getTime())); + operateLogObj.setDuration((int) (System.currentTimeMillis() - startTime.getTime())); // (正常)处理 resultCode 和 resultMsg 字段 if (result != null) { if (result instanceof CommonResult) { CommonResult commonResult = (CommonResult) result; - operateLogDTO.setResultCode(commonResult.getCode()); - operateLogDTO.setResultMsg(commonResult.getMsg()); + operateLogObj.setResultCode(commonResult.getCode()); + operateLogObj.setResultMsg(commonResult.getMsg()); } else { - operateLogDTO.setResultCode(SUCCESS.getCode()); + operateLogObj.setResultCode(SUCCESS.getCode()); } } // (异常)处理 resultCode 和 resultMsg 字段 if (exception != null) { - operateLogDTO.setResultCode(INTERNAL_SERVER_ERROR.getCode()); - operateLogDTO.setResultMsg(ExceptionUtil.getRootCauseMessage(exception)); + operateLogObj.setResultCode(INTERNAL_SERVER_ERROR.getCode()); + operateLogObj.setResultMsg(ExceptionUtil.getRootCauseMessage(exception)); } } - private static boolean isLogEnable(ProceedingJoinPoint joinPoint, OperateLog operateLog) { + private static boolean isLogEnable(ProceedingJoinPoint joinPoint, + cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog operateLog) { // 有 @OperateLog 注解的情况下 if (operateLog != null) { return operateLog.enable(); @@ -256,9 +267,9 @@ public class OperateLogAspect { return null; } return Arrays.stream(requestMethods).filter(requestMethod -> - requestMethod == RequestMethod.POST - || requestMethod == RequestMethod.PUT - || requestMethod == RequestMethod.DELETE) + requestMethod == RequestMethod.POST + || requestMethod == RequestMethod.PUT + || requestMethod == RequestMethod.DELETE) .findFirst().orElse(null); } diff --git a/yudao-framework/yudao-spring-boot-starter-biz-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelog/core/dto/OperateLogCreateReqDTO.java b/yudao-framework/yudao-spring-boot-starter-biz-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelog/core/dto/OperateLogCreateReqDTO.java deleted file mode 100644 index d676001f2..000000000 --- a/yudao-framework/yudao-spring-boot-starter-biz-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelog/core/dto/OperateLogCreateReqDTO.java +++ /dev/null @@ -1,87 +0,0 @@ -package cn.iocoder.yudao.framework.operatelog.core.dto; - -import io.swagger.annotations.ApiModelProperty; -import lombok.Data; - -import javax.validation.constraints.NotEmpty; -import javax.validation.constraints.NotNull; -import java.util.Date; -import java.util.Map; - -/** - * 操作日志创建 Request DTO - */ -@Data -public class OperateLogCreateReqDTO { - - @ApiModelProperty(value = "链路追踪编号", required = true, example = "89aca178-a370-411c-ae02-3f0d672be4ab") - @NotEmpty(message = "链路追踪编号不能为空") - private String traceId; - - @ApiModelProperty(value = "用户编号", required = true, example = "1024") - @NotNull(message = "用户编号不能为空") - private Long userId; - @ApiModelProperty(value = "用户类型", required = true, example = "1") - @NotNull(message = "用户类型不能为空") - private Integer userType; - - @ApiModelProperty(value = "操作模块", required = true, example = "订单") - @NotEmpty(message = "操作模块不能为空") - private String module; - - @ApiModelProperty(value = "操作名", required = true, example = "创建订单") - @NotEmpty(message = "操作名") - private String name; - - @ApiModelProperty(value = "操作分类", required = true, example = "1", notes = "参见 SysOperateLogTypeEnum 枚举类") - @NotNull(message = "操作分类不能为空") - private Integer type; - - @ApiModelProperty(value = "操作明细", example = "修改编号为 1 的用户信息,将性别从男改成女,将姓名从芋道改成源码。") - private String content; - - @ApiModelProperty(value = "拓展字段", example = "{'orderId': 1}") - private Map exts; - - @ApiModelProperty(value = "请求方法名", required = true, example = "GET") - @NotEmpty(message = "请求方法名不能为空") - private String requestMethod; - - @ApiModelProperty(value = "请求地址", required = true, example = "/xxx/yyy") - @NotEmpty(message = "请求地址不能为空") - private String requestUrl; - - @ApiModelProperty(value = "用户 IP", required = true, example = "127.0.0.1") - @NotEmpty(message = "用户 IP 不能为空") - private String userIp; - - @ApiModelProperty(value = "浏览器 UserAgent", required = true, example = "Mozilla/5.0") - @NotEmpty(message = "浏览器 UserAgent 不能为空") - private String userAgent; - - @ApiModelProperty(value = "Java 方法名", required = true, example = "cn.iocoder.yudao.UserController.save(...)") - @NotEmpty(message = "Java 方法名不能为空") - private String javaMethod; - - @ApiModelProperty(value = "Java 方法的参数") - private String javaMethodArgs; - - @ApiModelProperty(value = "开始时间", required = true) - @NotNull(message = "开始时间不能为空") - private Date startTime; - - @ApiModelProperty(value = "执行时长,单位:毫秒", required = true) - @NotNull(message = "执行时长不能为空") - private Integer duration; - - @ApiModelProperty(value = "结果码", required = true) - @NotNull(message = "结果码不能为空") - private Integer resultCode; - - @ApiModelProperty(value = "结果提示") - private String resultMsg; - - @ApiModelProperty(value = "结果数据") - private String resultData; - -} diff --git a/yudao-framework/yudao-spring-boot-starter-biz-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelog/core/service/OperateLog.java b/yudao-framework/yudao-spring-boot-starter-biz-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelog/core/service/OperateLog.java new file mode 100644 index 000000000..7bce1c6bd --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-biz-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelog/core/service/OperateLog.java @@ -0,0 +1,110 @@ +package cn.iocoder.yudao.framework.operatelog.core.service; + +import lombok.Data; + +import java.util.Date; +import java.util.Map; + +/** + * 操作日志 + * + * @author 芋道源码 + */ +@Data +public class OperateLog { + + /** + * 链路追踪编号 + */ + private String traceId; + + /** + * 用户编号 + */ + private Long userId; + /** + * 用户类型 + */ + private Integer userType; + + /** + * 操作模块 + */ + private String module; + + /** + * 操作名 + */ + private String name; + + /** + * 操作分类 + */ + private Integer type; + + /** + * 操作明细 + */ + private String content; + + /** + * 拓展字段 + */ + private Map exts; + + /** + * 请求方法名 + */ + private String requestMethod; + + /** + * 请求地址 + */ + private String requestUrl; + + /** + * 用户 IP + */ + private String userIp; + + /** + * 浏览器 UserAgent + */ + private String userAgent; + + /** + * Java 方法名 + */ + private String javaMethod; + + /** + * Java 方法的参数 + */ + private String javaMethodArgs; + + /** + * 开始时间 + */ + private Date startTime; + + /** + * 执行时长,单位:毫秒 + */ + private Integer duration; + + /** + * 结果码 + */ + private Integer resultCode; + + /** + * 结果提示 + */ + private String resultMsg; + + /** + * 结果数据 + */ + private String resultData; + +} diff --git a/yudao-framework/yudao-spring-boot-starter-biz-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelog/core/service/OperateLogFrameworkService.java b/yudao-framework/yudao-spring-boot-starter-biz-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelog/core/service/OperateLogFrameworkService.java index ef20e2ece..235616244 100644 --- a/yudao-framework/yudao-spring-boot-starter-biz-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelog/core/service/OperateLogFrameworkService.java +++ b/yudao-framework/yudao-spring-boot-starter-biz-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelog/core/service/OperateLogFrameworkService.java @@ -1,17 +1,17 @@ package cn.iocoder.yudao.framework.operatelog.core.service; -import cn.iocoder.yudao.framework.operatelog.core.dto.OperateLogCreateReqDTO; - -import java.util.concurrent.Future; - +/** + * 操作日志 Framework Service 接口 + * + * @author 芋道源码 + */ public interface OperateLogFrameworkService { /** - * 异步记录操作日志 + * 记录操作日志 * - * @param reqVO 操作日志请求 - * @return true: 记录成功,false: 记录失败 + * @param operateLog 操作日志请求 */ - Future createOperateLogAsync(OperateLogCreateReqDTO reqVO); + void createOperateLog(OperateLog operateLog); } diff --git a/yudao-framework/yudao-spring-boot-starter-biz-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelog/core/service/OperateLogFrameworkServiceImpl.java b/yudao-framework/yudao-spring-boot-starter-biz-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelog/core/service/OperateLogFrameworkServiceImpl.java new file mode 100644 index 000000000..a636c4bdf --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-biz-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelog/core/service/OperateLogFrameworkServiceImpl.java @@ -0,0 +1,28 @@ +package cn.iocoder.yudao.framework.operatelog.core.service; + +import cn.hutool.core.bean.BeanUtil; +import cn.iocoder.yudao.module.system.api.logger.OperateLogApi; +import cn.iocoder.yudao.module.system.api.logger.dto.OperateLogCreateReqDTO; +import lombok.RequiredArgsConstructor; +import org.springframework.scheduling.annotation.Async; + +/** + * 操作日志 Framework Service 实现类 + * + * 基于 {@link OperateLogApi} 实现,记录操作日志 + * + * @author 芋道源码 + */ +@RequiredArgsConstructor +public class OperateLogFrameworkServiceImpl implements OperateLogFrameworkService { + + private final OperateLogApi operateLogApi; + + @Override + @Async + public void createOperateLog(OperateLog operateLog) { + OperateLogCreateReqDTO reqDTO = BeanUtil.copyProperties(operateLog, OperateLogCreateReqDTO.class); + operateLogApi.createOperateLog(reqDTO); + } + +} diff --git a/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/logger/OperateLogApi.java b/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/logger/OperateLogApi.java new file mode 100644 index 000000000..802cc0a2b --- /dev/null +++ b/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/logger/OperateLogApi.java @@ -0,0 +1,21 @@ +package cn.iocoder.yudao.module.system.api.logger; + +import cn.iocoder.yudao.module.system.api.logger.dto.OperateLogCreateReqDTO; + +import javax.validation.Valid; + +/** + * 操作日志 API 接口 + * + * @author 芋道源码 + */ +public interface OperateLogApi { + + /** + * 创建操作日志 + * + * @param createReqDTO 请求 + */ + void createOperateLog(@Valid OperateLogCreateReqDTO createReqDTO); + +} diff --git a/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/logger/dto/OperateLogCreateReqDTO.java b/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/logger/dto/OperateLogCreateReqDTO.java new file mode 100644 index 000000000..80161f77f --- /dev/null +++ b/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/logger/dto/OperateLogCreateReqDTO.java @@ -0,0 +1,123 @@ +package cn.iocoder.yudao.module.system.api.logger.dto; + +import lombok.Data; + +import javax.validation.constraints.NotEmpty; +import javax.validation.constraints.NotNull; +import java.util.Date; +import java.util.Map; + +/** + * 操作日志创建 Request DTO + */ +@Data +public class OperateLogCreateReqDTO { + + /** + * 链路追踪编号 + */ + private String traceId; + + /** + * 用户编号 + */ + @NotNull(message = "用户编号不能为空") + private Long userId; + /** + * 用户类型 + */ + @NotNull(message = "用户类型不能为空") + private Integer userType; + + /** + * 操作模块 + */ + @NotEmpty(message = "操作模块不能为空") + private String module; + + /** + * 操作名 + */ + @NotEmpty(message = "操作名") + private String name; + + /** + * 操作分类 + */ + @NotNull(message = "操作分类不能为空") + private Integer type; + + /** + * 操作明细 + */ + private String content; + + /** + * 拓展字段 + */ + private Map exts; + + /** + * 请求方法名 + */ + @NotEmpty(message = "请求方法名不能为空") + private String requestMethod; + + /** + * 请求地址 + */ + @NotEmpty(message = "请求地址不能为空") + private String requestUrl; + + /** + * 用户 IP + */ + @NotEmpty(message = "用户 IP 不能为空") + private String userIp; + + /** + * 浏览器 UserAgent + */ + @NotEmpty(message = "浏览器 UserAgent 不能为空") + private String userAgent; + + /** + * Java 方法名 + */ + @NotEmpty(message = "Java 方法名不能为空") + private String javaMethod; + + /** + * Java 方法的参数 + */ + private String javaMethodArgs; + + /** + * 开始时间 + */ + @NotNull(message = "开始时间不能为空") + private Date startTime; + + /** + * 执行时长,单位:毫秒 + */ + @NotNull(message = "执行时长不能为空") + private Integer duration; + + /** + * 结果码 + */ + @NotNull(message = "结果码不能为空") + private Integer resultCode; + + /** + * 结果提示 + */ + private String resultMsg; + + /** + * 结果数据 + */ + private String resultData; + +} diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/api/logger/OperateLogApiImpl.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/api/logger/OperateLogApiImpl.java new file mode 100644 index 000000000..186f1e098 --- /dev/null +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/api/logger/OperateLogApiImpl.java @@ -0,0 +1,27 @@ +package cn.iocoder.yudao.module.system.api.logger; + +import cn.iocoder.yudao.module.system.api.logger.dto.OperateLogCreateReqDTO; +import cn.iocoder.yudao.module.system.service.logger.OperateLogService; +import org.springframework.stereotype.Service; +import org.springframework.validation.annotation.Validated; + +import javax.annotation.Resource; + +/** + * 操作日志 API 实现类 + * + * @author 芋道源码 + */ +@Service +@Validated +public class OperateLogApiImpl implements OperateLogApi { + + @Resource + private OperateLogService operateLogService; + + @Override + public void createOperateLog(OperateLogCreateReqDTO createReqDTO) { + operateLogService.createOperateLog(createReqDTO); + } + +} diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sms/SmsTemplateController.http b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sms/SmsTemplateController.http index 3bf59d965..e8213e5cd 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sms/SmsTemplateController.http +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sms/SmsTemplateController.http @@ -5,7 +5,8 @@ Content-Type: application/json tenant-id: {{adminTenentId}} { - "code": "test_01", + "templateCode": "test_01", + "mobile": "156016913900", "params": { "key01": "value01", "key02": "value02" diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/convert/logger/OperateLogConvert.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/convert/logger/OperateLogConvert.java index 21f7a4948..e32ebd091 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/convert/logger/OperateLogConvert.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/convert/logger/OperateLogConvert.java @@ -6,7 +6,7 @@ import cn.iocoder.yudao.module.system.dal.dataobject.logger.OperateLogDO; import cn.iocoder.yudao.module.system.dal.dataobject.user.AdminUserDO; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.util.collection.MapUtils; -import cn.iocoder.yudao.framework.operatelog.core.dto.OperateLogCreateReqDTO; +import cn.iocoder.yudao.module.system.api.logger.dto.OperateLogCreateReqDTO; import org.mapstruct.Mapper; import org.mapstruct.factory.Mappers; diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/logger/OperateLogService.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/logger/OperateLogService.java index 4ec2d8f01..224a83f19 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/logger/OperateLogService.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/logger/OperateLogService.java @@ -1,7 +1,9 @@ package cn.iocoder.yudao.module.system.service.logger; import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.operatelog.core.service.OperateLog; import cn.iocoder.yudao.framework.operatelog.core.service.OperateLogFrameworkService; +import cn.iocoder.yudao.module.system.api.logger.dto.OperateLogCreateReqDTO; import cn.iocoder.yudao.module.system.controller.admin.logger.vo.operatelog.OperateLogExportReqVO; import cn.iocoder.yudao.module.system.controller.admin.logger.vo.operatelog.OperateLogPageReqVO; import cn.iocoder.yudao.module.system.dal.dataobject.logger.OperateLogDO; @@ -10,8 +12,17 @@ import java.util.List; /** * 操作日志 Service 接口 + * + * @author 芋道源码 */ -public interface OperateLogService extends OperateLogFrameworkService { +public interface OperateLogService { + + /** + * 记录操作日志 + * + * @param createReqDTO 操作日志请求 + */ + void createOperateLog(OperateLogCreateReqDTO createReqDTO); /** * 获得操作日志分页列表 diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/logger/OperateLogServiceImpl.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/logger/OperateLogServiceImpl.java index 48f1b5b15..8ae3d139b 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/logger/OperateLogServiceImpl.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/logger/OperateLogServiceImpl.java @@ -4,7 +4,7 @@ import cn.hutool.core.collection.CollUtil; import cn.hutool.core.util.StrUtil; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.util.string.StrUtils; -import cn.iocoder.yudao.framework.operatelog.core.dto.OperateLogCreateReqDTO; +import cn.iocoder.yudao.module.system.api.logger.dto.OperateLogCreateReqDTO; import cn.iocoder.yudao.module.system.controller.admin.logger.vo.operatelog.OperateLogExportReqVO; import cn.iocoder.yudao.module.system.controller.admin.logger.vo.operatelog.OperateLogPageReqVO; import cn.iocoder.yudao.module.system.convert.logger.OperateLogConvert; @@ -13,8 +13,6 @@ import cn.iocoder.yudao.module.system.dal.dataobject.user.AdminUserDO; import cn.iocoder.yudao.module.system.dal.mysql.logger.OperateLogMapper; import cn.iocoder.yudao.module.system.service.user.AdminUserService; import lombok.extern.slf4j.Slf4j; -import org.springframework.scheduling.annotation.Async; -import org.springframework.scheduling.annotation.AsyncResult; import org.springframework.stereotype.Service; import org.springframework.validation.annotation.Validated; @@ -22,7 +20,6 @@ import javax.annotation.Resource; import java.util.Collection; import java.util.Collections; import java.util.List; -import java.util.concurrent.Future; import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; import static cn.iocoder.yudao.module.system.dal.dataobject.logger.OperateLogDO.JAVA_METHOD_ARGS_MAX_LENGTH; @@ -40,19 +37,11 @@ public class OperateLogServiceImpl implements OperateLogService { private AdminUserService userService; @Override - @Async - public Future createOperateLogAsync(OperateLogCreateReqDTO reqVO) { - boolean success = false; - try { - OperateLogDO logDO = OperateLogConvert.INSTANCE.convert(reqVO); - logDO.setJavaMethodArgs(StrUtils.maxLength(logDO.getJavaMethodArgs(), JAVA_METHOD_ARGS_MAX_LENGTH)); - logDO.setResultData(StrUtils.maxLength(logDO.getResultData(), RESULT_MAX_LENGTH)); - success = operateLogMapper.insert(logDO) == 1; - } catch (Throwable throwable) { - // 仅仅打印日志,不对外抛出。原因是,还是要保留现场数据。 - log.error("[createOperateLogAsync][记录操作日志异常,日志为 ({})]", reqVO, throwable); - } - return new AsyncResult<>(success); + public void createOperateLog(OperateLogCreateReqDTO createReqDTO) { + OperateLogDO logDO = OperateLogConvert.INSTANCE.convert(createReqDTO); + logDO.setJavaMethodArgs(StrUtils.maxLength(logDO.getJavaMethodArgs(), JAVA_METHOD_ARGS_MAX_LENGTH)); + logDO.setResultData(StrUtils.maxLength(logDO.getResultData(), RESULT_MAX_LENGTH)); + operateLogMapper.insert(logDO); } @Override diff --git a/yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/service/logger/OperateLogServiceImplTest.java b/yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/service/logger/OperateLogServiceImplTest.java index 8e6d742c2..f1b043524 100644 --- a/yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/service/logger/OperateLogServiceImplTest.java +++ b/yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/service/logger/OperateLogServiceImplTest.java @@ -7,9 +7,10 @@ import cn.iocoder.yudao.framework.common.exception.enums.GlobalErrorCodeConstant import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.util.monitor.TracerUtils; import cn.iocoder.yudao.framework.common.util.object.ObjectUtils; -import cn.iocoder.yudao.framework.operatelog.core.dto.OperateLogCreateReqDTO; import cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum; +import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest; import cn.iocoder.yudao.framework.test.core.util.RandomUtils; +import cn.iocoder.yudao.module.system.api.logger.dto.OperateLogCreateReqDTO; import cn.iocoder.yudao.module.system.controller.admin.logger.vo.operatelog.OperateLogExportReqVO; import cn.iocoder.yudao.module.system.controller.admin.logger.vo.operatelog.OperateLogPageReqVO; import cn.iocoder.yudao.module.system.dal.dataobject.logger.OperateLogDO; @@ -17,7 +18,6 @@ import cn.iocoder.yudao.module.system.dal.dataobject.user.AdminUserDO; import cn.iocoder.yudao.module.system.dal.mysql.logger.OperateLogMapper; import cn.iocoder.yudao.module.system.enums.common.SexEnum; import cn.iocoder.yudao.module.system.service.user.AdminUserService; -import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest; import org.junit.jupiter.api.Test; import org.springframework.boot.test.mock.mockito.MockBean; import org.springframework.context.annotation.Import; @@ -25,8 +25,6 @@ import org.springframework.context.annotation.Import; import javax.annotation.Resource; import java.util.Collections; import java.util.List; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.Future; import static cn.hutool.core.util.RandomUtil.randomEle; import static cn.iocoder.yudao.framework.common.exception.enums.GlobalErrorCodeConstants.BAD_REQUEST; @@ -49,7 +47,7 @@ public class OperateLogServiceImplTest extends BaseDbUnitTest { private AdminUserService userService; @Test - public void testCreateOperateLogAsync() throws InterruptedException, ExecutionException { + public void testCreateOperateLogAsync() { String traceId = TracerUtils.getTraceId(); OperateLogCreateReqDTO reqVO = RandomUtils.randomPojo(OperateLogCreateReqDTO.class, o -> { o.setTraceId(traceId); @@ -59,8 +57,7 @@ public class OperateLogServiceImplTest extends BaseDbUnitTest { }); // 执行service方法 - Future future = operateLogServiceImpl.createOperateLogAsync(reqVO); - future.get(); + operateLogServiceImpl.createOperateLog(reqVO); // 断言插入是否正确 OperateLogDO sysOperateLogDO = operateLogMapper.selectOne("trace_id", traceId); assertPojoEquals(reqVO, sysOperateLogDO);