Commit e68d4f54f73dd853e69b6c20dee20c29e4ef69c5

Authored by YunaiV
1 parent b1aa9f48

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

Showing 15 changed files with 423 additions and 177 deletions
yudao-framework/yudao-spring-boot-starter-biz-operatelog/pom.xml
... ... @@ -34,6 +34,13 @@
34 34 <scope>provided</scope>
35 35 </dependency>
36 36  
  37 + <!-- 业务组件 -->
  38 + <dependency>
  39 + <groupId>cn.iocoder.boot</groupId>
  40 + <artifactId>yudao-module-system-api</artifactId> <!-- 需要使用它,进行操作日志的记录 -->
  41 + <version>${revision}</version>
  42 + </dependency>
  43 +
37 44 <!-- 工具类相关 -->
38 45 <dependency>
39 46 <groupId>com.google.guava</groupId>
... ...
yudao-framework/yudao-spring-boot-starter-biz-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelog/config/YudaoOperateLogAutoConfiguration.java
1 1 package cn.iocoder.yudao.framework.operatelog.config;
2 2  
3 3 import cn.iocoder.yudao.framework.operatelog.core.aop.OperateLogAspect;
  4 +import cn.iocoder.yudao.framework.operatelog.core.service.OperateLogFrameworkService;
  5 +import cn.iocoder.yudao.framework.operatelog.core.service.OperateLogFrameworkServiceImpl;
  6 +import cn.iocoder.yudao.module.system.api.logger.OperateLogApi;
4 7 import org.springframework.context.annotation.Bean;
5 8 import org.springframework.context.annotation.Configuration;
6 9  
... ... @@ -12,4 +15,9 @@ public class YudaoOperateLogAutoConfiguration {
12 15 return new OperateLogAspect();
13 16 }
14 17  
  18 + @Bean
  19 + public OperateLogFrameworkService operateLogFrameworkService(OperateLogApi operateLogApi) {
  20 + return new OperateLogFrameworkServiceImpl(operateLogApi);
  21 + }
  22 +
15 23 }
... ...
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;
9 9 import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
10 10 import cn.iocoder.yudao.framework.common.util.monitor.TracerUtils;
11 11 import cn.iocoder.yudao.framework.common.util.servlet.ServletUtils;
12   -import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog;
13   -import cn.iocoder.yudao.framework.operatelog.core.dto.OperateLogCreateReqDTO;
14 12 import cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum;
  13 +import cn.iocoder.yudao.framework.operatelog.core.service.OperateLog;
