springboot AOP+日誌的註解實現
阿新 • • 發佈:2019-01-21
註解檔案:
@Target({ElementType.METHOD,ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface InvokeLog {
String name() default "";
String description() default "";
boolean printReturn() default true;
}
切面類:
@Aspect
@Component
public class InvokeLogAspect {
public static final Logger logger = LoggerFactory.getLogger(InvokeLogAspect.class);
// 執行最大時間 超過該時間則警告
private static final int DEFAULT_TIME_LIMIT = 3000;
private static final String MSG = "--請求--\n --方法:{}\n --描述:{}\n --位置:{}\n --引數:{}\n --返回:{}\n --耗時:{} ms";
// 切點`
@Pointcut ("@annotation(com.common.annotation.InvokeLog)")
public void executePointCut() {
}
// around 切面強化
@Around("executePointCut()")
public Object execute(ProceedingJoinPoint joinPoint) throws Throwable {
Object[] args = joinPoint.getArgs();
if (logger.isDebugEnabled() || logger.isWarnEnabled()) {
StopWatch clock = new StopWatch();
clock.start();
Object retrunobj = null;
try {
// 注意和finally中的執行順序 finally是在return中的計算結束返回前執行
return retrunobj = joinPoint.proceed(args);
} catch (Exception e) {
throw e;
} finally {
clock.stop();
long totalTime = clock.getTotalTimeMillis();
// 列印日誌
handleLog(joinPoint, args, retrunobj, totalTime);
}
} else {
return joinPoint.proceed(args);
}
}
/**
* 日誌處理
*
* @param joinPoint 位置
* @param args 引數
* @param retrunobj 響應
* @param totalTime 耗時ms
*/
private void handleLog(ProceedingJoinPoint joinPoint, Object[] args, Object retrunobj, long totalTime) {
Method method = ((MethodSignature) joinPoint.getSignature()).getMethod();
InvokeLog invokeLog = method.getAnnotation(InvokeLog.class);
printLogMsg(invokeLog.name(), invokeLog.description(), invokeLog.printReturn(), joinPoint, args, retrunobj, totalTime);
}
/**
* @param name 操作名稱
* @param description 描述
* @param printReturn 是否列印響應
* @param joinPoint 位置
* @param args 引數
* @param returnObj 響應
* @param totalTimeMillis 耗時ms
*/
protected void printLogMsg(String name, String description, boolean printReturn, JoinPoint joinPoint, Object[] args, Object returnObj, long totalTimeMillis) {
Object[] params = argsDemote(args);
if (totalTimeMillis < DEFAULT_TIME_LIMIT)
logger.info(MSG, new Object[]{name, description, joinPoint.getStaticPart(), params, getPrintMsg(printReturn, returnObj), totalTimeMillis});
else
logger.warn(MSG, new Object[]{name, description, joinPoint.getStaticPart(), params, getPrintMsg(printReturn, returnObj), totalTimeMillis});
}
private String getPrintMsg(boolean printReturn, Object returnObj) {
return printReturn ? ((returnObj != null) ? JSONObject.toJSONString(returnObj) : "null") : "[printReturn = false]";
}
private Object[] argsDemote(Object[] args) {
if (args == null || args.length == 0) {
return new Object[]{};
}
Object[] params = new Object[args.length];
for (int i = 0; i < args.length; i++) {
Object arg = args[i];
if (arg instanceof ServletRequest || arg instanceof ServletResponse || arg instanceof ModelMap
|| arg instanceof Model || arg instanceof InputStreamSource ||
arg instanceof File) {
params[i] = args.toString();
} else {
params[i] = args[i];
}
}
return params;
}
}
呼叫:
在controller方法前加上
@InvokeLog(name = "method name", description = "方法描述")