Просмотр исходного кода

优化 yudao-spring-boot-starter-biz-operatelog 的封装,和 yudao-cloud 保持一致

YunaiV 3 лет назад
Родитель
Сommit
e68d4f54f7
15 измененных файлов с 423 добавлено и 177 удалено
  1. 7 0
      yudao-framework/yudao-spring-boot-starter-biz-operatelog/pom.xml
  2. 8 0
      yudao-framework/yudao-spring-boot-starter-biz-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelog/config/YudaoOperateLogAutoConfiguration.java
  3. 66 55
      yudao-framework/yudao-spring-boot-starter-biz-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelog/core/aop/OperateLogAspect.java
  4. 0 87
      yudao-framework/yudao-spring-boot-starter-biz-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelog/core/dto/OperateLogCreateReqDTO.java
  5. 110 0
      yudao-framework/yudao-spring-boot-starter-biz-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelog/core/service/OperateLog.java
  6. 8 8
      yudao-framework/yudao-spring-boot-starter-biz-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelog/core/service/OperateLogFrameworkService.java
  7. 28 0
      yudao-framework/yudao-spring-boot-starter-biz-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelog/core/service/OperateLogFrameworkServiceImpl.java
  8. 21 0
      yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/logger/OperateLogApi.java
  9. 123 0
      yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/logger/dto/OperateLogCreateReqDTO.java
  10. 27 0
      yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/api/logger/OperateLogApiImpl.java
  11. 2 1
      yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sms/SmsTemplateController.http
  12. 1 1
      yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/convert/logger/OperateLogConvert.java
  13. 12 1
      yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/logger/OperateLogService.java
  14. 6 17
      yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/logger/OperateLogServiceImpl.java
  15. 4 7
      yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/service/logger/OperateLogServiceImplTest.java

+ 7 - 0
yudao-framework/yudao-spring-boot-starter-biz-operatelog/pom.xml

@@ -34,6 +34,13 @@
             <scope>provided</scope>
         </dependency>
 
+        <!-- 业务组件 -->
+        <dependency>
+            <groupId>cn.iocoder.boot</groupId>
+            <artifactId>yudao-module-system-api</artifactId> <!-- 需要使用它,进行操作日志的记录 -->
+            <version>${revision}</version>
+        </dependency>
+
         <!-- 工具类相关 -->
         <dependency>
             <groupId>com.google.guava</groupId>

+ 8 - 0
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);
+    }
+
 }

+ 66 - 55
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<String> CONTENT = new ThreadLocal<>();
     /**
      * 用于记录拓展字段的上下文
      *
-     * @see OperateLogCreateReqDTO#getExts()
+     * @see OperateLog#getExts()
      */
     private static final ThreadLocal<Map<String, Object>> 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);
     }
 

+ 0 - 87
yudao-framework/yudao-spring-boot-starter-biz-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelog/core/dto/OperateLogCreateReqDTO.java

@@ -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<String, Object> 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;
-
-}

+ 110 - 0
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<String, Object> 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;
+
+}

+ 8 - 8
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<Boolean> createOperateLogAsync(OperateLogCreateReqDTO reqVO);
+    void createOperateLog(OperateLog operateLog);
 
 }

+ 28 - 0
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);
+    }
+
+}

+ 21 - 0
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);
+
+}

+ 123 - 0
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<String, Object> 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;
+
+}

+ 27 - 0
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);
+    }
+
+}

+ 2 - 1
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"

+ 1 - 1
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;
 

+ 12 - 1
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);
 
     /**
      * 获得操作日志分页列表

+ 6 - 17
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<Boolean> 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

+ 4 - 7
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<Boolean> future = operateLogServiceImpl.createOperateLogAsync(reqVO);
-        future.get();
+        operateLogServiceImpl.createOperateLog(reqVO);
         // 断言插入是否正确
         OperateLogDO sysOperateLogDO = operateLogMapper.selectOne("trace_id", traceId);
         assertPojoEquals(reqVO, sysOperateLogDO);