15 14 import cn.iocoder.yudao.framework.operatelog.core.service.OperateLogFrameworkService;
16 15 import cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils;
17 16 import com.google.common.collect.Maps;
... ... @@ -57,13 +56,13 @@ public class OperateLogAspect {
57 56 /**
58 57 * 用于记录操作内容的上下文
59 58 *
60   - * @see OperateLogCreateReqDTO#getContent()
  59 + * @see OperateLog#getContent()
61 60 */
62 61 private static final ThreadLocal<String> CONTENT = new ThreadLocal<>();
63 62 /**
64 63 * 用于记录拓展字段的上下文
65 64 *
66   - * @see OperateLogCreateReqDTO#getExts()
  65 + * @see OperateLog#getExts()
67 66 */
68 67 private static final ThreadLocal<Map<String, Object>> EXTS = new ThreadLocal<>();
69 68  
... ... @@ -73,16 +72,20 @@ public class OperateLogAspect {
73 72 @Around("@annotation(apiOperation)")
74 73 public Object around(ProceedingJoinPoint joinPoint, ApiOperation apiOperation) throws Throwable {
75 74 // 可能也添加了 @ApiOperation 注解
76   - OperateLog operateLog = getMethodAnnotation(joinPoint, OperateLog.class);
  75 + cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog operateLog = getMethodAnnotation(joinPoint,
  76 + cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog.class);
77 77 return around0(joinPoint, operateLog, apiOperation);
78 78 }
79 79  
80 80 @Around("!@annotation(io.swagger.annotations.ApiOperation) && @annotation(operateLog)") // 兼容处理,只添加 @OperateLog 注解的情况
81   - public Object around(ProceedingJoinPoint joinPoint, OperateLog operateLog) throws Throwable {
  81 + public Object around(ProceedingJoinPoint joinPoint,
  82 + cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog operateLog) throws Throwable {
82 83 return around0(joinPoint, operateLog, null);
83 84 }
84 85  
85   - private Object around0(ProceedingJoinPoint joinPoint, OperateLog operateLog, ApiOperation apiOperation) throws Throwable {
  86 + private Object around0(ProceedingJoinPoint joinPoint,
  87 + cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog operateLog,
  88 + ApiOperation apiOperation) throws Throwable {
86 89 // 目前,只有管理员,才记录操作日志!所以非管理员,直接调用,不进行记录
87 90 Integer userType = WebFrameworkUtils.getLoginUserType();
88 91 if (!Objects.equals(userType, UserTypeEnum.ADMIN.getValue())) {
... ... @@ -121,7 +124,9 @@ public class OperateLogAspect {
121 124 EXTS.remove();
122 125 }
123 126  
124   - private void log(ProceedingJoinPoint joinPoint, OperateLog operateLog, ApiOperation apiOperation,
  127 + private void log(ProceedingJoinPoint joinPoint,
  128 + cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog operateLog,
  129 + ApiOperation apiOperation,
125 130 Date startTime, Object result, Throwable exception) {
126 131 try {
127 132 // 判断不记录的情况
... ... @@ -136,113 +141,119 @@ public class OperateLogAspect {
136 141 }
137 142 }
138 143  
139   - private void log0(ProceedingJoinPoint joinPoint, OperateLog operateLog, ApiOperation apiOperation,
  144 + private void log0(ProceedingJoinPoint joinPoint,
  145 + cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog operateLog,
  146 + ApiOperation apiOperation,
140 147 Date startTime, Object result, Throwable exception) {
141   - OperateLogCreateReqDTO operateLogDTO = new OperateLogCreateReqDTO();
  148 + OperateLog operateLogObj = new OperateLog();
142 149 // 补全通用字段
143   - operateLogDTO.setTraceId(TracerUtils.getTraceId());
144   - operateLogDTO.setStartTime(startTime);
  150 + operateLogObj.setTraceId(TracerUtils.getTraceId());
  151 + operateLogObj.setStartTime(startTime);
145 152 // 补充用户信息
146   - fillUserFields(operateLogDTO);
  153 + fillUserFields(operateLogObj);
147 154 // 补全模块信息
148   - fillModuleFields(operateLogDTO, joinPoint, operateLog, apiOperation);
  155 + fillModuleFields(operateLogObj, joinPoint, operateLog, apiOperation);
149 156 // 补全请求信息
150   - fillRequestFields(operateLogDTO);
  157 + fillRequestFields(operateLogObj);
151 158 // 补全方法信息
152   - fillMethodFields(operateLogDTO, joinPoint, operateLog, startTime, result, exception);
  159 + fillMethodFields(operateLogObj, joinPoint, operateLog, startTime, result, exception);
153 160  
154 161 // 异步记录日志
155   - operateLogFrameworkService.createOperateLogAsync(operateLogDTO);
  162 + operateLogFrameworkService.createOperateLog(operateLogObj);
156 163 }
157 164  
158   - private static void fillUserFields(OperateLogCreateReqDTO operateLogDTO) {
159   - operateLogDTO.setUserId(WebFrameworkUtils.getLoginUserId());
160   - operateLogDTO.setUserType(WebFrameworkUtils.getLoginUserType());
  165 + private static void fillUserFields(OperateLog operateLogObj) {
  166 + operateLogObj.setUserId(WebFrameworkUtils.getLoginUserId());
  167 + operateLogObj.setUserType(WebFrameworkUtils.getLoginUserType());
161 168 }
162 169  
163   - private static void fillModuleFields(OperateLogCreateReqDTO operateLogDTO,
164   - ProceedingJoinPoint joinPoint, OperateLog operateLog, ApiOperation apiOperation) {
  170 + private static void fillModuleFields(OperateLog operateLogObj,
  171 + ProceedingJoinPoint joinPoint,
  172 + cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog operateLog,
  173 + ApiOperation apiOperation) {
165 174 // module 属性
166 175 if (operateLog != null) {
167   - operateLogDTO.setModule(operateLog.module());
  176 + operateLogObj.setModule(operateLog.module());
168 177 }
169   - if (StrUtil.isEmpty(operateLogDTO.getModule())) {
  178 + if (StrUtil.isEmpty(operateLogObj.getModule())) {
170 179 Api api = getClassAnnotation(joinPoint, Api.class);
171 180 if (api != null) {
172 181 // 优先读取 @API 的 name 属性
173 182 if (StrUtil.isNotEmpty(api.value())) {
174   - operateLogDTO.setModule(api.value());
  183 + operateLogObj.setModule(api.value());
175 184 }
176 185 // 没有的话,读取 @API 的 tags 属性
177   - if (StrUtil.isEmpty(operateLogDTO.getModule()) && ArrayUtil.isNotEmpty(api.tags())) {
178   - operateLogDTO.setModule(api.tags()[0]);
  186 + if (StrUtil.isEmpty(operateLogObj.getModule()) && ArrayUtil.isNotEmpty(api.tags())) {
  187 + operateLogObj.setModule(api.tags()[0]);
179 188 }
180 189 }
181 190 }
182 191 // name 属性
183 192 if (operateLog != null) {
184   - operateLogDTO.setName(operateLog.name());
  193 + operateLogObj.setName(operateLog.name());
185 194 }
186   - if (StrUtil.isEmpty(operateLogDTO.getName()) && apiOperation != null) {
187   - operateLogDTO.setName(apiOperation.value());
  195 + if (StrUtil.isEmpty(operateLogObj.getName()) && apiOperation != null) {
  196 + operateLogObj.setName(apiOperation.value());
188 197 }
189 198 // type 属性
190 199 if (operateLog != null && ArrayUtil.isNotEmpty(operateLog.type())) {
191   - operateLogDTO.setType(operateLog.type()[0].getType());
  200 + operateLogObj.setType(operateLog.type()[0].getType());
192 201 }
193   - if (operateLogDTO.getType() == null) {
  202 + if (operateLogObj.getType() == null) {
194 203 RequestMethod requestMethod = obtainFirstMatchRequestMethod(obtainRequestMethod(joinPoint));
195 204 OperateTypeEnum operateLogType = convertOperateLogType(requestMethod);
196   - operateLogDTO.setType(operateLogType != null ? operateLogType.getType() : null);
  205 + operateLogObj.setType(operateLogType != null ? operateLogType.getType() : null);
197 206 }
198 207 // content 和 exts 属性
199   - operateLogDTO.setContent(CONTENT.get());
200   - operateLogDTO.setExts(EXTS.get());
  208 + operateLogObj.setContent(CONTENT.get());
  209 + operateLogObj.setExts(EXTS.get());
201 210 }
202 211  
203   - private static void fillRequestFields(OperateLogCreateReqDTO operateLogDTO) {
  212 + private static void fillRequestFields(OperateLog operateLogObj) {
204 213 // 获得 Request 对象
205 214 HttpServletRequest request = ServletUtils.getRequest();
206 215 if (request == null) {
207 216 return;
208 217 }
209 218 // 补全请求信息
210   - operateLogDTO.setRequestMethod(request.getMethod());
211   - operateLogDTO.setRequestUrl(request.getRequestURI());
212   - operateLogDTO.setUserIp(ServletUtil.getClientIP(request));
213   - operateLogDTO.setUserAgent(ServletUtils.getUserAgent(request));
  219 + operateLogObj.setRequestMethod(request.getMethod());
  220 + operateLogObj.setRequestUrl(request.getRequestURI());
  221 + operateLogObj.setUserIp(ServletUtil.getClientIP(request));
  222 + operateLogObj.setUserAgent(ServletUtils.getUserAgent(request));
214 223 }
215 224  
216   - private static void fillMethodFields(OperateLogCreateReqDTO operateLogDTO,
217   - ProceedingJoinPoint joinPoint, OperateLog operateLog,
  225 + private static void fillMethodFields(OperateLog operateLogObj,
  226 + ProceedingJoinPoint joinPoint,
  227 + cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog operateLog,
218 228 Date startTime, Object result, Throwable exception) {
219 229 MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
220   - operateLogDTO.setJavaMethod(methodSignature.toString());
  230 + operateLogObj.setJavaMethod(methodSignature.toString());
221 231 if (operateLog == null || operateLog.logArgs()) {
222   - operateLogDTO.setJavaMethodArgs(obtainMethodArgs(joinPoint));
  232 + operateLogObj.setJavaMethodArgs(obtainMethodArgs(joinPoint));
223 233 }
224 234 if (operateLog == null || operateLog.logResultData()) {
225   - operateLogDTO.setResultData(obtainResultData(result));
  235 + operateLogObj.setResultData(obtainResultData(result));
226 236 }
227   - operateLogDTO.setDuration((int) (System.currentTimeMillis() - startTime.getTime()));
  237 + operateLogObj.setDuration((int) (System.currentTimeMillis() - startTime.getTime()));
228 238 // (正常)处理 resultCode 和 resultMsg 字段
229 239 if (result != null) {
230 240 if (result instanceof CommonResult) {
231 241 CommonResult<?> commonResult = (CommonResult<?>) result;
232   - operateLogDTO.setResultCode(commonResult.getCode());
233   - operateLogDTO.setResultMsg(commonResult.getMsg());
  242 + operateLogObj.setResultCode(commonResult.getCode());
  243 + operateLogObj.setResultMsg(commonResult.getMsg());
234 244 } else {
235   - operateLogDTO.setResultCode(SUCCESS.getCode());
  245 + operateLogObj.setResultCode(SUCCESS.getCode());
236 246 }
237 247 }
238 248 // (异常)处理 resultCode 和 resultMsg 字段
239 249 if (exception != null) {
240   - operateLogDTO.setResultCode(INTERNAL_SERVER_ERROR.getCode());
241   - operateLogDTO.setResultMsg(ExceptionUtil.getRootCauseMessage(exception));
  250 + operateLogObj.setResultCode(INTERNAL_SERVER_ERROR.getCode());
  251 + operateLogObj.setResultMsg(ExceptionUtil.getRootCauseMessage(exception));
242 252 }
243 253 }
244 254  
245   - private static boolean isLogEnable(ProceedingJoinPoint joinPoint, OperateLog operateLog) {
  255 + private static boolean isLogEnable(ProceedingJoinPoint joinPoint,
  256 + cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog operateLog) {
246 257 // 有 @OperateLog 注解的情况下
247 258 if (operateLog != null) {
248 259 return operateLog.enable();
... ... @@ -256,9 +267,9 @@ public class OperateLogAspect {
256 267 return null;
257 268 }
258 269 return Arrays.stream(requestMethods).filter(requestMethod ->
259   - requestMethod == RequestMethod.POST
260   - || requestMethod == RequestMethod.PUT
261   - || requestMethod == RequestMethod.DELETE)
  270 + requestMethod == RequestMethod.POST
  271 + || requestMethod == RequestMethod.PUT
  272 + || requestMethod == RequestMethod.DELETE)
262 273 .findFirst().orElse(null);
263 274 }
264 275  
... ...
yudao-framework/yudao-spring-boot-starter-biz-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelog/core/dto/OperateLogCreateReqDTO.java deleted
1   -package cn.iocoder.yudao.framework.operatelog.core.dto;
2   -
3   -import io.swagger.annotations.ApiModelProperty;
4   -import lombok.Data;
5   -
6   -import javax.validation.constraints.NotEmpty;
7   -import javax.validation.constraints.NotNull;
8   -import java.util.Date;
9   -import java.util.Map;
10   -
11   -/**
12   - * 操作日志创建 Request DTO
13   - */
14   -@Data
15   -public class OperateLogCreateReqDTO {
16   -
17   - @ApiModelProperty(value = "链路追踪编号", required = true, example = "89aca178-a370-411c-ae02-3f0d672be4ab")
18   - @NotEmpty(message = "链路追踪编号不能为空")
19   - private String traceId;
20   -
21   - @ApiModelProperty(value = "用户编号", required = true, example = "1024")
22   - @NotNull(message = "用户编号不能为空")
23   - private Long userId;
24   - @ApiModelProperty(value = "用户类型", required = true, example = "1")
25   - @NotNull(message = "用户类型不能为空")
26   - private Integer userType;
27   -
28   - @ApiModelProperty(value = "操作模块", required = true, example = "订单")
29   - @NotEmpty(message = "操作模块不能为空")
30   - private String module;
31   -
32   - @ApiModelProperty(value = "操作名", required = true, example = "创建订单")
33   - @NotEmpty(message = "操作名")
34   - private String name;
35   -
36   - @ApiModelProperty(value = "操作分类", required = true, example = "1", notes = "参见 SysOperateLogTypeEnum 枚举类")
37   - @NotNull(message = "操作分类不能为空")
38   - private Integer type;
39   -
40   - @ApiModelProperty(value = "操作明细", example = "修改编号为 1 的用户信息,将性别从男改成女,将姓名从芋道改成源码。")
41   - private String content;
42   -
43   - @ApiModelProperty(value = "拓展字段", example = "{'orderId': 1}")
44   - private Map<String, Object> exts;
45   -
46   - @ApiModelProperty(value = "请求方法名", required = true, example = "GET")
47   - @NotEmpty(message = "请求方法名不能为空")
48   - private String requestMethod;
49   -
50   - @ApiModelProperty(value = "请求地址", required = true, example = "/xxx/yyy")
51   - @NotEmpty(message = "请求地址不能为空")
52   - private String requestUrl;
53   -
54   - @ApiModelProperty(value = "用户 IP", required = true, example = "127.0.0.1")
55   - @NotEmpty(message = "用户 IP 不能为空")
56   - private String userIp;
57   -
58   - @ApiModelProperty(value = "浏览器 UserAgent", required = true, example = "Mozilla/5.0")
59   - @NotEmpty(message = "浏览器 UserAgent 不能为空")
60   - private String userAgent;
61   -
62   - @ApiModelProperty(value = "Java 方法名", required = true, example = "cn.iocoder.yudao.UserController.save(...)")
63   - @NotEmpty(message = "Java 方法名不能为空")
64   - private String javaMethod;
65   -
66   - @ApiModelProperty(value = "Java 方法的参数")
67   - private String javaMethodArgs;
68   -
69   - @ApiModelProperty(value = "开始时间", required = true)
70   - @NotNull(message = "开始时间不能为空")
71   - private Date startTime;
72   -
73   - @ApiModelProperty(value = "执行时长,单位:毫秒", required = true)
74   - @NotNull(message = "执行时长不能为空")
75   - private Integer duration;
76   -
77   - @ApiModelProperty(value = "结果码", required = true)
78   - @NotNull(message = "结果码不能为空")
79   - private Integer resultCode;
80   -
81   - @ApiModelProperty(value = "结果提示")
82   - private String resultMsg;
83   -
84   - @ApiModelProperty(value = "结果数据")
85   - private String resultData;
86   -
87   -}
yudao-framework/yudao-spring-boot-starter-biz-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelog/core/service/OperateLog.java 0 → 100644
  1 +package cn.iocoder.yudao.framework.operatelog.core.service;
  2 +
  3 +import lombok.Data;
  4 +
  5 +import java.util.Date;
  6 +import java.util.Map;
  7 +
  8 +/**
  9 + * 操作日志
  10 + *
  11 + * @author 芋道源码
  12 + */
  13 +@Data
  14 +public class OperateLog {
  15 +
  16 + /**
  17 + * 链路追踪编号
  18 + */
  19 + private String traceId;
  20 +
  21 + /**
  22 + * 用户编号
  23 + */
  24 + private Long userId;
  25 + /**
  26 + * 用户类型
  27 + */
  28 + private Integer userType;
  29 +
  30 + /**
  31 + * 操作模块
  32 + */
  33 + private String module;
  34 +
  35 + /**
  36 + * 操作名
  37 + */
  38 + private String name;
  39 +
  40 + /**
  41 + * 操作分类
  42 + */
  43 + private Integer type;
  44 +
  45 + /**
  46 + * 操作明细
  47 + */
  48 + private String content;
  49 +
  50 + /**
  51 + * 拓展字段
  52 + */
  53 + private Map<String, Object> exts;
  54 +
  55 + /**
  56 + * 请求方法名
  57 + */
  58 + private String requestMethod;
  59 +
  60 + /**
  61 + * 请求地址
  62 + */
  63 + private String requestUrl;
  64 +
  65 + /**
  66 + * 用户 IP
  67 + */
  68 + private String userIp;
  69 +
  70 + /**
  71 + * 浏览器 UserAgent
  72 + */
  73 + private String userAgent;
  74 +
  75 + /**
  76 + * Java 方法名
  77 + */
  78 + private String javaMethod;
  79 +
  80 + /**
  81 + * Java 方法的参数
  82 + */
  83 + private String javaMethodArgs;
  84 +
  85 + /**
  86 + * 开始时间
  87 + */
  88 + private Date startTime;
  89 +
  90 + /**
  91 + * 执行时长,单位:毫秒
  92 + */
  93 + private Integer duration;
  94 +
  95 + /**
  96 + * 结果码
  97 + */
  98 + private Integer resultCode;
  99 +
  100 + /**
  101 + * 结果提示
  102 + */
  103 + private String resultMsg;
  104 +
  105 + /**
  106 + * 结果数据
  107 + */
  108 + private String resultData;
  109 +
  110 +}
... ...
yudao-framework/yudao-spring-boot-starter-biz-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelog/core/service/OperateLogFrameworkService.java
1 1 package cn.iocoder.yudao.framework.operatelog.core.service;
2 2  
3   -import cn.iocoder.yudao.framework.operatelog.core.dto.OperateLogCreateReqDTO;
4   -
5   -import java.util.concurrent.Future;
6   -
  3 +/**
  4 + * 操作日志 Framework Service 接口
  5 + *
  6 + * @author 芋道源码
  7 + */
7 8 public interface OperateLogFrameworkService {
8 9  
9 10 /**
10   - * 异步记录操作日志
  11 + * 记录操作日志
11 12 *
12   - * @param reqVO 操作日志请求
13   - * @return true: 记录成功,false: 记录失败
  13 + * @param operateLog 操作日志请求
14 14 */
15   - Future<Boolean> createOperateLogAsync(OperateLogCreateReqDTO reqVO);
  15 + void createOperateLog(OperateLog operateLog);
16 16  
17 17 }
... ...
yudao-framework/yudao-spring-boot-starter-biz-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelog/core/service/OperateLogFrameworkServiceImpl.java 0 → 100644
  1 +package cn.iocoder.yudao.framework.operatelog.core.service;
  2 +
  3 +import cn.hutool.core.bean.BeanUtil;
  4 +import cn.iocoder.yudao.module.system.api.logger.OperateLogApi;
  5 +import cn.iocoder.yudao.module.system.api.logger.dto.OperateLogCreateReqDTO;
  6 +import lombok.RequiredArgsConstructor;
  7 +import org.springframework.scheduling.annotation.Async;
  8 +
  9 +/**
  10 + * 操作日志 Framework Service 实现类
  11 + *
  12 + * 基于 {@link OperateLogApi} 实现,记录操作日志
  13 + *
  14 + * @author 芋道源码
  15 + */
  16 +@RequiredArgsConstructor
  17 +public class OperateLogFrameworkServiceImpl implements OperateLogFrameworkService {
  18 +
  19 + private final OperateLogApi operateLogApi;
  20 +
  21 + @Override
  22 + @Async
  23 + public void createOperateLog(OperateLog operateLog) {
  24 + OperateLogCreateReqDTO reqDTO = BeanUtil.copyProperties(operateLog, OperateLogCreateReqDTO.class);
  25 + operateLogApi.createOperateLog(reqDTO);
  26 + }
  27 +
  28 +}
... ...
yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/logger/OperateLogApi.java 0 → 100644
  1 +package cn.iocoder.yudao.module.system.api.logger;
  2 +
  3 +import cn.iocoder.yudao.module.system.api.logger.dto.OperateLogCreateReqDTO;
  4 +
  5 +import javax.validation.Valid;
  6 +
  7 +/**
  8 + * 操作日志 API 接口
  9 + *
  10 + * @author 芋道源码
  11 + */
  12 +public interface OperateLogApi {
  13 +
  14 + /**
  15 + * 创建操作日志
  16 + *
  17 + * @param createReqDTO 请求
  18 + */
  19 + void createOperateLog(@Valid OperateLogCreateReqDTO createReqDTO);
  20 +
  21 +}
... ...
yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/logger/dto/OperateLogCreateReqDTO.java 0 → 100644
  1 +package cn.iocoder.yudao.module.system.api.logger.dto;
  2 +
  3 +import lombok.Data;
  4 +
  5 +import javax.validation.constraints.NotEmpty;
  6 +import javax.validation.constraints.NotNull;
  7 +import java.util.Date;
  8 +import java.util.Map;
  9 +
  10 +/**
  11 + * 操作日志创建 Request DTO
  12 + */
  13 +@Data
  14 +public class OperateLogCreateReqDTO {
  15 +
  16 + /**
  17 + * 链路追踪编号
  18 + */
  19 + private String traceId;
  20 +
  21 + /**
  22 + * 用户编号
  23 + */
  24 + @NotNull(message = "用户编号不能为空")
  25 + private Long userId;
  26 + /**
  27 + * 用户类型
  28 + */
  29 + @NotNull(message = "用户类型不能为空")
  30 + private Integer userType;
  31 +
  32 + /**
  33 + * 操作模块
  34 + */
  35 + @NotEmpty(message = "操作模块不能为空")
  36 + private String module;
  37 +
  38 + /**
  39 + * 操作名
  40 + */
  41 + @NotEmpty(message = "操作名")
  42 + private String name;
  43 +
  44 + /**
  45 + * 操作分类
  46 + */
  47 + @NotNull(message = "操作分类不能为空")
  48 + private Integer type;
  49 +
  50 + /**
  51 + * 操作明细
  52 + */
  53 + private String content;
  54 +
  55 + /**
  56 + * 拓展字段
  57 + */
  58 + private Map<String, Object> exts;
  59 +
  60 + /**
  61 + * 请求方法名
  62 + */
  63 + @NotEmpty(message = "请求方法名不能为空")
  64 + private String requestMethod;
  65 +
  66 + /**
  67 + * 请求地址
  68 + */
  69 + @NotEmpty(message = "请求地址不能为空")
  70 + private String requestUrl;
  71 +
  72 + /**
  73 + * 用户 IP
  74 + */
  75 + @NotEmpty(message = "用户 IP 不能为空")
  76 + private String userIp;
  77 +
  78 + /**
  79 + * 浏览器 UserAgent
  80 + */
  81 + @NotEmpty(message = "浏览器 UserAgent 不能为空")
  82 + private String userAgent;
  83 +
  84 + /**
  85 + * Java 方法名
  86 + */
  87 + @NotEmpty(message = "Java 方法名不能为空")
  88 + private String javaMethod;
  89 +
  90 + /**
  91 + * Java 方法的参数
  92 + */
  93 + private String javaMethodArgs;
  94 +
  95 + /**
  96 + * 开始时间
  97 + */
  98 + @NotNull(message = "开始时间不能为空")
  99 + private Date startTime;
  100 +
  101 + /**
  102 + * 执行时长,单位:毫秒
  103 + */
  104 + @NotNull(message = "执行时长不能为空")
  105 + private Integer duration;
  106 +
  107 + /**
  108 + * 结果码
  109 + */
  110 + @NotNull(message = "结果码不能为空")
  111 + private Integer resultCode;
  112 +
  113 + /**
  114 + * 结果提示
  115 + */
  116 + private String resultMsg;
  117 +
  118 + /**
  119 + * 结果数据
  120 + */
  121 + private String resultData;
  122 +
  123 +}
... ...
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/api/logger/OperateLogApiImpl.java 0 → 100644
  1 +package cn.iocoder.yudao.module.system.api.logger;
  2 +
  3 +import cn.iocoder.yudao.module.system.api.logger.dto.OperateLogCreateReqDTO;
  4 +import cn.iocoder.yudao.module.system.service.logger.OperateLogService;
  5 +import org.springframework.stereotype.Service;
  6 +import org.springframework.validation.annotation.Validated;
  7 +
  8 +import javax.annotation.Resource;
  9 +
  10 +/**
  11 + * 操作日志 API 实现类
  12 + *
  13 + * @author 芋道源码
  14 + */
  15 +@Service
  16 +@Validated
  17 +public class OperateLogApiImpl implements OperateLogApi {
  18 +
  19 + @Resource
  20 + private OperateLogService operateLogService;
  21 +
  22 + @Override
  23 + public void createOperateLog(OperateLogCreateReqDTO createReqDTO) {
  24 + operateLogService.createOperateLog(createReqDTO);
  25 + }
  26 +
  27 +}
... ...
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
5 5 tenant-id: {{adminTenentId}}
6 6  
7 7 {
8   - "code": "test_01",
  8 + "templateCode": "test_01",
  9 + "mobile": "156016913900",
9 10 "params": {
10 11 "key01": "value01",
11 12 "key02": "value02"
... ...
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;
6 6 import cn.iocoder.yudao.module.system.dal.dataobject.user.AdminUserDO;
7 7 import cn.iocoder.yudao.framework.common.pojo.PageResult;
8 8 import cn.iocoder.yudao.framework.common.util.collection.MapUtils;
9   -import cn.iocoder.yudao.framework.operatelog.core.dto.OperateLogCreateReqDTO;
  9 +import cn.iocoder.yudao.module.system.api.logger.dto.OperateLogCreateReqDTO;
10 10 import org.mapstruct.Mapper;
11 11 import org.mapstruct.factory.Mappers;
12 12  
... ...
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/logger/OperateLogService.java
1 1 package cn.iocoder.yudao.module.system.service.logger;
2 2  
3 3 import cn.iocoder.yudao.framework.common.pojo.PageResult;
  4 +import cn.iocoder.yudao.framework.operatelog.core.service.OperateLog;
4 5 import cn.iocoder.yudao.framework.operatelog.core.service.OperateLogFrameworkService;
  6 +import cn.iocoder.yudao.module.system.api.logger.dto.OperateLogCreateReqDTO;
5 7 import cn.iocoder.yudao.module.system.controller.admin.logger.vo.operatelog.OperateLogExportReqVO;
6 8 import cn.iocoder.yudao.module.system.controller.admin.logger.vo.operatelog.OperateLogPageReqVO;
7 9 import cn.iocoder.yudao.module.system.dal.dataobject.logger.OperateLogDO;
... ... @@ -10,8 +12,17 @@ import java.util.List;
10 12  
11 13 /**
12 14 * 操作日志 Service 接口
  15 + *
  16 + * @author 芋道源码
13 17 */
14   -public interface OperateLogService extends OperateLogFrameworkService {
  18 +public interface OperateLogService {
  19 +
  20 + /**
  21 + * 记录操作日志
  22 + *
  23 + * @param createReqDTO 操作日志请求
  24 + */
  25 + void createOperateLog(OperateLogCreateReqDTO createReqDTO);
15 26  
16 27 /**
17 28 * 获得操作日志分页列表
... ...
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;
4 4 import cn.hutool.core.util.StrUtil;
5 5 import cn.iocoder.yudao.framework.common.pojo.PageResult;
6 6 import cn.iocoder.yudao.framework.common.util.string.StrUtils;
7   -import cn.iocoder.yudao.framework.operatelog.core.dto.OperateLogCreateReqDTO;
  7 +import cn.iocoder.yudao.module.system.api.logger.dto.OperateLogCreateReqDTO;
8 8 import cn.iocoder.yudao.module.system.controller.admin.logger.vo.operatelog.OperateLogExportReqVO;
9 9 import cn.iocoder.yudao.module.system.controller.admin.logger.vo.operatelog.OperateLogPageReqVO;
10 10 import cn.iocoder.yudao.module.system.convert.logger.OperateLogConvert;
... ... @@ -13,8 +13,6 @@ import cn.iocoder.yudao.module.system.dal.dataobject.user.AdminUserDO;
13 13 import cn.iocoder.yudao.module.system.dal.mysql.logger.OperateLogMapper;
14 14 import cn.iocoder.yudao.module.system.service.user.AdminUserService;
15 15 import lombok.extern.slf4j.Slf4j;
16   -import org.springframework.scheduling.annotation.Async;
17   -import org.springframework.scheduling.annotation.AsyncResult;
18 16 import org.springframework.stereotype.Service;
19 17 import org.springframework.validation.annotation.Validated;
20 18  
... ... @@ -22,7 +20,6 @@ import javax.annotation.Resource;
22 20 import java.util.Collection;
23 21 import java.util.Collections;
24 22 import java.util.List;
25   -import java.util.concurrent.Future;
26 23  
27 24 import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet;
28 25 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 {
40 37 private AdminUserService userService;
41 38  
42 39 @Override
43   - @Async
44   - public Future<Boolean> createOperateLogAsync(OperateLogCreateReqDTO reqVO) {
45   - boolean success = false;
46   - try {
47   - OperateLogDO logDO = OperateLogConvert.INSTANCE.convert(reqVO);
48   - logDO.setJavaMethodArgs(StrUtils.maxLength(logDO.getJavaMethodArgs(), JAVA_METHOD_ARGS_MAX_LENGTH));
49   - logDO.setResultData(StrUtils.maxLength(logDO.getResultData(), RESULT_MAX_LENGTH));
50   - success = operateLogMapper.insert(logDO) == 1;
51   - } catch (Throwable throwable) {
52   - // 仅仅打印日志,不对外抛出。原因是,还是要保留现场数据。
53   - log.error("[createOperateLogAsync][记录操作日志异常,日志为 ({})]", reqVO, throwable);
54   - }
55   - return new AsyncResult<>(success);
  40 + public void createOperateLog(OperateLogCreateReqDTO createReqDTO) {
  41 + OperateLogDO logDO = OperateLogConvert.INSTANCE.convert(createReqDTO);
  42 + logDO.setJavaMethodArgs(StrUtils.maxLength(logDO.getJavaMethodArgs(), JAVA_METHOD_ARGS_MAX_LENGTH));
  43 + logDO.setResultData(StrUtils.maxLength(logDO.getResultData(), RESULT_MAX_LENGTH));
  44 + operateLogMapper.insert(logDO);
56 45 }
57 46  
58 47 @Override
... ...
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
7 7 import cn.iocoder.yudao.framework.common.pojo.PageResult;
8 8 import cn.iocoder.yudao.framework.common.util.monitor.TracerUtils;
9 9 import cn.iocoder.yudao.framework.common.util.object.ObjectUtils;
10   -import cn.iocoder.yudao.framework.operatelog.core.dto.OperateLogCreateReqDTO;
11 10 import cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum;
  11 +import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest;
12 12 import cn.iocoder.yudao.framework.test.core.util.RandomUtils;
  13 +import cn.iocoder.yudao.module.system.api.logger.dto.OperateLogCreateReqDTO;
13 14 import cn.iocoder.yudao.module.system.controller.admin.logger.vo.operatelog.OperateLogExportReqVO;
14 15 import cn.iocoder.yudao.module.system.controller.admin.logger.vo.operatelog.OperateLogPageReqVO;
15 16 import cn.iocoder.yudao.module.system.dal.dataobject.logger.OperateLogDO;
... ... @@ -17,7 +18,6 @@ import cn.iocoder.yudao.module.system.dal.dataobject.user.AdminUserDO;
17 18 import cn.iocoder.yudao.module.system.dal.mysql.logger.OperateLogMapper;
18 19 import cn.iocoder.yudao.module.system.enums.common.SexEnum;
19 20 import cn.iocoder.yudao.module.system.service.user.AdminUserService;
20   -import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest;
21 21 import org.junit.jupiter.api.Test;
22 22 import org.springframework.boot.test.mock.mockito.MockBean;
23 23 import org.springframework.context.annotation.Import;
... ... @@ -25,8 +25,6 @@ import org.springframework.context.annotation.Import;
25 25 import javax.annotation.Resource;
26 26 import java.util.Collections;
27 27 import java.util.List;
28   -import java.util.concurrent.ExecutionException;
29   -import java.util.concurrent.Future;
30 28  
31 29 import static cn.hutool.core.util.RandomUtil.randomEle;
32 30 import static cn.iocoder.yudao.framework.common.exception.enums.GlobalErrorCodeConstants.BAD_REQUEST;
... ... @@ -49,7 +47,7 @@ public class OperateLogServiceImplTest extends BaseDbUnitTest {
49 47 private AdminUserService userService;
50 48  
51 49 @Test
52   - public void testCreateOperateLogAsync() throws InterruptedException, ExecutionException {
  50 + public void testCreateOperateLogAsync() {
53 51 String traceId = TracerUtils.getTraceId();
54 52 OperateLogCreateReqDTO reqVO = RandomUtils.randomPojo(OperateLogCreateReqDTO.class, o -> {
55 53 o.setTraceId(traceId);
... ... @@ -59,8 +57,7 @@ public class OperateLogServiceImplTest extends BaseDbUnitTest {
59 57 });
60 58  
61 59 // 执行service方法
62   - Future<Boolean> future = operateLogServiceImpl.createOperateLogAsync(reqVO);
63   - future.get();
  60 + operateLogServiceImpl.createOperateLog(reqVO);
64 61 // 断言插入是否正确
65 62 OperateLogDO sysOperateLogDO = operateLogMapper.selectOne("trace_id", traceId);
66 63 assertPojoEquals(reqVO, sysOperateLogDO);
... ...