關於一次AOP攔截入參記錄日誌報錯的梳理總結

關於一次AOP攔截入參記錄日誌報錯的梳理總結html

將服務發佈到tomcat中後,觀察服務的運行狀態以及日誌記錄情況; 發現有以下一個問題:java

2018-10-31 16:20:10,701 [] INFO  aspect.PayMethodLogAspectJ - rest 請求開始{1540974010700}:clazzName: com.yuantu.unified.pay.openapi.OpenApiRest, methodName:preOrder, 參數:[Ljava.lang.Object;@49ffa5bd
2018-10-31 16:20:10,790 [] INFO  aspect.PayMethodLogAspectJ - rest 返回結束{1540974010700}::clazzName: com.yuantu.unified.pay.openapi.OpenApiRest, methodName:preOrder, 結果:{"msg":"subCorpNo{3701011318}","resultCode":"101","startTime":1540974010785,"success":false,"timeConsum":0},耗時毫秒數 89

日誌中記錄入參並無詳細的記錄下來,而是記錄了一個Object,這樣的日誌在未來的查詢問題的時候是不可用的,遂進行檢查代碼查找問題;api

代碼以下:tomcat

@Around("within(com.yuantu.unified.pay.openapi..*) || within(com.yuantu.unified.pay.rest..*)")
    public Object setCorporation(ProceedingJoinPoint joinPoint) throws Throwable {
        String classType = joinPoint.getTarget().getClass().getName();
        Class<?> clazz = Class.forName(classType);
        String clazzName = clazz.getName();
        String methodName = joinPoint.getSignature().getName();

        Long logId = System.currentTimeMillis();
        Object[] args = joinPoint.getArgs();
        String paramter = "";
        if (args != null) {
            try {
                paramter = JSON.toJSONString(args);
            } catch (Exception e) {
                paramter = args.toString();
            }
        }
        Long currentTime = System.currentTimeMillis();
        logger.info("rest 請求開始{" + logId + "}:clazzName: " + clazzName + ", methodName:" + methodName + ", 參數:" + paramter);
        Object proceed = Result.createFailResult();

        try {
            proceed = joinPoint.proceed(args);
        } catch (Exception e) {
            proceed = Result.createFailResult("系統異常,請及時與咱們聯繫,以便及時解決。錯誤類型:" + e.getClass().getName() +" 錯誤信息:"+ e.getMessage());
            logger.error("rest 請求發生異常{" + logId + "}:clazzName: " + clazzName + ", methodName:" + methodName + ", 參數:" + paramter, e);
        }

        String result = "";
        if (proceed != null) {
            result = JSON.toJSONString(proceed);
        }
        Long timeDiff = System.currentTimeMillis() - currentTime;
        logger.info("rest 返回結束{" + logId + "}::clazzName: " + clazzName + ", methodName:" + methodName + ", 結果:" + result + ",耗時毫秒數 " + timeDiff);
        return proceed;
    }

最初的觀察並無發現明顯的問題,由於paramter自己就是String類型; 後進行debug後,定位出問題所在位置: paramter = JSON.toJSONString(args); 在執行後報錯:java.lang.IllegalStateException: It is illegal to call this method if the current request is not in asynchronous mode (i.e. isAsyncStarted() returns false)async

上網查詢資料後發現,是由於使用 Object[] args = joinPoint.getArgs(); 獲取入參的時候,args還包含了一些其餘的內容,好比ServletRequest等,而這些入參並不能進行序列化,因此JSON.toJSONString時報錯;this

改造後的方法爲:debug

Object[] args = joinPoint.getArgs();
        Object[] arguments  = new Object[args.length];
        for (int i = 0; i < args.length; i++) {
            if (args[i] instanceof ServletRequest || args[i] instanceof ServletResponse || args[i] instanceof MultipartFile) {
                //ServletRequest不能序列化,從入參裏排除,不然報異常:java.lang.IllegalStateException: It is illegal to call this method if the current request is not in asynchronous mode (i.e. isAsyncStarted() returns false)
                //ServletResponse不能序列化 從入參裏排除,不然報異常:java.lang.IllegalStateException: getOutputStream() has already been called for this response
                continue;
            }
            arguments[i] = args[i];
        }
        String paramter = "";
        if (arguments != null) {
            try {
                paramter = JSONObject.toJSONString(arguments);
            } catch (Exception e) {
                paramter = arguments.toString();
            }
        }
        logger.info("rest 請求開始{" + logId + "}:clazzName: " + clazzName + ", methodName:" + methodName + ", 參數:" + paramter);

將不能進行序列化的入參過濾掉,只要留下咱們須要記錄的入參參數記錄到日誌中便可。rest

參考資料: https://www.cnblogs.com/zcz527/p/9300646.html日誌

相關文章
相關標籤/搜索