feat: 提交日志
This commit is contained in:
parent
66ed5cbc83
commit
fb918e67fb
@ -1,11 +1,14 @@
|
|||||||
package com.flyfish.framework.utils;
|
package com.flyfish.framework.utils;
|
||||||
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.apache.commons.lang3.ArrayUtils;
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.apache.commons.lang3.Validate;
|
import org.apache.commons.lang3.Validate;
|
||||||
|
import org.springframework.data.util.CastUtils;
|
||||||
import org.springframework.util.Assert;
|
import org.springframework.util.Assert;
|
||||||
|
|
||||||
import java.lang.reflect.*;
|
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) {
|
public static boolean hasField(final Object obj, final String fieldName) {
|
||||||
Field field = getAccessibleField(obj, fieldName);
|
Field field = getAccessibleField(obj, fieldName);
|
||||||
return field != null;
|
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;
|
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.ProceedingJoinPoint;
|
||||||
import org.aspectj.lang.annotation.Around;
|
import org.aspectj.lang.annotation.Around;
|
||||||
import org.aspectj.lang.annotation.Aspect;
|
import org.aspectj.lang.annotation.Aspect;
|
||||||
import org.aspectj.lang.annotation.Pointcut;
|
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
|
* @author wangyu
|
||||||
*/
|
*/
|
||||||
@Aspect
|
@Aspect
|
||||||
@Slf4j
|
|
||||||
public class LogAdvice {
|
public class LogAdvice {
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private LogManager logManager;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 切入注解
|
* 切入注解
|
||||||
*/
|
*/
|
||||||
@Pointcut("@annotation( com.flyfish.framework.annotations.Operation)")
|
@Pointcut("execution(public * com.flyfish..*.*Controller.*(..))")
|
||||||
public void pointCut() {
|
public void pointCut() {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 环绕切面,获取参数
|
* 环绕切面,获取参数
|
||||||
*
|
*
|
||||||
@ -33,13 +37,16 @@ public class LogAdvice {
|
|||||||
@Around("pointCut()")
|
@Around("pointCut()")
|
||||||
public Object process(ProceedingJoinPoint joinPoint) throws Throwable {
|
public Object process(ProceedingJoinPoint joinPoint) throws Throwable {
|
||||||
Object[] args = joinPoint.getArgs();
|
Object[] args = joinPoint.getArgs();
|
||||||
boolean success = false;
|
Throwable e = null;
|
||||||
|
Object result = null;
|
||||||
try {
|
try {
|
||||||
Object result = joinPoint.proceed(args);
|
result = joinPoint.proceed(args);
|
||||||
success = true;
|
|
||||||
return result;
|
return result;
|
||||||
|
} catch (Throwable throwable) {
|
||||||
|
e = throwable;
|
||||||
|
throw throwable;
|
||||||
} finally {
|
} 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 com.flyfish.framework.logging.advice.LogAdvice;
|
||||||
import org.springframework.context.annotation.Bean;
|
import org.springframework.context.annotation.Bean;
|
||||||
|
import org.springframework.context.annotation.EnableAspectJAutoProxy;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 日志配置
|
* 日志配置
|
||||||
*
|
*
|
||||||
* @author wangyu
|
* @author wangyu
|
||||||
*/
|
*/
|
||||||
|
@EnableAspectJAutoProxy
|
||||||
public class LoggingConfig {
|
public class LoggingConfig {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -19,4 +23,14 @@ public class LoggingConfig {
|
|||||||
public LogAdvice logAdvice() {
|
public LogAdvice logAdvice() {
|
||||||
return new 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…
x
Reference in New Issue
Block a user