feat: 提交日志
This commit is contained in:
parent
66ed5cbc83
commit
fb918e67fb
@ -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<Class<?>> 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);
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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<LoggingTextModifier> modifiers) {
|
||||
return new LoggingTextRegistry(modifiers);
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,15 @@
|
||||
package com.flyfish.framework.logging.config;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 日志记录文本自定义
|
||||
* @author wangyu
|
||||
*/
|
||||
public interface LoggingTextModifier {
|
||||
|
||||
/**
|
||||
* 自定义映射
|
||||
*/
|
||||
void modify(Map<String, String> mapping);
|
||||
}
|
@ -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<String, String> mapping = new HashMap<>();
|
||||
|
||||
// 自定义处理
|
||||
private final List<LoggingTextModifier> modifiers;
|
||||
|
||||
public String text(String code) {
|
||||
return mapping.getOrDefault(code, code);
|
||||
}
|
||||
}
|
@ -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<? extends Domain> domainClass;
|
||||
|
||||
private final String name;
|
||||
|
||||
public static DomainDescriptions getByClass(Class<? extends Domain> clazz) {
|
||||
return Arrays.stream(values()).filter(descriptions -> descriptions.domainClass == clazz)
|
||||
.findFirst().orElse(DEFAULT);
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user