mirror of
				https://gitee.com/hhyykk/ipms-sjy.git
				synced 2025-11-01 02:38:43 +08:00 
			
		
		
		
	【代码优化】SYSTEM:操作日志,增加异步记录
This commit is contained in:
		| @@ -7,6 +7,8 @@ import com.baomidou.mybatisplus.autoconfigure.MybatisPlusAutoConfiguration; | ||||
| import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler; | ||||
| import com.baomidou.mybatisplus.core.incrementer.IKeyGenerator; | ||||
| import com.baomidou.mybatisplus.extension.incrementer.*; | ||||
| import com.baomidou.mybatisplus.extension.parser.JsqlParserGlobal; | ||||
| import com.baomidou.mybatisplus.extension.parser.cache.JdkSerialCaffeineJsqlParseCache; | ||||
| import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor; | ||||
| import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor; | ||||
| import org.apache.ibatis.annotations.Mapper; | ||||
| @@ -16,6 +18,8 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; | ||||
| import org.springframework.context.annotation.Bean; | ||||
| import org.springframework.core.env.ConfigurableEnvironment; | ||||
|  | ||||
| import java.util.concurrent.TimeUnit; | ||||
|  | ||||
| /** | ||||
|  * MyBaits 配置类 | ||||
|  * | ||||
| @@ -26,6 +30,14 @@ import org.springframework.core.env.ConfigurableEnvironment; | ||||
|         lazyInitialization = "${mybatis.lazy-initialization:false}") // Mapper 懒加载,目前仅用于单元测试 | ||||
| public class YudaoMybatisAutoConfiguration { | ||||
|  | ||||
|     static { | ||||
|         // 动态 SQL 智能优化支持本地缓存加速解析,更完善的租户复杂 XML 动态 SQL 支持,静态注入缓存 | ||||
|         JsqlParserGlobal.setJsqlParseCache(new JdkSerialCaffeineJsqlParseCache( | ||||
|                 (cache) -> cache.maximumSize(1024) | ||||
|                         .expireAfterWrite(5, TimeUnit.SECONDS)) | ||||
|         ); | ||||
|     } | ||||
|  | ||||
|     @Bean | ||||
|     public MybatisPlusInterceptor mybatisPlusInterceptor() { | ||||
|         MybatisPlusInterceptor mybatisPlusInterceptor = new MybatisPlusInterceptor(); | ||||
| @@ -34,7 +46,7 @@ public class YudaoMybatisAutoConfiguration { | ||||
|     } | ||||
|  | ||||
|     @Bean | ||||
|     public MetaObjectHandler defaultMetaObjectHandler(){ | ||||
|     public MetaObjectHandler defaultMetaObjectHandler() { | ||||
|         return new DefaultDBFieldHandler(); // 自动填充参数类 | ||||
|     } | ||||
|  | ||||
|   | ||||
| @@ -69,7 +69,7 @@ public class ApiSignatureAspect { | ||||
|  | ||||
|         // 3. 将 nonce 记入缓存,防止重复使用(重点二:此处需要将 ttl 设定为允许 timestamp 时间差的值 x 2 ) | ||||
|         String nonce = request.getHeader(signature.nonce()); | ||||
|         signatureRedisDAO.setNonce(nonce, signature.timeout() * 2, signature.timeUnit()); | ||||
|         signatureRedisDAO.setNonce(appId, nonce, signature.timeout() * 2, signature.timeUnit()); | ||||
|         return true; | ||||
|     } | ||||
|  | ||||
| @@ -113,7 +113,7 @@ public class ApiSignatureAspect { | ||||
|         } | ||||
|  | ||||
|         // 3. 检查 nonce 是否存在,有且仅能使用一次 | ||||
|         return signatureRedisDAO.getNonce(nonce) == null; | ||||
|         return signatureRedisDAO.getNonce(appId, nonce) == null; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
| @@ -165,5 +165,4 @@ public class ApiSignatureAspect { | ||||
|         return sortedMap; | ||||
|     } | ||||
|  | ||||
| } | ||||
|  | ||||
| } | ||||
| @@ -22,7 +22,7 @@ public class ApiSignatureRedisDAO { | ||||
|      * VALUE 格式:String | ||||
|      * 过期时间:不固定 | ||||
|      */ | ||||
|     private static final String SIGNATURE_NONCE = "api_signature_nonce:%s"; | ||||
|     private static final String SIGNATURE_NONCE = "api_signature_nonce:%s:%s"; | ||||
|  | ||||
|     /** | ||||
|      * 签名密钥 | ||||
| @@ -36,16 +36,16 @@ public class ApiSignatureRedisDAO { | ||||
|  | ||||
|     // ========== 验签随机数 ========== | ||||
|  | ||||
|     public String getNonce(String nonce) { | ||||
|         return stringRedisTemplate.opsForValue().get(formatNonceKey(nonce)); | ||||
|     public String getNonce(String appId, String nonce) { | ||||
|         return stringRedisTemplate.opsForValue().get(formatNonceKey(appId, nonce)); | ||||
|     } | ||||
|  | ||||
|     public void setNonce(String nonce, int time, TimeUnit timeUnit) { | ||||
|         stringRedisTemplate.opsForValue().set(formatNonceKey(nonce), "", time, timeUnit); | ||||
|     public void setNonce(String appId, String nonce, int time, TimeUnit timeUnit) { | ||||
|         stringRedisTemplate.opsForValue().set(formatNonceKey(appId, nonce), "", time, timeUnit); | ||||
|     } | ||||
|  | ||||
|     private static String formatNonceKey(String key) { | ||||
|         return String.format(SIGNATURE_NONCE, key); | ||||
|     private static String formatNonceKey(String appId, String nonce) { | ||||
|         return String.format(SIGNATURE_NONCE, appId, nonce); | ||||
|     } | ||||
|  | ||||
|     // ========== 签名密钥 ========== | ||||
|   | ||||
| @@ -69,7 +69,7 @@ public class ApiSignatureTest { | ||||
|         // 断言结果 | ||||
|         assertTrue(result); | ||||
|         // 断言调用 | ||||
|         verify(signatureRedisDAO).setNonce(eq(nonce), eq(120), eq(TimeUnit.SECONDS)); | ||||
|         verify(signatureRedisDAO).setNonce(eq(appId), eq(nonce), eq(120), eq(TimeUnit.SECONDS)); | ||||
|     } | ||||
|  | ||||
| } | ||||
| } | ||||
| @@ -11,6 +11,7 @@ import com.mzt.logapi.service.ILogRecordService; | ||||
| import jakarta.annotation.Resource; | ||||
| import jakarta.servlet.http.HttpServletRequest; | ||||
| import lombok.extern.slf4j.Slf4j; | ||||
| import org.springframework.scheduling.annotation.Async; | ||||
|  | ||||
| import java.util.List; | ||||
|  | ||||
| @@ -28,19 +29,24 @@ public class LogRecordServiceImpl implements ILogRecordService { | ||||
|     private OperateLogApi operateLogApi; | ||||
|  | ||||
|     @Override | ||||
|     @Async | ||||
|     public void record(LogRecord logRecord) { | ||||
|         // 1. 补全通用字段 | ||||
|         OperateLogCreateReqDTO reqDTO = new OperateLogCreateReqDTO(); | ||||
|         reqDTO.setTraceId(TracerUtils.getTraceId()); | ||||
|         // 补充用户信息 | ||||
|         fillUserFields(reqDTO); | ||||
|         // 补全模块信息 | ||||
|         fillModuleFields(reqDTO, logRecord); | ||||
|         // 补全请求信息 | ||||
|         fillRequestFields(reqDTO); | ||||
|         try { | ||||
|             reqDTO.setTraceId(TracerUtils.getTraceId()); | ||||
|             // 补充用户信息 | ||||
|             fillUserFields(reqDTO); | ||||
|             // 补全模块信息 | ||||
|             fillModuleFields(reqDTO, logRecord); | ||||
|             // 补全请求信息 | ||||
|             fillRequestFields(reqDTO); | ||||
|  | ||||
|         // 2. 异步记录日志 | ||||
|         operateLogApi.createOperateLog(reqDTO); | ||||
|             // 2. 异步记录日志 | ||||
|             operateLogApi.createOperateLog(reqDTO); | ||||
|         } catch (Throwable ex) { | ||||
|             // 由于 @Async 异步调用,这里打印下日志,更容易跟进 | ||||
|             log.error("[record][url({}) log({}) 发生异常]", reqDTO.getRequestUrl(), reqDTO, ex); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     private static void fillUserFields(OperateLogCreateReqDTO reqDTO) { | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 YunaiV
					YunaiV