介面日誌有啥用
在我們日常的開發過程中,我們可以通過介面日誌去檢視這個介面的一些詳細資訊。比如客戶端的IP,客戶端的型別,響應的時間,請求的型別,請求的介面方法等等,我們可以對這些資料進行統計分析,提取出我們想要的資訊。
怎麼拿到介面日誌
這裡,我們使用的是Spring的兩大殺器之AOP,通過在Controller層定義切點,然後對請求物件進行分析獲取介面資訊,同時開啟一個ThreadLocal來記錄響應時間。
關於AOP的註解
@Aspect
:將一個類定義為切面類。@Pointcut
:定義一個切入點。@Before
:在切入點開始處切入內容。@After
:在切入點結尾處切入內容。@AfterReturning
:在切入點返回內容之後切入內容(可以用來對處理返回值做一些加工處理。@Around
:在切入點前後切入內容,並自己控制何時執行切入點自身的內容@AfterThrowing
:用來處理當切入內容部分丟擲異常之後的處理邏輯。@Order
:在切入點前的操作,按order的值由小到大執行;在切入點後的操作,按order的值由大到小執行。
實戰應用
一:引入依賴
首先,我們需要新增引入aop的依賴,以及用於分析客戶端資訊的UserAgentUtils包,還有用於@Slf4j
列印日誌的Lombok的包:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
<dependency>
<groupId>eu.bitwalker</groupId>
<artifactId>UserAgentUtils</artifactId>
<version>1.20</version>
</dependency>
複製程式碼
二:定義一個ResponseAop切面類
在之前的統一返回值和異常處理中我們已經定義過這個類,這裡是對其進行完善。這裡我再把程式碼再寫一下:
@Aspect
@Order(5)
@Component
@Slf4j
public class ResponseAop
複製程式碼
三:定義一個ThreadLocal變數
直接在這裡定義基本型別會有同步問題,所以我們定義一個ThreadLocal物件來記錄消耗的時間。
ThreadLocal<Long> startTime = new ThreadLocal<>();
複製程式碼
四:定義切點
這裡需要注意的是切點的寫法,一定要正確才能保證AOP生效!這裡附上一些簡單的寫法,後續會單獨開一章講解execution表示式的書寫。
- 任意公共方法:
execution(public * *(..))
- 任何一個以“set”開始的方法的執行:
execution(* set*(..))
- Service介面的任意方法的執行:
execution(* com.xyz.service.Service.*(..))
- 定義在service包裡的任意方法的執行:
execution(* com.xyz.service.*.*(..))
- 定義在service包和所有子包裡的任意類的任意方法的執行:
e
xecution(* com.xyz.service..*.*(..))
/**
* 切點
*/
@Pointcut("execution(public * indi.viyoung.viboot.*.controller..*(..))")
public void httpResponse() {
}
複製程式碼
五:在@Before中獲取請求資訊
@Before("httpResponse()")
public void doBefore(JoinPoint joinPoint){
//開始計時
startTime.set(System.currentTimeMillis());
ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
HttpServletRequest request = attributes.getRequest();
//列印請求的內容
UserAgent userAgent = UserAgent.parseUserAgentString(request.getHeader("User-Agent"));//獲取請求頭中的User-Agent
log.info("介面路徑:{}" , request.getRequestURL().toString());
log.info("瀏覽器:{}", userAgent.getBrowser().toString());
log.info("瀏覽器版本:{}",userAgent.getBrowserVersion());
log.info("作業系統: {}", userAgent.getOperatingSystem().toString());
log.info("IP : {}" , request.getRemoteAddr());
log.info("請求型別:{}", request.getMethod());
log.info("類方法 : " + joinPoint.getSignature().getDeclaringTypeName() + "." + joinPoint.getSignature().getName());
log.info("請求引數 : {} " + Arrays.toString(joinPoint.getArgs()));
}
複製程式碼
六:在@AfterReturning中獲取方法的返回值和執行時間
@AfterReturning(returning = "ret" , pointcut = "httpResponse()")
public void doAfterReturning(Object ret){
//處理完請求後,返回內容
log.info("方法返回值:{}" , ret);
log.info("方法執行時間:{}毫秒", (System.currentTimeMillis() - startTime.get()));
}
複製程式碼
七:測試結果
下面,我們對一個介面進行訪問:
2019-02-21 21:03:31.358 INFO 11788 --- [nio-8090-exec-5] indi.viyoung.viboot.aop.ResponseAop : 介面路徑:http://localhost:8090/users
2019-02-21 21:03:31.359 INFO 11788 --- [nio-8090-exec-5] indi.viyoung.viboot.aop.ResponseAop : 瀏覽器:CHROME
2019-02-21 21:03:31.359 INFO 11788 --- [nio-8090-exec-5] indi.viyoung.viboot.aop.ResponseAop : 瀏覽器版本:72.0.3626.109
2019-02-21 21:03:31.360 INFO 11788 --- [nio-8090-exec-5] indi.viyoung.viboot.aop.ResponseAop : 作業系統: MAC_OS_X
2019-02-21 21:03:31.360 INFO 11788 --- [nio-8090-exec-5] indi.viyoung.viboot.aop.ResponseAop : IP : 0:0:0:0:0:0:0:1
2019-02-21 21:03:31.360 INFO 11788 --- [nio-8090-exec-5] indi.viyoung.viboot.aop.ResponseAop : 請求型別:GET
2019-02-21 21:03:31.360 INFO 11788 --- [nio-8090-exec-5] indi.viyoung.viboot.aop.ResponseAop : 類方法 : indi.viyoung.viboot.apilog.controller.UserController.findAll
2019-02-21 21:03:31.360 INFO 11788 --- [nio-8090-exec-5] indi.viyoung.viboot.aop.ResponseAop : 請求引數 : {} []
...
2019-02-21 21:03:31.393 INFO 11788 --- [nio-8090-exec-5] indi.viyoung.viboot.aop.ResponseAop : 方法返回值:ReturnVO{code='2000', message='操作成功', data=[User(id=10000001, password=123456, userName=vi-young), User(id=10000002, password=123456, userName=vi-young), User(id=10000003, password=123123, userName=lxt), User(id=10000004, password=123456, userName=yangwei)]}
2019-02-21 21:03:31.393 INFO 11788 --- [nio-8090-exec-5] indi.viyoung.viboot.aop.ResponseAop : 方法執行時間:36毫秒
複製程式碼
可以看出,我們已經獲取到我們想要的資訊~
在後面的應用實戰中,我們會將這些資訊儲存到資料庫中,並且使用一些資料分析工具進行分析。
公眾號
您的推薦是對我最大的幫助!