1. 程式人生 > >springboot 註解日誌實現

springboot 註解日誌實現

springboot AOP+日誌的註解實現

2017年12月08日 15:12:19

閱讀數:534

註解檔案:


@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 = "方法描述")