上一篇文章已經就如何獲取到 controller 層方法的參數和返回值進行了詳細分析,並且封裝了 HandlerMethodPostProcessor
接口以便使用,接下來就實現業務需求:根據 controller 層方法的入參和返回值動態生成日誌。
實現日誌解析
實現思路是這樣的:定義一個註解,註解的 value 爲日誌表達式,HandlerMethodPostProcessor#postProcessorAfterInvoke
方法中判斷 HandlerMethod 是否使用了該註解,使用了就解析其日誌表達式。
日誌需要根據參數和返回值動態生成,所以需要在日誌表達式中提供一種方式能取到兩者的值,這裏提供兩種實現方式:
- 自己定義參數和返回值的獲取表達式,在
postProcessorAfterInvoke
方法中解析時再將其替換爲具體值 - 使用 SpEL 表達式,需要將參數和返回值添加到
org.springframework.expression.spel.support.EvaluationContext
中,並藉助 SpEL 的 API 進行解析
第一種方式需要自己解析日誌表達式,比較複雜,所以我的實現裏只是進行了簡單的取值,也可以對參數和返回值的成員通過 getter 遞歸取值;SpEL 表達式提供了強大而完備的功能,可以進行算數運算,邏輯判斷,也可以獲取其他 bean、java 類、系統參數或項目參數,但對於簡單的日誌表達式可能不需要這麼多的功能,可以按需使用兩種方式。
自定義日誌表達式
表達式的解析規則如下
{parName}
: {} 內部的內容將被解析,普通單詞將識別爲參數名{$}
: $ 符將被認爲返回值{parName.count}
: .count 的形式將調用參數 parName 的 getCount 獲得其值{parName.role.name}
: .role.name 的形式將調用參數 parName 的 getRole,再繼續調用 Role 的 getName{$.name}
: 調用返回值的相應 getter 方法
可以像下面這樣使用:
HandlerMethodPostProcessor#postProcessorAfterInvoke
解析時只需將 {}
部分替換爲具體值即可。
SpEL 解析日誌
SpEL 可以像如下方式進行使用:
解析時#$
獲取到的是方法返回值,#num
將被替換爲參數 num 的值。
代碼說明
StandardEvaluationContext
+SpelExpressionParser
+TemplateParserContext
可以用來解析 SpEL 表達式定義的日誌logExpressionParser.parse
方法將解析自定義的日誌
在handleCustomLog
方法中就可以對日誌進行具體的處理。
private void handleCustomLog(String content, Object result, ServletInvocableHandlerMethod handlerMethod, Object[]
args) {
}
完整代碼已上傳 GitHub,可以在 這裏 找到