From fb918e67fbdf5f57449b6c97a7b553332e2e2c76 Mon Sep 17 00:00:00 2001 From: wangyu <727842003@qq.com> Date: Thu, 14 Jan 2021 12:07:00 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=8F=90=E4=BA=A4=E6=97=A5=E5=BF=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../framework/utils/ReflectionUtils.java | 15 ++++ .../framework/logging/advice/LogAdvice.java | 23 +++-- .../logging/config/LoggingConfig.java | 14 +++ .../logging/config/LoggingTextModifier.java | 15 ++++ .../logging/config/LoggingTextRegistry.java | 26 ++++++ .../logging/domain/DomainDescriptions.java | 36 ++++++++ .../framework/logging/service/LogManager.java | 90 +++++++++++++++++++ 7 files changed, 211 insertions(+), 8 deletions(-) create mode 100644 flyfish-logging/src/main/java/com/flyfish/framework/logging/config/LoggingTextModifier.java create mode 100644 flyfish-logging/src/main/java/com/flyfish/framework/logging/config/LoggingTextRegistry.java create mode 100644 flyfish-logging/src/main/java/com/flyfish/framework/logging/domain/DomainDescriptions.java create mode 100644 flyfish-logging/src/main/java/com/flyfish/framework/logging/service/LogManager.java diff --git a/flyfish-common/src/main/java/com/flyfish/framework/utils/ReflectionUtils.java b/flyfish-common/src/main/java/com/flyfish/framework/utils/ReflectionUtils.java index b86c398..3872d26 100644 --- a/flyfish-common/src/main/java/com/flyfish/framework/utils/ReflectionUtils.java +++ b/flyfish-common/src/main/java/com/flyfish/framework/utils/ReflectionUtils.java @@ -1,11 +1,14 @@ package com.flyfish.framework.utils; import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.ArrayUtils; import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.Validate; +import org.springframework.data.util.CastUtils; import org.springframework.util.Assert; import java.lang.reflect.*; +import java.util.Optional; /** * 反射工具类. @@ -333,6 +336,18 @@ public class ReflectionUtils { public static boolean hasField(final Object obj, final String fieldName) { Field field = getAccessibleField(obj, fieldName); return field != null; + } + /** + * 获取范型,默认取得第一个 + * @param clazz 类 + * @return 结果 + */ + public static Optional> getGenericType(Class clazz) { + ParameterizedType type = CastUtils.cast(clazz.getGenericSuperclass()); + return Optional.ofNullable(type.getActualTypeArguments()).filter(ArrayUtils::isNotEmpty) + .map(array -> array[0]) + .filter(beanType -> beanType instanceof Class) + .map(beanType -> (Class) beanType); } } diff --git a/flyfish-logging/src/main/java/com/flyfish/framework/logging/advice/LogAdvice.java b/flyfish-logging/src/main/java/com/flyfish/framework/logging/advice/LogAdvice.java index fb335fb..48cb901 100644 --- a/flyfish-logging/src/main/java/com/flyfish/framework/logging/advice/LogAdvice.java +++ b/flyfish-logging/src/main/java/com/flyfish/framework/logging/advice/LogAdvice.java @@ -1,11 +1,12 @@ package com.flyfish.framework.logging.advice; -import lombok.extern.slf4j.Slf4j; +import com.flyfish.framework.logging.service.LogManager; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.Around; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Pointcut; -import org.springframework.stereotype.Component; + +import javax.annotation.Resource; /** * 日志切面 @@ -13,17 +14,20 @@ import org.springframework.stereotype.Component; * @author wangyu */ @Aspect -@Slf4j public class LogAdvice { + @Resource + private LogManager logManager; + /** * 切入注解 */ - @Pointcut("@annotation( com.flyfish.framework.annotations.Operation)") + @Pointcut("execution(public * com.flyfish..*.*Controller.*(..))") public void pointCut() { } + /** * 环绕切面,获取参数 * @@ -33,13 +37,16 @@ public class LogAdvice { @Around("pointCut()") public Object process(ProceedingJoinPoint joinPoint) throws Throwable { Object[] args = joinPoint.getArgs(); - boolean success = false; + Throwable e = null; + Object result = null; try { - Object result = joinPoint.proceed(args); - success = true; + result = joinPoint.proceed(args); return result; + } catch (Throwable throwable) { + e = throwable; + throw throwable; } finally { - log.info("success: {}, {}", success,joinPoint.getSignature().getName()); + logManager.tryLog(joinPoint, result, e); } } } diff --git a/flyfish-logging/src/main/java/com/flyfish/framework/logging/config/LoggingConfig.java b/flyfish-logging/src/main/java/com/flyfish/framework/logging/config/LoggingConfig.java index 25086e9..8e4e909 100644 --- a/flyfish-logging/src/main/java/com/flyfish/framework/logging/config/LoggingConfig.java +++ b/flyfish-logging/src/main/java/com/flyfish/framework/logging/config/LoggingConfig.java @@ -2,12 +2,16 @@ package com.flyfish.framework.logging.config; import com.flyfish.framework.logging.advice.LogAdvice; import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.EnableAspectJAutoProxy; + +import java.util.List; /** * 日志配置 * * @author wangyu */ +@EnableAspectJAutoProxy public class LoggingConfig { /** @@ -19,4 +23,14 @@ public class LoggingConfig { public LogAdvice logAdvice() { return new LogAdvice(); } + + /** + * 日志文本注册,提供类型的动态渲染 + * + * @return 结果 + */ + @Bean + public LoggingTextRegistry loggingTextRegistry(List modifiers) { + return new LoggingTextRegistry(modifiers); + } } diff --git a/flyfish-logging/src/main/java/com/flyfish/framework/logging/config/LoggingTextModifier.java b/flyfish-logging/src/main/java/com/flyfish/framework/logging/config/LoggingTextModifier.java new file mode 100644 index 0000000..0dce351 --- /dev/null +++ b/flyfish-logging/src/main/java/com/flyfish/framework/logging/config/LoggingTextModifier.java @@ -0,0 +1,15 @@ +package com.flyfish.framework.logging.config; + +import java.util.Map; + +/** + * 日志记录文本自定义 + * @author wangyu + */ +public interface LoggingTextModifier { + + /** + * 自定义映射 + */ + void modify(Map mapping); +} diff --git a/flyfish-logging/src/main/java/com/flyfish/framework/logging/config/LoggingTextRegistry.java b/flyfish-logging/src/main/java/com/flyfish/framework/logging/config/LoggingTextRegistry.java new file mode 100644 index 0000000..6101742 --- /dev/null +++ b/flyfish-logging/src/main/java/com/flyfish/framework/logging/config/LoggingTextRegistry.java @@ -0,0 +1,26 @@ +package com.flyfish.framework.logging.config; + +import lombok.RequiredArgsConstructor; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * 日志文本注册器 + * + * @author wangyu + */ +@RequiredArgsConstructor +public class LoggingTextRegistry { + + // 映射 + private final Map mapping = new HashMap<>(); + + // 自定义处理 + private final List modifiers; + + public String text(String code) { + return mapping.getOrDefault(code, code); + } +} diff --git a/flyfish-logging/src/main/java/com/flyfish/framework/logging/domain/DomainDescriptions.java b/flyfish-logging/src/main/java/com/flyfish/framework/logging/domain/DomainDescriptions.java new file mode 100644 index 0000000..ef16aae --- /dev/null +++ b/flyfish-logging/src/main/java/com/flyfish/framework/logging/domain/DomainDescriptions.java @@ -0,0 +1,36 @@ +package com.flyfish.framework.logging.domain; + +import com.flyfish.framework.domain.base.Domain; +import com.flyfish.framework.domain.po.Department; +import com.flyfish.framework.domain.po.Permission; +import com.flyfish.framework.domain.po.Role; +import com.flyfish.framework.domain.po.User; +import lombok.AllArgsConstructor; +import lombok.Getter; + +import java.util.Arrays; + +/** + * 缺省的实体描述 + * @author wangyu + */ +@AllArgsConstructor +@Getter +public enum DomainDescriptions { + + DEFAULT(null, "未知数据"), + ADMIN_USER(User.class, "系统用户"), + ROLE(Role.class, "用户角色"), + PERMISSION(Permission.class, "用户权限"), + LOG(Log.class, "系统日志"), + DEPARTMENT(Department.class, "部门"); + + private final Class domainClass; + + private final String name; + + public static DomainDescriptions getByClass(Class clazz) { + return Arrays.stream(values()).filter(descriptions -> descriptions.domainClass == clazz) + .findFirst().orElse(DEFAULT); + } +} diff --git a/flyfish-logging/src/main/java/com/flyfish/framework/logging/service/LogManager.java b/flyfish-logging/src/main/java/com/flyfish/framework/logging/service/LogManager.java new file mode 100644 index 0000000..d48486a --- /dev/null +++ b/flyfish-logging/src/main/java/com/flyfish/framework/logging/service/LogManager.java @@ -0,0 +1,90 @@ +package com.flyfish.framework.logging.service; + +import com.alibaba.fastjson.JSON; +import com.flyfish.framework.annotations.Operation; +import com.flyfish.framework.beans.meta.RestBean; +import com.flyfish.framework.context.UserContext; +import com.flyfish.framework.domain.base.Domain; +import com.flyfish.framework.logging.domain.DomainDescriptions; +import com.flyfish.framework.logging.domain.Log; +import com.flyfish.framework.utils.ReflectionUtils; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.ArrayUtils; +import org.apache.commons.lang3.StringUtils; +import org.aspectj.lang.ProceedingJoinPoint; +import org.aspectj.lang.Signature; +import org.aspectj.lang.reflect.MethodSignature; +import org.springframework.core.annotation.AnnotationUtils; +import org.springframework.data.util.CastUtils; +import org.springframework.stereotype.Service; +import org.springframework.web.bind.annotation.RequestMapping; + +import java.util.Optional; + +/** + * 日志管理器 + * + * @author wangyu + */ +@Service +@Slf4j +public class LogManager { + + /** + * 尝试记录日志 + * + * @param joinPoint 接入点 + * @param e 异常 + */ + public void tryLog(ProceedingJoinPoint joinPoint, Object result, Throwable e) { + Signature signature = joinPoint.getSignature(); + if (signature instanceof MethodSignature) { + MethodSignature methodSignature = (MethodSignature) signature; + Operation operation = AnnotationUtils.findAnnotation(methodSignature.getMethod(), Operation.class); + if (null != operation) { + String module = operation.module(); + Class targetClass = joinPoint.getTarget().getClass(); + if (StringUtils.isBlank(module)) { + module = ReflectionUtils.getGenericType(targetClass) + .flatMap(clazz -> { + DomainDescriptions description = DomainDescriptions.getByClass(CastUtils.cast(clazz)); + if (null != description) { + return Optional.of(description.getName()); + } + return Optional.ofNullable(AnnotationUtils.findAnnotation(clazz, RestBean.class)) + .map(RestBean::name); + }) + .orElse("未知模块"); + } + log.info("监测到支持的切点:{}, {}", module, operation.value()); + // 构建日志 + Log log = new Log(); + log.setSuccess(null == e); + log.setBody(bodyString(joinPoint.getArgs())); + log.setModule(module); + log.setBusiness(operation.value()); + log.setError(Optional.ofNullable(e).map(JSON::toJSONString).orElse(null)); + log.setResponse(Optional.ofNullable(result).map(JSON::toJSONString).orElse(null)); + log.setOperator(UserContext.sharedContext().map(UserContext::currentUser).map(Domain::getName).orElse("未知")); + log.setSignature(joinPoint.getSignature().getName()); + log.setUri(Optional.ofNullable(AnnotationUtils.findAnnotation(targetClass, RequestMapping.class)) + .map(mapping -> mapping.value()) + .filter(ArrayUtils::isNotEmpty) + .map(array -> array[0]) + ); + // 写入日志 + logService.create() + } + } + } + + private String bodyString(Object[] args) { + if (ArrayUtils.isEmpty(args)) { + return null; + } + if (args.length == 1) { + return JSON.toJSONString(args[0]); + } + return JSON.toJSONString(args); + } +}