本篇博客主要是实现自定义注解,通过在方法中使用该注解,打印出该方法的请求参数以及返回参数,用于排查问题。减少日志的打印。
方法枚举:
package cn.eric.jdktools.annotation;
/**
* 方法返回参数枚举
* @Author wilsonm
* @Date 2020/4/13 1:02 下午
* @Param
* @return
**/
public enum LogType {
TIME("TIME", "方法调用时间"),
PARAM("PARAM", "参数打印");
private String type;
private String desc;
LogType(String type, String desc) {
this.type = type;
this.desc = desc;
}
}
自定义注解:
package cn.eric.jdktools.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface LogUseTime {
/**
* 描述
*
* @return
*/
String desc() default "";
/**
* 需要打印的日志形式
*
* @return
*/
LogType type() default LogType.PARAM;
}
方法实现:
package cn.eric.jdktools.annotation;
import com.alibaba.fastjson.JSON;
import com.google.common.collect.Lists;
import lombok.extern.log4j.Log4j2;
import org.apache.commons.lang3.StringUtils;
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.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;
import java.lang.reflect.Method;
import java.util.List;
/**
* 接口调用耗时 入参返回参数打印切面
* @author: wilsonm
* @date: 2020/4/13 1:02 下午
**/
@Aspect
@Component
@Log4j2
public class LogUseTimeAspect {
/**
* 参数截止长度
*/
private static int maxParamLen = 2000;
@Pointcut("@annotation(cn.eric.jdktools.annotation.LogUseTime)")
public void annotationCallTime() {
// not need body
}
@Around(value = "annotationCallTime()")
public Object doAround(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
Method method = ((MethodSignature) proceedingJoinPoint.getSignature()).getMethod();
LogUseTime useTime = method.getAnnotation(LogUseTime.class);
long startTime = System.currentTimeMillis();
Object object = null;
try {
object = proceedingJoinPoint.proceed();
} catch (Throwable throwable) {
String argStr = getArgStr(proceedingJoinPoint.getArgs());
long costTime = System.currentTimeMillis() - startTime;
log.info("method:{}, in params:{}, out params:{}, use time:{}ms", method.getName(), argStr,
throwable.getMessage(), costTime);
throw throwable;
}
long costTime = System.currentTimeMillis() - startTime;
switch (useTime.type()) {
case TIME:
log.info("desc:{}, method:{}, use time:{}ms", useTime.desc(),
method.getName(), costTime);
break;
case PARAM:
String argStr = getArgStr(proceedingJoinPoint.getArgs());
String result = JSON.toJSONString(object);
if (!StringUtils.isEmpty(result) && result.length() > maxParamLen) {
result = result.substring(0, maxParamLen) + "...";
}
if (StringUtils.isNotEmpty(useTime.desc())) {
log.info("desc:{}, method:{}, in params:{}, out params:{}, use time:{}ms", useTime.desc(),
method.getName(), argStr, result, costTime);
} else {
log.info("method:{}, in params:{}, out params:{}, use time:{}ms", method.getName(), argStr,
result, costTime);
}
break;
default:
}
return object;
}
private String getArgStr(Object[] args) {
List<String> argList = Lists.newArrayList();
try {
for (Object obj : args) {
String str = JSON.toJSONString(obj);
if (StringUtils.isEmpty(str)) {
continue;
}
if (str.length() > maxParamLen) {
argList.add(str.substring(0, maxParamLen) + "...");
} else {
argList.add(str);
}
}
} catch (Exception e) {
// ignore exception
}
return String.join("&", argList);
}
}
相关依赖:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>28.2-jre</version>
</dependency>
<dependency>
<groupId>commons-lang</groupId>
<artifactId>commons-lang</artifactId>
<version>2.6</version>
</dependency>
使用示例:
@LogUseTime(desc = "获取供应商完整信息")
@GetMapping("info/fetch/mostInfo")
public BaseDataVO getSupplierMostInfo(String supplierNo) {
return successModel(supplierInfoServiceForRemote.findSupplierInfoAndAccount(supplierNo));
}