概述:项目啥都没有,一个日志都没有,维护别人的接口很是麻烦,半天掉不通一个接口,出入参啥的都不熟悉,所以写了个日志切面。
使用的时候自己修改下表达式即可。
import com.yshz.emgot.goods.logs.HappyLog;
import emgot.response.HttpResult;
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.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.stereotype.Component;
import java.lang.reflect.Array;
import java.util.Collection;
/**
* @author dsc
* @version 1.0
* @createTime: 2022年08月23日 16:12
* @description: 日志切面
*/
@Aspect
@Component
public class HappyLogAspect {
private static final Logger log = LoggerFactory.getLogger(HappyLogAspect.class);
/**
* 拦截controller层接口 方法权限修饰符任意 com.yshz 包的深度任意.controller.类名任意.方法名任意.(形参列表任意)
*/
@Pointcut("execution(* com.yshz..controller.*.*(..)) ")
public void controllerPointCut() {
}
/**
* HappyLog注解拦截
* within:对象级别 annotation:方法级别
*/
@Pointcut("@within(com.yshz.emgot.goods.logs.HappyLog) || @annotation(com.yshz.emgot.goods.logs.HappyLog)")
public void annoPointCut() {
}
@Around("controllerPointCut() ||annoPointCut()")
public Object proceed(ProceedingJoinPoint point) throws Throwable {
long start = System.currentTimeMillis();
MethodSignature signature = (MethodSignature) point.getSignature();
HappyLog classAnno = AnnotationUtils.findAnnotation(point.getTarget().getClass(), HappyLog.class);
HappyLog methodAnno = AnnotationUtils.findAnnotation(signature.getMethod(), HappyLog.class);
String clazz = point.getTarget().getClass().getSimpleName();
String method = signature.getMethod().getName();
//标签:定位到业务代码位置
String classMethodName = clazz + "#" + method;
String label;
if (methodAnno != null && StringUtils.isNotBlank(methodAnno.value())) {
label = methodAnno.value() + "#" + classMethodName;
} else if (classAnno != null && StringUtils.isNotBlank(classAnno.value())) {
label = classAnno.value() + "#" + classMethodName;
} else {
label = classMethodName;
}
//true:打印日志 false:不打印日志
boolean isPrint = this.isNotProxy(clazz);
if (isPrint) {
log.debug("开始调用 --->>> {} {} {}", label, signature.getParameterNames(), point.getArgs());
}
Object result;
//目标方法是否失败
boolean isFail = false;
try {
isFail = true;
result = point.proceed();
isFail = false;
} finally {
//目标方法出现异常
if (isFail) {
long time = System.currentTimeMillis() - start;
if (isPrint) {
log.debug("调用失败结束 --->>> {} 耗时:{}ms", label, time);
}
}
}
long time = System.currentTimeMillis() - start;
if (isPrint) {
if (result == null) {
log.debug("调用成功结束 --->>> {} 耗时:{}ms", label, time);
return result;
}
debug(
label,
result instanceof HttpResult ? ((HttpResult<?>) result).getData() : result,
time
);
}
return result;
}
private void debug(String label, Object result, long time) {
if (result == null) {
log.debug("调用成功结束 --->>> {} 耗时:{}ms", label, time);
} else if (result instanceof Collection) {
log.debug("调用成功结束 --->>> {} 耗时:{}ms, result's size is {}", label, time, ((Collection<?>) result).size());
} else if (result.getClass().isArray()) {
log.debug("调用成功结束 --->>> {} 耗时:{}ms, result's length is {}", label, time, Array.getLength(result));
} else {
log.debug("调用成功结束 --->>> {} 耗时:{}ms, result:{}", label, time, result);
}
}
private boolean isNotProxy(String className) {
return className == null || !className.contains("proxy");
}
}
import java.lang.annotation.*;
@Documented
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
public @interface HappyLog {
/**
*日志标签(标注业务方法)
*/
String value() default "";
}