溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點(diǎn)擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

springboot中如何配置aop切面日志打印

發(fā)布時間:2021-07-08 17:09:58 來源:億速云 閱讀:142 作者:Leah 欄目:編程語言

這篇文章給大家介紹springboot中如何配置aop切面日志打印,內(nèi)容非常詳細(xì),感興趣的小伙伴們可以參考借鑒,希望對大家能有所幫助。

一、SpringBoot Aop說明

1. Aop

AOP(Aspect-Oriented Programming,面向切面編程),它利用一種”橫切”的技術(shù),將那些多個類的共同行為封裝到一個可重用的模塊。便于減少系統(tǒng)的重復(fù)代碼,降低模塊之間的耦合度,并有利于未來的可操作性和可維護(hù)性。

2. AOP相關(guān)概念:Aspect(切面):聲明類似于Java中的類聲明,在Aspect中會包含一些Pointcut及相應(yīng)的Advice。

Joint point(連接點(diǎn)):表示在程序中明確定義的點(diǎn)。包括方法的調(diào)用、對類成員的訪問等。

Pointcut(切入點(diǎn)):表示一個組Joint point,如方法名、參數(shù)類型、返回類型等等。

Advice(通知):Advice定義了在Pointcut里面定義的程序點(diǎn)具體要做的操作,它通過(before、around、after(return、throw)、finally來區(qū)別實(shí)在每個Joint point之前、之后還是執(zhí)行 前后要調(diào)用的代碼。

Before:在執(zhí)行方法前調(diào)用Advice,比如請求接口之前的登錄驗(yàn)證。

Around:在執(zhí)行方法前后調(diào)用Advice,這是最常用的方法。

After:在執(zhí)行方法后調(diào)用Advice,after、return是方法正常返回后調(diào)用,after\throw是方法拋出異常后調(diào)用。

Finally:方法調(diào)用后執(zhí)行Advice,無論是否拋出異常還是正常返回。

AOP proxy:AOP proxy也是Java對象,是由AOP框架創(chuàng)建,用來完成上述動作,AOP對象通??梢酝ㄟ^JDK dynamic proxy完成,或者使用CGLIb完成。

Weaving:實(shí)現(xiàn)上述切面編程的代碼織入,可以在編譯時刻,也可以在運(yùn)行時刻,Spring和其它大多數(shù)Java框架都是在運(yùn)行時刻生成代理。

二、代碼示例

1. POM引入

<dependencies>  <dependency>    <groupId>org.springframework.boot</groupId>    <artifactId>spring-boot-starter-web</artifactId>  </dependency>  <dependency>    <groupId>org.springframework.boot</groupId>    <artifactId>spring-boot-starter-aop</artifactId>  </dependency>  <!-- 分析客戶端信息的工具類-->  <dependency>    <groupId>eu.bitwalker</groupId>    <artifactId>UserAgentUtils</artifactId>    <version>1.21</version>  </dependency>  <!-- lombok -->  <dependency>    <groupId>org.projectlombok</groupId>    <artifactId>lombok</artifactId>    <scope>1.18.10</scope>  </dependency></dependencies>

2、切面:WebLogAspect代碼

/** * 添加aop日志打印 * * @author 馬振全 2020/1/13 14:42 */@Aspect@Component@Slf4jpublic class WebLogAspect {  /**   * 進(jìn)入方法時間戳   */  private Long startTime;  /**   * 方法結(jié)束時間戳(計(jì)時)   */  private Long endTime;   public WebLogAspect() {  }    /**   * 定義請求日志切入點(diǎn),其切入點(diǎn)表達(dá)式有多種匹配方式,這里是指定路徑   */  @Pointcut("execution(public * com.soyoung.ad.engine.controller.*.*(..))")  public void webLogPointcut() {  }   /**   * 前置通知:   * 1. 在執(zhí)行目標(biāo)方法之前執(zhí)行,比如請求接口之前的登錄驗(yàn)證;   * 2. 在前置通知中設(shè)置請求日志信息,如開始時間,請求參數(shù),注解內(nèi)容等   *   * @param joinPoint   * @throws Throwable   */  @Before("webLogPointcut()")  public void doBefore(JoinPoint joinPoint) {     // 接收到請求,記錄請求內(nèi)容    ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();    HttpServletRequest request = attributes.getRequest();    //獲取請求頭中的User-Agent    UserAgent userAgent = UserAgent.parseUserAgentString(request.getHeader("User-Agent"));    //打印請求的內(nèi)容    startTime = System.currentTimeMillis();    log.info("請求開始時間:{}", LocalDateTime.now());    log.info("請求Url : {}", request.getRequestURL().toString());    log.info("請求方式 : {}", request.getMethod());    log.info("請求ip : {}", request.getRemoteAddr());    log.info("請求方法 : ", joinPoint.getSignature().getDeclaringTypeName() + "." + joinPoint.getSignature().getName());    log.info("請求參數(shù) : {}", Arrays.toString(joinPoint.getArgs()));    // 系統(tǒng)信息    log.info("瀏覽器:{}", userAgent.getBrowser().toString());    log.info("瀏覽器版本:{}", userAgent.getBrowserVersion());    log.info("操作系統(tǒng): {}", userAgent.getOperatingSystem().toString());  }   /**   * 返回通知:   * 1. 在目標(biāo)方法正常結(jié)束之后執(zhí)行   * 1. 在返回通知中補(bǔ)充請求日志信息,如返回時間,方法耗時,返回值,并且保存日志信息   *   * @param ret   * @throws Throwable   */  @AfterReturning(returning = "ret", pointcut = "webLogPointcut()")  public void doAfterReturning(Object ret) throws Throwable {    endTime = System.currentTimeMillis();    log.info("請求結(jié)束時間:{}", LocalDateTime.now());    log.info("請求耗時:{}", (endTime - startTime));    // 處理完請求,返回內(nèi)容    log.info("請求返回 : {}", ret);  }   /**   * 異常通知:   * 1. 在目標(biāo)方法非正常結(jié)束,發(fā)生異常或者拋出異常時執(zhí)行   * 1. 在異常通知中設(shè)置異常信息,并將其保存   *   * @param throwable   */  @AfterThrowing(value = "webLogPointcut()", throwing = "throwable")  public void doAfterThrowing(Throwable throwable) {    // 保存異常日志記錄    log.error("發(fā)生異常時間:{}", LocalDateTime.now());    log.error("拋出異常:{}", throwable.getMessage());  }}

3、@Before和@AfterReturning部分也可使用以下代碼替代

/** * 在執(zhí)行方法前后調(diào)用Advice,這是最常用的方法,相當(dāng)于@Before和@AfterReturning全部做的事兒 * @param pjp * @return * @throws Throwable */@Around("webLogPointcut()")public Object doAround(ProceedingJoinPoint pjp) throws Throwable {  // 接收到請求,記錄請求內(nèi)容  ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();  HttpServletRequest request = attributes.getRequest();  //獲取請求頭中的User-Agent  UserAgent userAgent = UserAgent.parseUserAgentString(request.getHeader("User-Agent"));  //打印請求的內(nèi)容  startTime = System.currentTimeMillis();  log.info("請求Url : {}" , request.getRequestURL().toString());  log.info("請求方式 : {}" , request.getMethod());  log.info("請求ip : {}" , request.getRemoteAddr());  log.info("請求方法 : " , pjp.getSignature().getDeclaringTypeName() , "." , pjp.getSignature().getName());  log.info("請求參數(shù) : {}" , Arrays.toString(pjp.getArgs()));// 系統(tǒng)信息  log.info("瀏覽器:{}", userAgent.getBrowser().toString());  log.info("瀏覽器版本:{}",userAgent.getBrowserVersion());  log.info("操作系統(tǒng): {}", userAgent.getOperatingSystem().toString());  // pjp.proceed():當(dāng)我們執(zhí)行完切面代碼之后,還有繼續(xù)處理業(yè)務(wù)相關(guān)的代碼。proceed()方法會繼續(xù)執(zhí)行業(yè)務(wù)代碼,并且其返回值,就是業(yè)務(wù)處理完成之后的返回值。  Object ret = pjp.proceed();  log.info("請求結(jié)束時間:"+ LocalDateTime.now());  log.info("請求耗時:{}" , (System.currentTimeMillis() - startTime));  // 處理完請求,返回內(nèi)容  log.info("請求返回 : " , ret);  return ret;}

4、測試結(jié)果

2020-01-13 15:18:21.309 INFO xxx.WebLogAspect : 請求開始時間:2020-01-13T15:18:21.3092020-01-13 15:18:21.309 INFO xxx.WebLogAspect : 請求Url : http://localhost:8020/api/v1/hourlyStat/findHourlyStatReportList2020-01-13 15:18:21.320 INFO xxx.WebLogAspect : 請求方式 : POST2020-01-13 15:18:21.321 INFO xxx.WebLogAspect : 請求ip : 0:0:0:0:0:0:0:12020-01-13 15:18:21.322 INFO xxx.WebLogAspect : 請求方法 : 2020-01-13 15:18:21.325 INFO xxx.WebLogAspect : 請求參數(shù) : [HourlyStat{subStrategyId=null}]2020-01-13 15:18:21.326 INFO xxx.WebLogAspect : 瀏覽器:CHROME2020-01-13 15:18:21.327 INFO xxx.WebLogAspect : 瀏覽器版本:78.0.3904.1082020-01-13 15:18:21.333 INFO xxx.WebLogAspect : 操作系統(tǒng): WINDOWS_102020-01-13 15:18:21.403 INFO xxx.WebLogAspect : 請求結(jié)束時間:2020-01-13T15:18:21.4032020-01-13 15:18:21.405 INFO xxx.WebLogAspect : 請求耗時:942020-01-13 15:18:21.405 INFO xxx.WebLogAspect : 請求返回 : com.soyoung.ad.engine.common.Result@2f935d032020-01-13 15:18:21.492 INFO xxx.WebLogAspect : 請求結(jié)束時間:2020-01-13T15:18:21.4922020-01-13 15:18:21.493 INFO xxx.WebLogAspect : 請求耗時:1832020-01-13 15:18:21.494 INFO xxx.WebLogAspect : 請求返回 : com.soyoung.ad.engine.common.Result@7199e9222020-01-13 15:18:42.859 INFO xxx.WebLogAspect : 請求開始時間:2020-01-13T15:18:42.8592020-01-13 15:18:42.860 INFO xxx.WebLogAspect : 請求Url : http://localhost:8020/api/v1/hourlyStat/findHourlyStatReportList2020-01-13 15:18:42.860 INFO xxx.WebLogAspect : 請求方式 : POST2020-01-13 15:18:42.861 INFO xxx.WebLogAspect : 請求ip : 0:0:0:0:0:0:0:12020-01-13 15:18:42.861 INFO xxx.WebLogAspect : 請求方法 : 2020-01-13 15:18:42.862 INFO xxx.WebLogAspect : 請求參數(shù) : [HourlyStat{subStrategyId=1003}]2020-01-13 15:18:42.862 INFO xxx.WebLogAspect : 瀏覽器:CHROME2020-01-13 15:18:42.863 INFO xxx.WebLogAspect : 瀏覽器版本:78.0.3904.1082020-01-13 15:18:42.864 INFO xxx.WebLogAspect : 操作系統(tǒng): WINDOWS_102020-01-13 15:18:42.909 INFO xxx.WebLogAspect : 請求結(jié)束時間:2020-01-13T15:18:42.9092020-01-13 15:18:42.910 INFO xxx.WebLogAspect : 請求耗時:502020-01-13 15:18:42.910 INFO xxx.WebLogAspect : 請求返回 : com.soyoung.ad.engine.common.Result@7d494cbd

關(guān)于springboot中如何配置aop切面日志打印就分享到這里了,希望以上內(nèi)容可以對大家有一定的幫助,可以學(xué)到更多知識。如果覺得文章不錯,可以把它分享出去讓更多的人看到。

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI