组件概述
- 方法或类上添加日志打印注解并打印日志
组件POM
pom
<dependency>
<groupId>org.opengoofy.index12306</groupId>
<artifactId>aska12306-log-spring-boot-starter</artifactId>
<version>${project.version}</version>
</dependency>
组件功能
1. 日志打印
-
定义日志打印注解,可以标记在类或者方法上。
-
标记在类上,类下所有方法都会打印;标记在方法上,仅打印标记方法;如果类或者方法上都有标记,以方法上注解为准
java
package com.opengoofy.aska12306.framework.starter.log.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* Log 注解打印,可以标记在类或者方法上
* 标记在类上,类下所有方法都会打印;标记在方法上,仅打印标记方法;如果类或者方法上都有标记,以方法上注解为准
* aska12306
*/
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface ILog {
/**
* 入参打印
*
* @return 打印结果中是否包含入参,{@link Boolean#TRUE} 打印,{@link Boolean#FALSE} 不打印
*/
boolean input() default true;
/**
* 出参打印
*
* @return 打印结果中是否包含出参,{@link Boolean#TRUE} 打印,{@link Boolean#FALSE} 不打印
*/
boolean output() default true;
}
定义日志打印规约参数,共打印参数:开始时间、请求入参、以及返回参数等
java
package com.opengoofy.aska12306.framework.starter.log.core;
import lombok.Data;
/**
* ILog 日志打印实体
* aska12306
*/
@Data
public class ILogPrintDTO {
/**
* 开始时间
*/
private String beginTime;
/**
* 请求入参
*/
private Object[] inputParams;
/**
* 返回参数
*/
private Object outputParams;
}
-
定义日志注解 AOP 扫描类,执行方法执行前后增强,最终打印方法执行日志。
-
@within
和@annotation
注解分别对注解在类上和在方法上增强 -
特别是 @within 这个很少用到 而对于 @annotation 相信大家基本上是见怪不怪了
java
package com.opengoofy.aska12306.framework.starter.log.core;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.date.SystemClock;
import com.alibaba.fastjson2.JSON;
import com.opengoofy.aska12306.framework.starter.log.annotation.ILog;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.springframework.web.multipart.MultipartFile;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.lang.reflect.Method;
import java.util.Optional;
/**
* {@link ILog} 日志打印 AOP 切面
* aska12306
*/
@Aspect
public class ILogPrintAspect {
/**
* 打印类或方法上的 {@link ILog}
*/
@Around("@within(com.opengoofy.aska12306.framework.starter.log.annotation.ILog) || @annotation(com.opengoofy.aska12306.framework.starter.log.annotation.ILog)")
public Object printMLog(ProceedingJoinPoint joinPoint) throws Throwable {
long startTime = SystemClock.now();
MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
Logger log = LoggerFactory.getLogger(methodSignature.getDeclaringType());
String beginTime = DateUtil.now();
Object result = null;
try {
result = joinPoint.proceed();
} finally {
Method targetMethod = joinPoint.getTarget().getClass().getDeclaredMethod(methodSignature.getName(), methodSignature.getMethod().getParameterTypes());
ILog logAnnotation = Optional.ofNullable(targetMethod.getAnnotation(ILog.class)).orElse(joinPoint.getTarget().getClass().getAnnotation(ILog.class));
if (logAnnotation != null) {
ILogPrintDTO logPrint = new ILogPrintDTO();
logPrint.setBeginTime(beginTime);
if (logAnnotation.input()) {
logPrint.setInputParams(buildInput(joinPoint));
}
if (logAnnotation.output()) {
logPrint.setOutputParams(result);
}
String methodType = "", requestURI = "";
try {
ServletRequestAttributes servletRequestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
assert servletRequestAttributes != null;
methodType = servletRequestAttributes.getRequest().getMethod();
requestURI = servletRequestAttributes.getRequest().getRequestURI();
} catch (Exception ignored) {
}
log.info("[{}] {}, executeTime: {}ms, info: {}", methodType, requestURI, SystemClock.now() - startTime, JSON.toJSONString(logPrint));
}
}
return result;
}
private Object[] buildInput(ProceedingJoinPoint joinPoint) {
Object[] args = joinPoint.getArgs();
Object[] printArgs = new Object[args.length];
for (int i = 0; i < args.length; i++) {
if ((args[i] instanceof HttpServletRequest) || args[i] instanceof HttpServletResponse) {
continue;
}
if (args[i] instanceof byte[]) {
printArgs[i] = "byte array";
} else if (args[i] instanceof MultipartFile) {
printArgs[i] = "file";
} else {
printArgs[i] = args[i];
}
}
return printArgs;
}
}