mirror of
				https://github.com/continew-org/continew-starter.git
				synced 2025-10-31 10:57:15 +08:00 
			
		
		
		
	refactor(log): 新增 LogHandler 提升日志模块的复用性
This commit is contained in:
		| @@ -19,7 +19,9 @@ package top.continew.starter.log.aspect; | |||||||
| import jakarta.servlet.http.HttpServletRequest; | import jakarta.servlet.http.HttpServletRequest; | ||||||
| import jakarta.servlet.http.HttpServletResponse; | import jakarta.servlet.http.HttpServletResponse; | ||||||
| import org.aspectj.lang.ProceedingJoinPoint; | import org.aspectj.lang.ProceedingJoinPoint; | ||||||
| import org.aspectj.lang.annotation.*; | import org.aspectj.lang.annotation.Around; | ||||||
|  | import org.aspectj.lang.annotation.Aspect; | ||||||
|  | import org.aspectj.lang.annotation.Pointcut; | ||||||
| import org.slf4j.Logger; | import org.slf4j.Logger; | ||||||
| import org.slf4j.LoggerFactory; | import org.slf4j.LoggerFactory; | ||||||
| import org.springframework.web.context.request.RequestContextHolder; | import org.springframework.web.context.request.RequestContextHolder; | ||||||
| @@ -47,12 +49,47 @@ public class AccessLogAspect { | |||||||
|     } |     } | ||||||
|  |  | ||||||
|     /** |     /** | ||||||
|      * 切点 - 匹配所有控制器层的方法 |      * 切点 - 匹配所有控制器层的 GET 请求方法 | ||||||
|      */ |      */ | ||||||
|     @Pointcut("execution(* *..controller.*.*(..)) || execution(* *..*Controller.*(..))") |     @Pointcut("within(@org.springframework.web.bind.annotation.RequestMapping *)") | ||||||
|     public void pointcut() { |     public void pointcut() { | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 切点 - 匹配所有控制器层的 GET 请求方法 | ||||||
|  |      */ | ||||||
|  |     @Pointcut("within(@org.springframework.web.bind.annotation.GetMapping *)") | ||||||
|  |     public void pointcutGet() { | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 切点 - 匹配所有控制器层的 POST 请求方法 | ||||||
|  |      */ | ||||||
|  |     @Pointcut("within(@org.springframework.web.bind.annotation.PostMapping *)") | ||||||
|  |     public void pointcutPost() { | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 切点 - 匹配所有控制器层的 PUT 请求方法 | ||||||
|  |      */ | ||||||
|  |     @Pointcut("within(@org.springframework.web.bind.annotation.PutMapping *)") | ||||||
|  |     public void pointcutPut() { | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 切点 - 匹配所有控制器层的 DELETE 请求方法 | ||||||
|  |      */ | ||||||
|  |     @Pointcut("within(@org.springframework.web.bind.annotation.DeleteMapping *)") | ||||||
|  |     public void pointcutDelete() { | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 切点 - 匹配所有控制器层的 PATCH 请求方法 | ||||||
|  |      */ | ||||||
|  |     @Pointcut("within(@org.springframework.web.bind.annotation.PatchMapping *)") | ||||||
|  |     public void pointcutPatch() { | ||||||
|  |     } | ||||||
|  |  | ||||||
|     /** |     /** | ||||||
|      * 打印访问日志 |      * 打印访问日志 | ||||||
|      * |      * | ||||||
| @@ -60,7 +97,7 @@ public class AccessLogAspect { | |||||||
|      * @return 返回结果 |      * @return 返回结果 | ||||||
|      * @throws Throwable 异常 |      * @throws Throwable 异常 | ||||||
|      */ |      */ | ||||||
|     @Around("pointcut()") |     @Around("pointcut() || pointcutGet() || pointcutPost() || pointcutPut() || pointcutDelete() || pointcutPatch()") | ||||||
|     public Object around(ProceedingJoinPoint joinPoint) throws Throwable { |     public Object around(ProceedingJoinPoint joinPoint) throws Throwable { | ||||||
|         Instant startTime = Instant.now(); |         Instant startTime = Instant.now(); | ||||||
|         // 非 Web 环境不记录 |         // 非 Web 环境不记录 | ||||||
|   | |||||||
| @@ -32,15 +32,11 @@ import org.springframework.web.context.request.ServletRequestAttributes; | |||||||
| import top.continew.starter.log.annotation.Log; | import top.continew.starter.log.annotation.Log; | ||||||
| import top.continew.starter.log.autoconfigure.LogProperties; | import top.continew.starter.log.autoconfigure.LogProperties; | ||||||
| import top.continew.starter.log.dao.LogDao; | import top.continew.starter.log.dao.LogDao; | ||||||
| import top.continew.starter.log.enums.Include; | import top.continew.starter.log.handler.LogHandler; | ||||||
| import top.continew.starter.log.http.recordable.impl.RecordableServletHttpRequest; |  | ||||||
| import top.continew.starter.log.http.recordable.impl.RecordableServletHttpResponse; |  | ||||||
| import top.continew.starter.log.model.LogRecord; | import top.continew.starter.log.model.LogRecord; | ||||||
|  |  | ||||||
| import java.lang.reflect.Method; | import java.lang.reflect.Method; | ||||||
| import java.time.Instant; | import java.time.Instant; | ||||||
| import java.util.HashSet; |  | ||||||
| import java.util.Set; |  | ||||||
|  |  | ||||||
| /** | /** | ||||||
|  * 日志切面 |  * 日志切面 | ||||||
| @@ -53,12 +49,14 @@ import java.util.Set; | |||||||
| public class LogAspect { | public class LogAspect { | ||||||
|  |  | ||||||
|     private static final Logger log = LoggerFactory.getLogger(LogAspect.class); |     private static final Logger log = LoggerFactory.getLogger(LogAspect.class); | ||||||
|     private final LogDao logDao; |  | ||||||
|     private final LogProperties logProperties; |     private final LogProperties logProperties; | ||||||
|  |     private final LogHandler logHandler; | ||||||
|  |     private final LogDao logDao; | ||||||
|  |  | ||||||
|     public LogAspect(LogDao logDao, LogProperties logProperties) { |     public LogAspect(LogProperties logProperties, LogHandler logHandler, LogDao logDao) { | ||||||
|         this.logDao = logDao; |  | ||||||
|         this.logProperties = logProperties; |         this.logProperties = logProperties; | ||||||
|  |         this.logHandler = logHandler; | ||||||
|  |         this.logDao = logDao; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     /** |     /** | ||||||
| @@ -87,7 +85,7 @@ public class LogAspect { | |||||||
|         HttpServletResponse response = attributes.getResponse(); |         HttpServletResponse response = attributes.getResponse(); | ||||||
|         String errorMsg = null; |         String errorMsg = null; | ||||||
|         // 开始记录 |         // 开始记录 | ||||||
|         LogRecord.Started startedLogRecord = LogRecord.start(startTime, new RecordableServletHttpRequest(request)); |         LogRecord.Started startedLogRecord = logHandler.start(startTime, request); | ||||||
|         try { |         try { | ||||||
|             // 执行目标方法 |             // 执行目标方法 | ||||||
|             return joinPoint.proceed(); |             return joinPoint.proceed(); | ||||||
| @@ -95,48 +93,21 @@ public class LogAspect { | |||||||
|             errorMsg = CharSequenceUtil.sub(e.getMessage(), 0, 2000); |             errorMsg = CharSequenceUtil.sub(e.getMessage(), 0, 2000); | ||||||
|             throw e; |             throw e; | ||||||
|         } finally { |         } finally { | ||||||
|             // 结束记录 |             try { | ||||||
|             this.logFinish(startedLogRecord, errorMsg, response, joinPoint); |                 Instant endTime = Instant.now(); | ||||||
|         } |                 Method targetMethod = this.getMethod(joinPoint); | ||||||
|     } |                 Class<?> targetClass = joinPoint.getTarget().getClass(); | ||||||
|  |                 LogRecord logRecord = logHandler.finish(startedLogRecord, endTime, response, logProperties | ||||||
|     /** |                     .getIncludes(), targetMethod, targetClass); | ||||||
|      * 结束记录日志 |                 // 记录异常信息 | ||||||
|      * |                 if (errorMsg != null) { | ||||||
|      * @param startedLogRecord 日志记录器 |                     logRecord.setErrorMsg(errorMsg); | ||||||
|      * @param errorMsg         异常信息 |                 } | ||||||
|      * @param response         响应对象 |                 logDao.add(logRecord); | ||||||
|      * @param joinPoint        切点 |             } catch (Exception e) { | ||||||
|      */ |                 log.error("Logging http log occurred an error: {}.", e.getMessage(), e); | ||||||
|     private void logFinish(LogRecord.Started startedLogRecord, |                 throw e; | ||||||
|                            String errorMsg, |  | ||||||
|                            HttpServletResponse response, |  | ||||||
|                            ProceedingJoinPoint joinPoint) { |  | ||||||
|         try { |  | ||||||
|             Instant endTime = Instant.now(); |  | ||||||
|             Method method = this.getMethod(joinPoint); |  | ||||||
|             Class<?> targetClass = joinPoint.getTarget().getClass(); |  | ||||||
|             Log methodLog = method.getAnnotation(Log.class); |  | ||||||
|             Log classLog = targetClass.getAnnotation(Log.class); |  | ||||||
|             Set<Include> includeSet = this.getIncludes(methodLog, classLog); |  | ||||||
|             LogRecord finishedLogRecord = startedLogRecord |  | ||||||
|                 .finish(endTime, new RecordableServletHttpResponse(response, response.getStatus()), includeSet); |  | ||||||
|             // 记录异常信息 |  | ||||||
|             if (errorMsg != null) { |  | ||||||
|                 finishedLogRecord.setErrorMsg(errorMsg); |  | ||||||
|             } |             } | ||||||
|             // 记录日志描述 |  | ||||||
|             if (includeSet.contains(Include.DESCRIPTION)) { |  | ||||||
|                 this.logDescription(finishedLogRecord, methodLog); |  | ||||||
|             } |  | ||||||
|             // 记录所属模块 |  | ||||||
|             if (includeSet.contains(Include.MODULE)) { |  | ||||||
|                 this.logModule(finishedLogRecord, methodLog, classLog); |  | ||||||
|             } |  | ||||||
|             logDao.add(finishedLogRecord); |  | ||||||
|         } catch (Exception e) { |  | ||||||
|             log.error("Logging http log occurred an error: {}.", e.getMessage(), e); |  | ||||||
|             throw e; |  | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
| @@ -150,74 +121,4 @@ public class LogAspect { | |||||||
|         MethodSignature signature = (MethodSignature)joinPoint.getSignature(); |         MethodSignature signature = (MethodSignature)joinPoint.getSignature(); | ||||||
|         return signature.getMethod(); |         return signature.getMethod(); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     /** |  | ||||||
|      * 获取日志包含信息 |  | ||||||
|      * |  | ||||||
|      * @param methodLog 方法级 Log 注解 |  | ||||||
|      * @param classLog  类级 Log 注解 |  | ||||||
|      * @return 日志包含信息 |  | ||||||
|      */ |  | ||||||
|     private Set<Include> getIncludes(Log methodLog, Log classLog) { |  | ||||||
|         Set<Include> includeSet = new HashSet<>(logProperties.getIncludes()); |  | ||||||
|         if (null != classLog) { |  | ||||||
|             processInclude(includeSet, classLog); |  | ||||||
|         } |  | ||||||
|         if (null != methodLog) { |  | ||||||
|             processInclude(includeSet, methodLog); |  | ||||||
|         } |  | ||||||
|         return includeSet; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     /** |  | ||||||
|      * 处理日志包含信息 |  | ||||||
|      * |  | ||||||
|      * @param includes      日志包含信息 |  | ||||||
|      * @param logAnnotation Log 注解 |  | ||||||
|      */ |  | ||||||
|     private void processInclude(Set<Include> includes, Log logAnnotation) { |  | ||||||
|         Include[] includeArr = logAnnotation.includes(); |  | ||||||
|         if (includeArr.length > 0) { |  | ||||||
|             includes.addAll(Set.of(includeArr)); |  | ||||||
|         } |  | ||||||
|         Include[] excludeArr = logAnnotation.excludes(); |  | ||||||
|         if (excludeArr.length > 0) { |  | ||||||
|             includes.removeAll(Set.of(excludeArr)); |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     /** |  | ||||||
|      * 记录描述 |  | ||||||
|      * |  | ||||||
|      * @param logRecord 日志信息 |  | ||||||
|      * @param methodLog 方法级 Log 注解 |  | ||||||
|      */ |  | ||||||
|     private void logDescription(LogRecord logRecord, Log methodLog) { |  | ||||||
|         // 例如:@Log("新增部门") -> 新增部门 |  | ||||||
|         if (null != methodLog && CharSequenceUtil.isNotBlank(methodLog.value())) { |  | ||||||
|             logRecord.setDescription(methodLog.value()); |  | ||||||
|         } else { |  | ||||||
|             logRecord.setDescription("请在该接口方法上指定日志描述"); |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     /** |  | ||||||
|      * 记录模块 |  | ||||||
|      * |  | ||||||
|      * @param logRecord 日志信息 |  | ||||||
|      * @param methodLog 方法级 Log 注解 |  | ||||||
|      * @param classLog  类级 Log 注解 |  | ||||||
|      */ |  | ||||||
|     private void logModule(LogRecord logRecord, Log methodLog, Log classLog) { |  | ||||||
|         // 例如:@Log(module = "部门管理") -> 部门管理 |  | ||||||
|         // 优先使用方法注解的模块 |  | ||||||
|         if (null != methodLog && CharSequenceUtil.isNotBlank(methodLog.module())) { |  | ||||||
|             logRecord.setModule(methodLog.module()); |  | ||||||
|             return; |  | ||||||
|         } |  | ||||||
|         // 其次使用类注解的模块 |  | ||||||
|         if (null != classLog) { |  | ||||||
|             logRecord.setModule(CharSequenceUtil.blankToDefault(classLog.module(), "请在该接口类上指定所属模块")); |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
| } | } | ||||||
|   | |||||||
| @@ -29,6 +29,8 @@ import top.continew.starter.log.aspect.AccessLogAspect; | |||||||
| import top.continew.starter.log.aspect.LogAspect; | import top.continew.starter.log.aspect.LogAspect; | ||||||
| import top.continew.starter.log.dao.LogDao; | import top.continew.starter.log.dao.LogDao; | ||||||
| import top.continew.starter.log.dao.impl.DefaultLogDaoImpl; | import top.continew.starter.log.dao.impl.DefaultLogDaoImpl; | ||||||
|  | import top.continew.starter.log.handler.AopLogHandler; | ||||||
|  | import top.continew.starter.log.handler.LogHandler; | ||||||
|  |  | ||||||
| /** | /** | ||||||
|  * 日志自动配置 |  * 日志自动配置 | ||||||
| @@ -53,12 +55,14 @@ public class LogAutoConfiguration { | |||||||
|     /** |     /** | ||||||
|      * 日志切面 |      * 日志切面 | ||||||
|      * |      * | ||||||
|  |      * @param logHandler 日志处理器 | ||||||
|  |      * @param logDao     日志持久层接口 | ||||||
|      * @return {@link LogAspect } |      * @return {@link LogAspect } | ||||||
|      */ |      */ | ||||||
|     @Bean |     @Bean | ||||||
|     @ConditionalOnMissingBean |     @ConditionalOnMissingBean | ||||||
|     public LogAspect logAspect(LogDao logDao) { |     public LogAspect logAspect(LogHandler logHandler, LogDao logDao) { | ||||||
|         return new LogAspect(logDao, logProperties); |         return new LogAspect(logProperties, logHandler, logDao); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     /** |     /** | ||||||
| @@ -72,6 +76,15 @@ public class LogAutoConfiguration { | |||||||
|         return new AccessLogAspect(logProperties); |         return new AccessLogAspect(logProperties); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 日志处理器 | ||||||
|  |      */ | ||||||
|  |     @Bean | ||||||
|  |     @ConditionalOnMissingBean | ||||||
|  |     public LogHandler logHandler() { | ||||||
|  |         return new AopLogHandler(); | ||||||
|  |     } | ||||||
|  |  | ||||||
|     /** |     /** | ||||||
|      * 日志持久层接口 |      * 日志持久层接口 | ||||||
|      */ |      */ | ||||||
|   | |||||||
| @@ -0,0 +1,47 @@ | |||||||
|  | /* | ||||||
|  |  * Copyright (c) 2022-present Charles7c Authors. All Rights Reserved. | ||||||
|  |  * <p> | ||||||
|  |  * Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0; | ||||||
|  |  * you may not use this file except in compliance with the License. | ||||||
|  |  * You may obtain a copy of the License at | ||||||
|  |  * <p> | ||||||
|  |  * http://www.gnu.org/licenses/lgpl.html | ||||||
|  |  * <p> | ||||||
|  |  * Unless required by applicable law or agreed to in writing, software | ||||||
|  |  * distributed under the License is distributed on an "AS IS" BASIS, | ||||||
|  |  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||||
|  |  * See the License for the specific language governing permissions and | ||||||
|  |  * limitations under the License. | ||||||
|  |  */ | ||||||
|  |  | ||||||
|  | package top.continew.starter.log.handler; | ||||||
|  |  | ||||||
|  | import cn.hutool.core.text.CharSequenceUtil; | ||||||
|  | import top.continew.starter.log.model.LogRecord; | ||||||
|  |  | ||||||
|  | import java.lang.reflect.Method; | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * 日志处理器-AOP 版实现 | ||||||
|  |  * | ||||||
|  |  * @author Charles7c | ||||||
|  |  * @since 2.8.0 | ||||||
|  |  */ | ||||||
|  | public class AopLogHandler extends AbstractLogHandler { | ||||||
|  |  | ||||||
|  |     @Override | ||||||
|  |     public void logDescription(LogRecord logRecord, Method targetMethod) { | ||||||
|  |         super.logDescription(logRecord, targetMethod); | ||||||
|  |         if (CharSequenceUtil.isBlank(logRecord.getDescription())) { | ||||||
|  |             logRecord.setDescription("请在该接口方法上指定日志描述"); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     @Override | ||||||
|  |     public void logModule(LogRecord logRecord, Method targetMethod, Class<?> targetClass) { | ||||||
|  |         super.logModule(logRecord, targetMethod, targetClass); | ||||||
|  |         if (CharSequenceUtil.isBlank(logRecord.getModule())) { | ||||||
|  |             logRecord.setModule("请在该接口类上指定所属模块"); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
| @@ -0,0 +1,143 @@ | |||||||
|  | /* | ||||||
|  |  * Copyright (c) 2022-present Charles7c Authors. All Rights Reserved. | ||||||
|  |  * <p> | ||||||
|  |  * Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0; | ||||||
|  |  * you may not use this file except in compliance with the License. | ||||||
|  |  * You may obtain a copy of the License at | ||||||
|  |  * <p> | ||||||
|  |  * http://www.gnu.org/licenses/lgpl.html | ||||||
|  |  * <p> | ||||||
|  |  * Unless required by applicable law or agreed to in writing, software | ||||||
|  |  * distributed under the License is distributed on an "AS IS" BASIS, | ||||||
|  |  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||||
|  |  * See the License for the specific language governing permissions and | ||||||
|  |  * limitations under the License. | ||||||
|  |  */ | ||||||
|  |  | ||||||
|  | package top.continew.starter.log.handler; | ||||||
|  |  | ||||||
|  | import cn.hutool.core.annotation.AnnotationUtil; | ||||||
|  | import cn.hutool.core.text.CharSequenceUtil; | ||||||
|  | import jakarta.servlet.http.HttpServletRequest; | ||||||
|  | import jakarta.servlet.http.HttpServletResponse; | ||||||
|  | import top.continew.starter.log.annotation.Log; | ||||||
|  | import top.continew.starter.log.enums.Include; | ||||||
|  | import top.continew.starter.log.http.recordable.impl.RecordableServletHttpRequest; | ||||||
|  | import top.continew.starter.log.http.recordable.impl.RecordableServletHttpResponse; | ||||||
|  | import top.continew.starter.log.model.LogRecord; | ||||||
|  |  | ||||||
|  | import java.lang.reflect.Method; | ||||||
|  | import java.time.Instant; | ||||||
|  | import java.util.HashSet; | ||||||
|  | import java.util.Set; | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * 日志处理器基类 | ||||||
|  |  * | ||||||
|  |  * @author Charles7c | ||||||
|  |  * @since 2.8.0 | ||||||
|  |  */ | ||||||
|  | public abstract class AbstractLogHandler implements LogHandler { | ||||||
|  |  | ||||||
|  |     @Override | ||||||
|  |     public LogRecord.Started start(Instant startTime, HttpServletRequest request) { | ||||||
|  |         return LogRecord.start(startTime, new RecordableServletHttpRequest(request)); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     @Override | ||||||
|  |     public LogRecord finish(LogRecord.Started started, | ||||||
|  |                             Instant endTime, | ||||||
|  |                             HttpServletResponse response, | ||||||
|  |                             Set<Include> includes, | ||||||
|  |                             Method targetMethod, | ||||||
|  |                             Class<?> targetClass) { | ||||||
|  |         Set<Include> includeSet = this.getIncludes(includes, targetMethod, targetClass); | ||||||
|  |         LogRecord logRecord = this.finish(started, endTime, response, includeSet); | ||||||
|  |         // 记录日志描述 | ||||||
|  |         if (includeSet.contains(Include.DESCRIPTION)) { | ||||||
|  |             this.logDescription(logRecord, targetMethod); | ||||||
|  |         } | ||||||
|  |         // 记录所属模块 | ||||||
|  |         if (includeSet.contains(Include.MODULE)) { | ||||||
|  |             this.logModule(logRecord, targetMethod, targetClass); | ||||||
|  |         } | ||||||
|  |         return logRecord; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     @Override | ||||||
|  |     public LogRecord finish(LogRecord.Started started, | ||||||
|  |                             Instant endTime, | ||||||
|  |                             HttpServletResponse response, | ||||||
|  |                             Set<Include> includes) { | ||||||
|  |         return started.finish(endTime, new RecordableServletHttpResponse(response, response.getStatus()), includes); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 记录日志描述 | ||||||
|  |      * | ||||||
|  |      * @param logRecord    日志记录 | ||||||
|  |      * @param targetMethod 目标方法 | ||||||
|  |      */ | ||||||
|  |     @Override | ||||||
|  |     public void logDescription(LogRecord logRecord, Method targetMethod) { | ||||||
|  |         Log methodLog = AnnotationUtil.getAnnotation(targetMethod, Log.class); | ||||||
|  |         // 例如:@Log("新增部门") -> 新增部门 | ||||||
|  |         if (null != methodLog && CharSequenceUtil.isNotBlank(methodLog.value())) { | ||||||
|  |             logRecord.setDescription(methodLog.value()); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 记录所属模块 | ||||||
|  |      * | ||||||
|  |      * @param logRecord    日志记录 | ||||||
|  |      * @param targetMethod 目标方法 | ||||||
|  |      * @param targetClass  目标类 | ||||||
|  |      */ | ||||||
|  |     @Override | ||||||
|  |     public void logModule(LogRecord logRecord, Method targetMethod, Class<?> targetClass) { | ||||||
|  |         Log methodLog = AnnotationUtil.getAnnotation(targetMethod, Log.class); | ||||||
|  |         // 例如:@Log(module = "部门管理") -> 部门管理 | ||||||
|  |         // 方法级注解优先级高于类级注解 | ||||||
|  |         if (null != methodLog && CharSequenceUtil.isNotBlank(methodLog.module())) { | ||||||
|  |             logRecord.setModule(methodLog.module()); | ||||||
|  |             return; | ||||||
|  |         } | ||||||
|  |         Log classLog = AnnotationUtil.getAnnotation(targetClass, Log.class); | ||||||
|  |         if (null != classLog && CharSequenceUtil.isNotBlank(classLog.module())) { | ||||||
|  |             logRecord.setModule(classLog.module()); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     @Override | ||||||
|  |     public Set<Include> getIncludes(Set<Include> includes, Method targetMethod, Class<?> targetClass) { | ||||||
|  |         Log classLog = AnnotationUtil.getAnnotation(targetClass, Log.class); | ||||||
|  |         Set<Include> includeSet = new HashSet<>(includes); | ||||||
|  |         if (null != classLog) { | ||||||
|  |             this.processInclude(includeSet, classLog); | ||||||
|  |         } | ||||||
|  |         // 方法级注解优先级高于类级注解 | ||||||
|  |         Log methodLog = AnnotationUtil.getAnnotation(targetMethod, Log.class); | ||||||
|  |         if (null != methodLog) { | ||||||
|  |             this.processInclude(includeSet, methodLog); | ||||||
|  |         } | ||||||
|  |         return includeSet; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 处理日志包含信息 | ||||||
|  |      * | ||||||
|  |      * @param includes      日志包含信息 | ||||||
|  |      * @param logAnnotation Log 注解 | ||||||
|  |      */ | ||||||
|  |     private void processInclude(Set<Include> includes, Log logAnnotation) { | ||||||
|  |         Include[] includeArr = logAnnotation.includes(); | ||||||
|  |         if (includeArr.length > 0) { | ||||||
|  |             includes.addAll(Set.of(includeArr)); | ||||||
|  |         } | ||||||
|  |         Include[] excludeArr = logAnnotation.excludes(); | ||||||
|  |         if (excludeArr.length > 0) { | ||||||
|  |             includes.removeAll(Set.of(excludeArr)); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
| @@ -0,0 +1,100 @@ | |||||||
|  | /* | ||||||
|  |  * Copyright (c) 2022-present Charles7c Authors. All Rights Reserved. | ||||||
|  |  * <p> | ||||||
|  |  * Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0; | ||||||
|  |  * you may not use this file except in compliance with the License. | ||||||
|  |  * You may obtain a copy of the License at | ||||||
|  |  * <p> | ||||||
|  |  * http://www.gnu.org/licenses/lgpl.html | ||||||
|  |  * <p> | ||||||
|  |  * Unless required by applicable law or agreed to in writing, software | ||||||
|  |  * distributed under the License is distributed on an "AS IS" BASIS, | ||||||
|  |  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||||
|  |  * See the License for the specific language governing permissions and | ||||||
|  |  * limitations under the License. | ||||||
|  |  */ | ||||||
|  |  | ||||||
|  | package top.continew.starter.log.handler; | ||||||
|  |  | ||||||
|  | import jakarta.servlet.http.HttpServletRequest; | ||||||
|  | import jakarta.servlet.http.HttpServletResponse; | ||||||
|  | import top.continew.starter.log.enums.Include; | ||||||
|  | import top.continew.starter.log.model.LogRecord; | ||||||
|  |  | ||||||
|  | import java.lang.reflect.Method; | ||||||
|  | import java.time.Instant; | ||||||
|  | import java.util.Set; | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * 日志处理器 | ||||||
|  |  * | ||||||
|  |  * @author Charles7c | ||||||
|  |  * @since 2.8.0 | ||||||
|  |  */ | ||||||
|  | public interface LogHandler { | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 开始日志记录 | ||||||
|  |      * | ||||||
|  |      * @param startTime 开始时间 | ||||||
|  |      * @param request   请求对象 | ||||||
|  |      * @return 日志记录器 | ||||||
|  |      */ | ||||||
|  |     LogRecord.Started start(Instant startTime, HttpServletRequest request); | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 结束日志记录 | ||||||
|  |      * | ||||||
|  |      * @param started  开始日志记录器 | ||||||
|  |      * @param endTime  结束时间 | ||||||
|  |      * @param response 响应对象 | ||||||
|  |      * @param includes 包含信息 | ||||||
|  |      * @return 日志记录 | ||||||
|  |      */ | ||||||
|  |     LogRecord finish(LogRecord.Started started, Instant endTime, HttpServletResponse response, Set<Include> includes); | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 结束日志记录 | ||||||
|  |      * | ||||||
|  |      * @param started      开始日志记录器- | ||||||
|  |      * @param endTime      结束时间 | ||||||
|  |      * @param response     响应对象 | ||||||
|  |      * @param includes     包含信息 | ||||||
|  |      * @param targetMethod 目标方法 | ||||||
|  |      * @param targetClass  目标类 | ||||||
|  |      * @return 日志记录 | ||||||
|  |      */ | ||||||
|  |     LogRecord finish(LogRecord.Started started, | ||||||
|  |                      Instant endTime, | ||||||
|  |                      HttpServletResponse response, | ||||||
|  |                      Set<Include> includes, | ||||||
|  |                      Method targetMethod, | ||||||
|  |                      Class<?> targetClass); | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 记录日志描述 | ||||||
|  |      * | ||||||
|  |      * @param logRecord    日志记录 | ||||||
|  |      * @param targetMethod 目标方法 | ||||||
|  |      */ | ||||||
|  |     void logDescription(LogRecord logRecord, Method targetMethod); | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 记录所属模块 | ||||||
|  |      * | ||||||
|  |      * @param logRecord    日志记录 | ||||||
|  |      * @param targetMethod 目标方法 | ||||||
|  |      * @param targetClass  目标类 | ||||||
|  |      */ | ||||||
|  |     void logModule(LogRecord logRecord, Method targetMethod, Class<?> targetClass); | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 获取日志包含信息 | ||||||
|  |      * | ||||||
|  |      * @param includes     默认包含信息 | ||||||
|  |      * @param targetMethod 目标方法 | ||||||
|  |      * @param targetClass  目标类 | ||||||
|  |      * @return 日志包含信息 | ||||||
|  |      */ | ||||||
|  |     Set<Include> getIncludes(Set<Include> includes, Method targetMethod, Class<?> targetClass); | ||||||
|  | } | ||||||
| @@ -26,11 +26,13 @@ import org.springframework.context.annotation.Bean; | |||||||
| import org.springframework.context.annotation.Configuration; | import org.springframework.context.annotation.Configuration; | ||||||
| import org.springframework.web.servlet.config.annotation.InterceptorRegistry; | import org.springframework.web.servlet.config.annotation.InterceptorRegistry; | ||||||
| import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; | import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; | ||||||
|  | import top.continew.starter.log.annotation.ConditionalOnEnabledLog; | ||||||
| import top.continew.starter.log.dao.LogDao; | import top.continew.starter.log.dao.LogDao; | ||||||
| import top.continew.starter.log.dao.impl.DefaultLogDaoImpl; | import top.continew.starter.log.dao.impl.DefaultLogDaoImpl; | ||||||
| import top.continew.starter.log.annotation.ConditionalOnEnabledLog; | import top.continew.starter.log.handler.InterceptorLogHandler; | ||||||
| import top.continew.starter.log.handler.LogFilter; | import top.continew.starter.log.handler.LogFilter; | ||||||
| import top.continew.starter.log.handler.LogInterceptor; | import top.continew.starter.log.handler.LogHandler; | ||||||
|  | import top.continew.starter.log.interceptor.LogInterceptor; | ||||||
|  |  | ||||||
| /** | /** | ||||||
|  * 日志自动配置 |  * 日志自动配置 | ||||||
| @@ -53,7 +55,7 @@ public class LogAutoConfiguration implements WebMvcConfigurer { | |||||||
|  |  | ||||||
|     @Override |     @Override | ||||||
|     public void addInterceptors(InterceptorRegistry registry) { |     public void addInterceptors(InterceptorRegistry registry) { | ||||||
|         registry.addInterceptor(new LogInterceptor(logDao(), logProperties)); |         registry.addInterceptor(new LogInterceptor(logProperties, logHandler(), logDao())); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     /** |     /** | ||||||
| @@ -65,6 +67,15 @@ public class LogAutoConfiguration implements WebMvcConfigurer { | |||||||
|         return new LogFilter(logProperties); |         return new LogFilter(logProperties); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 日志处理器 | ||||||
|  |      */ | ||||||
|  |     @Bean | ||||||
|  |     @ConditionalOnMissingBean | ||||||
|  |     public LogHandler logHandler() { | ||||||
|  |         return new InterceptorLogHandler(); | ||||||
|  |     } | ||||||
|  |  | ||||||
|     /** |     /** | ||||||
|      * 日志持久层接口 |      * 日志持久层接口 | ||||||
|      */ |      */ | ||||||
|   | |||||||
| @@ -0,0 +1,61 @@ | |||||||
|  | /* | ||||||
|  |  * Copyright (c) 2022-present Charles7c Authors. All Rights Reserved. | ||||||
|  |  * <p> | ||||||
|  |  * Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0; | ||||||
|  |  * you may not use this file except in compliance with the License. | ||||||
|  |  * You may obtain a copy of the License at | ||||||
|  |  * <p> | ||||||
|  |  * http://www.gnu.org/licenses/lgpl.html | ||||||
|  |  * <p> | ||||||
|  |  * Unless required by applicable law or agreed to in writing, software | ||||||
|  |  * distributed under the License is distributed on an "AS IS" BASIS, | ||||||
|  |  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||||
|  |  * See the License for the specific language governing permissions and | ||||||
|  |  * limitations under the License. | ||||||
|  |  */ | ||||||
|  |  | ||||||
|  | package top.continew.starter.log.handler; | ||||||
|  |  | ||||||
|  | import cn.hutool.core.annotation.AnnotationUtil; | ||||||
|  | import cn.hutool.core.text.CharSequenceUtil; | ||||||
|  | import io.swagger.v3.oas.annotations.Operation; | ||||||
|  | import io.swagger.v3.oas.annotations.tags.Tag; | ||||||
|  | import top.continew.starter.log.model.LogRecord; | ||||||
|  |  | ||||||
|  | import java.lang.reflect.Method; | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * 日志处理器-拦截器版实现 | ||||||
|  |  * | ||||||
|  |  * @author Charles7c | ||||||
|  |  * @since 2.8.0 | ||||||
|  |  */ | ||||||
|  | public class InterceptorLogHandler extends AbstractLogHandler { | ||||||
|  |  | ||||||
|  |     @Override | ||||||
|  |     public void logDescription(LogRecord logRecord, Method targetMethod) { | ||||||
|  |         super.logDescription(logRecord, targetMethod); | ||||||
|  |         if (CharSequenceUtil.isNotBlank(logRecord.getDescription())) { | ||||||
|  |             return; | ||||||
|  |         } | ||||||
|  |         // 例如:@Operation(summary="新增部门") -> 新增部门 | ||||||
|  |         Operation methodOperation = AnnotationUtil.getAnnotation(targetMethod, Operation.class); | ||||||
|  |         if (null != methodOperation) { | ||||||
|  |             logRecord.setDescription(CharSequenceUtil.blankToDefault(methodOperation.summary(), "请在该接口方法上指定日志描述")); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     @Override | ||||||
|  |     public void logModule(LogRecord logRecord, Method targetMethod, Class<?> targetClass) { | ||||||
|  |         super.logModule(logRecord, targetMethod, targetClass); | ||||||
|  |         if (CharSequenceUtil.isNotBlank(logRecord.getModule())) { | ||||||
|  |             return; | ||||||
|  |         } | ||||||
|  |         // 例如:@Tag(name = "部门管理") -> 部门管理 | ||||||
|  |         Tag classTag = AnnotationUtil.getAnnotation(targetClass, Tag.class); | ||||||
|  |         if (null != classTag) { | ||||||
|  |             String name = classTag.name(); | ||||||
|  |             logRecord.setModule(CharSequenceUtil.blankToDefault(name, "请在该接口类上指定所属模块")); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
| @@ -14,13 +14,11 @@ | |||||||
|  * limitations under the License. |  * limitations under the License. | ||||||
|  */ |  */ | ||||||
| 
 | 
 | ||||||
| package top.continew.starter.log.handler; | package top.continew.starter.log.interceptor; | ||||||
| 
 | 
 | ||||||
| import cn.hutool.core.text.CharSequenceUtil; |  | ||||||
| import com.alibaba.ttl.TransmittableThreadLocal; | import com.alibaba.ttl.TransmittableThreadLocal; | ||||||
| import io.swagger.v3.oas.annotations.Hidden; | import io.swagger.v3.oas.annotations.Hidden; | ||||||
| import io.swagger.v3.oas.annotations.Operation; | import io.swagger.v3.oas.annotations.Operation; | ||||||
| import io.swagger.v3.oas.annotations.tags.Tag; |  | ||||||
| import jakarta.servlet.http.HttpServletRequest; | import jakarta.servlet.http.HttpServletRequest; | ||||||
| import jakarta.servlet.http.HttpServletResponse; | import jakarta.servlet.http.HttpServletResponse; | ||||||
| import org.slf4j.Logger; | import org.slf4j.Logger; | ||||||
| @@ -28,18 +26,15 @@ import org.slf4j.LoggerFactory; | |||||||
| import org.springframework.lang.NonNull; | import org.springframework.lang.NonNull; | ||||||
| import org.springframework.web.method.HandlerMethod; | import org.springframework.web.method.HandlerMethod; | ||||||
| import org.springframework.web.servlet.HandlerInterceptor; | import org.springframework.web.servlet.HandlerInterceptor; | ||||||
| import top.continew.starter.log.http.recordable.impl.RecordableServletHttpRequest; |  | ||||||
| import top.continew.starter.log.http.recordable.impl.RecordableServletHttpResponse; |  | ||||||
| import top.continew.starter.log.annotation.Log; | import top.continew.starter.log.annotation.Log; | ||||||
| import top.continew.starter.log.dao.LogDao; |  | ||||||
| import top.continew.starter.log.enums.Include; |  | ||||||
| import top.continew.starter.log.model.LogRecord; |  | ||||||
| import top.continew.starter.log.autoconfigure.LogProperties; | import top.continew.starter.log.autoconfigure.LogProperties; | ||||||
|  | import top.continew.starter.log.dao.LogDao; | ||||||
|  | import top.continew.starter.log.handler.LogHandler; | ||||||
|  | import top.continew.starter.log.model.LogRecord; | ||||||
| 
 | 
 | ||||||
|  | import java.lang.reflect.Method; | ||||||
| import java.time.Duration; | import java.time.Duration; | ||||||
| import java.time.Instant; | import java.time.Instant; | ||||||
| import java.util.HashSet; |  | ||||||
| import java.util.Set; |  | ||||||
| 
 | 
 | ||||||
| /** | /** | ||||||
|  * 日志拦截器 |  * 日志拦截器 | ||||||
| @@ -50,14 +45,16 @@ import java.util.Set; | |||||||
| public class LogInterceptor implements HandlerInterceptor { | public class LogInterceptor implements HandlerInterceptor { | ||||||
| 
 | 
 | ||||||
|     private static final Logger log = LoggerFactory.getLogger(LogInterceptor.class); |     private static final Logger log = LoggerFactory.getLogger(LogInterceptor.class); | ||||||
|     private final LogDao logDao; |  | ||||||
|     private final LogProperties logProperties; |     private final LogProperties logProperties; | ||||||
|  |     private final LogHandler logHandler; | ||||||
|  |     private final LogDao logDao; | ||||||
|     private final TransmittableThreadLocal<Instant> timeTtl = new TransmittableThreadLocal<>(); |     private final TransmittableThreadLocal<Instant> timeTtl = new TransmittableThreadLocal<>(); | ||||||
|     private final TransmittableThreadLocal<LogRecord.Started> logTtl = new TransmittableThreadLocal<>(); |     private final TransmittableThreadLocal<LogRecord.Started> logTtl = new TransmittableThreadLocal<>(); | ||||||
| 
 | 
 | ||||||
|     public LogInterceptor(LogDao logDao, LogProperties logProperties) { |     public LogInterceptor(LogProperties logProperties, LogHandler logHandler, LogDao logDao) { | ||||||
|         this.logDao = logDao; |  | ||||||
|         this.logProperties = logProperties; |         this.logProperties = logProperties; | ||||||
|  |         this.logHandler = logHandler; | ||||||
|  |         this.logDao = logDao; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     @Override |     @Override | ||||||
| @@ -69,8 +66,9 @@ public class LogInterceptor implements HandlerInterceptor { | |||||||
|             log.info("[{}] {}", request.getMethod(), request.getRequestURI()); |             log.info("[{}] {}", request.getMethod(), request.getRequestURI()); | ||||||
|             timeTtl.set(startTime); |             timeTtl.set(startTime); | ||||||
|         } |         } | ||||||
|  |         // 开始日志记录 | ||||||
|         if (this.isRequestRecord(handler, request)) { |         if (this.isRequestRecord(handler, request)) { | ||||||
|             LogRecord.Started startedLogRecord = LogRecord.start(startTime, new RecordableServletHttpRequest(request)); |             LogRecord.Started startedLogRecord = logHandler.start(startTime, request); | ||||||
|             logTtl.set(startedLogRecord); |             logTtl.set(startedLogRecord); | ||||||
|         } |         } | ||||||
|         return true; |         return true; | ||||||
| @@ -92,21 +90,13 @@ public class LogInterceptor implements HandlerInterceptor { | |||||||
|             if (null == startedLogRecord) { |             if (null == startedLogRecord) { | ||||||
|                 return; |                 return; | ||||||
|             } |             } | ||||||
|  |             // 结束日志记录 | ||||||
|             HandlerMethod handlerMethod = (HandlerMethod)handler; |             HandlerMethod handlerMethod = (HandlerMethod)handler; | ||||||
|             Log methodLog = handlerMethod.getMethodAnnotation(Log.class); |             Method targetMethod = handlerMethod.getMethod(); | ||||||
|             Log classLog = handlerMethod.getBeanType().getDeclaredAnnotation(Log.class); |             Class<?> targetClass = handlerMethod.getBeanType(); | ||||||
|             Set<Include> includeSet = this.getIncludes(methodLog, classLog); |             LogRecord logRecord = logHandler.finish(startedLogRecord, endTime, response, logProperties | ||||||
|             LogRecord finishedLogRecord = startedLogRecord |                 .getIncludes(), targetMethod, targetClass); | ||||||
|                 .finish(endTime, new RecordableServletHttpResponse(response, response.getStatus()), includeSet); |             logDao.add(logRecord); | ||||||
|             // 记录日志描述 |  | ||||||
|             if (includeSet.contains(Include.DESCRIPTION)) { |  | ||||||
|                 this.logDescription(finishedLogRecord, methodLog, handlerMethod); |  | ||||||
|             } |  | ||||||
|             // 记录所属模块 |  | ||||||
|             if (includeSet.contains(Include.MODULE)) { |  | ||||||
|                 this.logModule(finishedLogRecord, methodLog, classLog, handlerMethod); |  | ||||||
|             } |  | ||||||
|             logDao.add(finishedLogRecord); |  | ||||||
|         } catch (Exception ex) { |         } catch (Exception ex) { | ||||||
|             log.error("Logging http log occurred an error: {}.", ex.getMessage(), ex); |             log.error("Logging http log occurred an error: {}.", ex.getMessage(), ex); | ||||||
|             throw ex; |             throw ex; | ||||||
| @@ -116,87 +106,6 @@ public class LogInterceptor implements HandlerInterceptor { | |||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     /** |  | ||||||
|      * 获取日志包含信息 |  | ||||||
|      * |  | ||||||
|      * @param methodLog 方法级 Log 注解 |  | ||||||
|      * @param classLog  类级 Log 注解 |  | ||||||
|      * @return 日志包含信息 |  | ||||||
|      */ |  | ||||||
|     private Set<Include> getIncludes(Log methodLog, Log classLog) { |  | ||||||
|         Set<Include> includeSet = new HashSet<>(logProperties.getIncludes()); |  | ||||||
|         if (null != classLog) { |  | ||||||
|             this.processInclude(includeSet, classLog); |  | ||||||
|         } |  | ||||||
|         if (null != methodLog) { |  | ||||||
|             this.processInclude(includeSet, methodLog); |  | ||||||
|         } |  | ||||||
|         return includeSet; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     /** |  | ||||||
|      * 处理日志包含信息 |  | ||||||
|      * |  | ||||||
|      * @param includes      日志包含信息 |  | ||||||
|      * @param logAnnotation Log 注解 |  | ||||||
|      */ |  | ||||||
|     private void processInclude(Set<Include> includes, Log logAnnotation) { |  | ||||||
|         Include[] includeArr = logAnnotation.includes(); |  | ||||||
|         if (includeArr.length > 0) { |  | ||||||
|             includes.addAll(Set.of(includeArr)); |  | ||||||
|         } |  | ||||||
|         Include[] excludeArr = logAnnotation.excludes(); |  | ||||||
|         if (excludeArr.length > 0) { |  | ||||||
|             includes.removeAll(Set.of(excludeArr)); |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     /** |  | ||||||
|      * 记录描述 |  | ||||||
|      * |  | ||||||
|      * @param logRecord     日志信息 |  | ||||||
|      * @param methodLog     方法级 Log 注解 |  | ||||||
|      * @param handlerMethod 处理器方法 |  | ||||||
|      */ |  | ||||||
|     private void logDescription(LogRecord logRecord, Log methodLog, HandlerMethod handlerMethod) { |  | ||||||
|         // 例如:@Log("新增部门") -> 新增部门 |  | ||||||
|         if (null != methodLog && CharSequenceUtil.isNotBlank(methodLog.value())) { |  | ||||||
|             logRecord.setDescription(methodLog.value()); |  | ||||||
|             return; |  | ||||||
|         } |  | ||||||
|         // 例如:@Operation(summary="新增部门") -> 新增部门 |  | ||||||
|         Operation methodOperation = handlerMethod.getMethodAnnotation(Operation.class); |  | ||||||
|         if (null != methodOperation) { |  | ||||||
|             logRecord.setDescription(CharSequenceUtil.blankToDefault(methodOperation.summary(), "请在该接口方法上指定日志描述")); |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     /** |  | ||||||
|      * 记录模块 |  | ||||||
|      * |  | ||||||
|      * @param logRecord     日志信息 |  | ||||||
|      * @param methodLog     方法级 Log 注解 |  | ||||||
|      * @param classLog      类级 Log 注解 |  | ||||||
|      * @param handlerMethod 处理器方法 |  | ||||||
|      */ |  | ||||||
|     private void logModule(LogRecord logRecord, Log methodLog, Log classLog, HandlerMethod handlerMethod) { |  | ||||||
|         // 例如:@Log(module = "部门管理") -> 部门管理 |  | ||||||
|         if (null != methodLog && CharSequenceUtil.isNotBlank(methodLog.module())) { |  | ||||||
|             logRecord.setModule(methodLog.module()); |  | ||||||
|             return; |  | ||||||
|         } |  | ||||||
|         if (null != classLog && CharSequenceUtil.isNotBlank(classLog.module())) { |  | ||||||
|             logRecord.setModule(classLog.module()); |  | ||||||
|             return; |  | ||||||
|         } |  | ||||||
|         // 例如:@Tag(name = "部门管理") -> 部门管理 |  | ||||||
|         Tag classTag = handlerMethod.getBeanType().getDeclaredAnnotation(Tag.class); |  | ||||||
|         if (null != classTag) { |  | ||||||
|             String name = classTag.name(); |  | ||||||
|             logRecord.setModule(CharSequenceUtil.blankToDefault(name, "请在该接口类上指定所属模块")); |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     /** |     /** | ||||||
|      * 是否要记录日志 |      * 是否要记录日志 | ||||||
|      * |      * | ||||||
		Reference in New Issue
	
	Block a user