最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

SpringBoot統(tǒng)計(jì)接口調(diào)用耗時(shí)的三種方式

 更新時(shí)間:2024年06月20日 10:44:55   作者:Excellent的崽子  
在實(shí)際開發(fā)中,了解項(xiàng)目中接口的響應(yīng)時(shí)間是必不可少的事情,SpringBoot 項(xiàng)目支持監(jiān)聽接口的功能也不止一個(gè),接下來我們分別以 AOP、ApplicationListener、Tomcat 三個(gè)方面去實(shí)現(xiàn)三種不同的監(jiān)聽接口響應(yīng)時(shí)間的操作,需要的朋友可以參考下

引言

在實(shí)際開發(fā)中,了解項(xiàng)目中接口的響應(yīng)時(shí)間是必不可少的事情。SpringBoot 項(xiàng)目支持監(jiān)聽接口的功能也不止一個(gè),接下來我們分別以 AOP、ApplicationListener、Tomcat 三個(gè)方面去實(shí)現(xiàn)三種不同的監(jiān)聽接口響應(yīng)時(shí)間的操作。

AOP

首先我們在項(xiàng)目中創(chuàng)建一個(gè)類 ,比如就叫 WebLogAspect ,然后在該類上加上 @Aspect 和 @Component 注解,聲明是一個(gè) Bean 并且是一個(gè)切面:

import org.aspectj.lang.JoinPoint;  
import org.aspectj.lang.ProceedingJoinPoint;  
import org.aspectj.lang.annotation.*;  
import org.slf4j.Logger;  
import org.slf4j.LoggerFactory;  
import org.springframework.stereotype.Component;  
import org.springframework.web.context.request.RequestContextHolder;  
import org.springframework.web.context.request.ServletRequestAttributes;  
  
import javax.servlet.http.HttpServletRequest;  
import java.util.Date;  
  
@Aspect  
@Component  
public class WebLogAspect {  
  
    private static final Logger logger = LoggerFactory.getLogger(WebLogAspect.class);  
  
    // 定義一個(gè)切入點(diǎn),攔截所有帶有@RequestMapping注解的方法
    @Pointcut("@annotation(org.springframework.web.bind.annotation.RequestMapping)")  
    public void webLog() {}  
  
    // 前置通知,在方法執(zhí)行前記錄請求信息  
    @Before("webLog()")  
    public void doBefore(JoinPoint joinPoint) {  
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();  
        HttpServletRequest request = attributes.getRequest();  
  
        // 記錄請求信息  
        logger.info("請求開始:URL={}, IP={}, 方法={}", request.getRequestURL(), request.getRemoteAddr(), request.getMethod());  
    }  
  
    // 環(huán)繞通知,記錄方法執(zhí)行時(shí)間  
    @Around("webLog()")  
    public Object doAround(ProceedingJoinPoint joinPoint) throws Throwable {  
        long startTime = System.currentTimeMillis();  
  
        Object result = joinPoint.proceed(); // 繼續(xù)執(zhí)行被攔截的方法  
  
        long endTime = System.currentTimeMillis();  
        long executeTime = endTime - startTime;  
  
        // 記錄執(zhí)行時(shí)間  
        logger.info("請求結(jié)束:耗時(shí)={}ms", executeTime);  
  
        return result;  
    }  
  
    // 異常通知,在方法拋出異常時(shí)記錄異常信息  
    @AfterThrowing(pointcut = "webLog()", throwing = "ex")  
    public void doAfterThrowing(JoinPoint joinPoint, Exception ex) {  
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();  
        HttpServletRequest request = attributes.getRequest();  
  
        // 記錄異常信息  
        logger.error("請求異常:URL={}, 異常={}", request.getRequestURL(), ex.getMessage());  
    }  
  
    // 后置通知(返回通知),在方法正常返回后記錄信息  
    @AfterReturning(returning = "retVal", pointcut = "webLog()")  
    public void doAfterReturning(JoinPoint joinPoint, Object retVal) {  
        // 你可以在這里記錄返回值,但通常我們不記錄,因?yàn)榭赡軙?huì)包含敏感信息  
        // logger.info("請求返回:返回值={}", retVal);  
    }  
}

2024-06-19 17:49:37.373 [TID: N/A] WARN  [com.springboot.demo.TakeTimeCountListener] 請求開始:URL=http://localhost:18080/springboot/test1, IP=0:0:0:0:0:0:0:1, 方法=POST
2024-06-19 17:49:37.386 [TID: N/A] WARN  [com.springboot.demo.TakeTimeCountListener] 請求結(jié)束:耗時(shí)=13ms
2024-06-19 17:49:37.501 [TID: N/A] WARN  [com.springboot.demo.TakeTimeCountListener] 請求開始:URL=http://localhost:18080/springboot/test2, IP=0:0:0:0:0:0:0:1, 方法=POST
2024-06-19 17:49:37.516 [TID: N/A] WARN  [com.springboot.demo.TakeTimeCountListener] 請求結(jié)束:耗時(shí)=15ms
2024-06-19 17:49:37.905 [TID: N/A] WARN  [com.springboot.demo.TakeTimeCountListener] 請求開始:URL=http://localhost:18080/springboot/test3, IP=0:0:0:0:0:0:0:1, 方法=POST
2024-06-19 17:49:37.913 [TID: N/A] WARN  [com.springboot.demo.TakeTimeCountListener] 請求結(jié)束:耗時(shí)=8ms

優(yōu)點(diǎn):

  • 全局性:可以在不修改業(yè)務(wù)代碼的情況下,對全局范圍內(nèi)的接口進(jìn)行執(zhí)行時(shí)間的記錄。
  • 靈活性:可以根據(jù)需要靈活定義哪些接口需要記錄執(zhí)行時(shí)間。
  • 精確性:可以精確記錄從方法開始執(zhí)行到結(jié)束的時(shí)間。

缺點(diǎn):

  • 配置復(fù)雜性:AOP配置可能相對復(fù)雜,特別是對于初學(xué)者來說。
  • 性能開銷:雖然性能開銷通常很小,但在高并發(fā)場景下仍然需要考慮,并且它是會(huì)阻塞主線程的。

**常用性:**在Spring框架中,AOP是一個(gè)強(qiáng)大的工具,用于實(shí)現(xiàn)諸如日志記錄、事務(wù)管理等橫切關(guān)注點(diǎn)。因此,使用AOP記錄接口執(zhí)行時(shí)間是一種非常常見和推薦的做法。

ApplicationListener

首先我們在項(xiàng)目中創(chuàng)建一個(gè)類 ,比如就叫 TakeTimeCountListener,然后實(shí)現(xiàn) ApplicationListener 接口:

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.ApplicationListener;
import org.springframework.stereotype.Component;
import org.springframework.web.context.support.ServletRequestHandledEvent;

@Component
public class TakeTimeCountListener implements ApplicationListener<ServletRequestHandledEvent> {

    public final Logger logger = LoggerFactory.getLogger(this.getClass());
    
    @Override
    public void onApplicationEvent(ServletRequestHandledEvent event) {
        Throwable failureCause = event.getFailureCause() ;
        if (failureCause != null) {
            logger.warn("錯(cuò)誤原因: {}", failureCause.getMessage());
        }
        // 比如我這里只記錄接口響應(yīng)時(shí)間大于1秒的日志
        if (event.getProcessingTimeMillis() > 1000) {
                logger.warn("請求客戶端地址:{}, 請求URL: {}, 請求Method: {}, 請求耗時(shí):{} ms",
                event.getClientAddress(),
                event.getRequestUrl(),
                event.getMethod(),
                event.getProcessingTimeMillis());
        }

    }
}

2024-06-19 17:14:59.620 [TID: N/A] WARN  [com.springboot.demo.TakeTimeCountListener] 請求客戶端地址:0:0:0:0:0:0:0:1, 請求URL: /springboot/test1, 請求Method: GET, 請求耗時(shí):51 ms
2024-06-19 17:14:59.716 [TID: N/A] WARN  [com.springboot.demo.TakeTimeCountListener] 請求客戶端地址:0:0:0:0:0:0:0:1, 請求URL: /springboot/test2, 請求Method: GET, 請求耗時(shí):136 ms
2024-06-19 17:14:59.787 [TID: N/A] WARN  [com.springboot.demo.TakeTimeCountListener] 請求客戶端地址:0:0:0:0:0:0:0:1, 請求URL: /springboot/test3, 請求Method: POST, 請求耗時(shí):255 ms
2024-06-19 17:14:59.859 [TID: N/A] WARN  [com.springboot.demo.TakeTimeCountListener] 請求客戶端地址:0:0:0:0:0:0:0:1, 請求URL: /springboot/test4, 請求Method: POST, 請求耗時(shí):167 ms

優(yōu)點(diǎn):

  • 集成性:與Spring MVC框架緊密集成,無需額外配置。
  • 性能:改方法是不會(huì)阻塞主線程的,也就是說 該方法在處理的時(shí)候,controller 已經(jīng)正常返回了,可以通過在該方法進(jìn)行斷點(diǎn)調(diào)試來驗(yàn)證。
  • 簡單易用:實(shí)現(xiàn)ApplicationListener接口并監(jiān)聽ServletRequestHandledEvent事件即可。

缺點(diǎn):

  • 適用范圍:主要適用于Spring MVC 框架下的 Web 請求,對于非 Web 接口(如RESTful API)可能不適用。
  • 精度:只能記錄整個(gè)請求的處理時(shí)間,無法精確到具體的方法執(zhí)行時(shí)間。

**常用性:**在Spring MVC應(yīng)用中,使用ApplicationListener來記錄請求處理時(shí)間是一種常見做法,但通常用于監(jiān)控和性能分析,而不是精確記錄接口執(zhí)行時(shí)間。

Tomcat

Tomcat 的實(shí)現(xiàn)很簡單,只需要開啟它本身就支持的訪問日志就可以了 ,在 SpringBoot 中,我們可以在 properties 或 yaml 文件中增加下面配置:

# 啟用Tomcat訪問日志
server.tomcat.accesslog.enabled=true  
# 啟用緩沖模式,日志會(huì)先寫入緩沖區(qū),然后定期刷新到磁盤 
server.tomcat.accesslog.buffered=true  
# 指定日志存儲(chǔ)目錄,這里是相對于項(xiàng)目根目錄的logs文件夾  
server.tomcat.accesslog.directory=logs 
# 定義日志文件名的日期格式
server.tomcat.accesslog.file-date-format=.yyyy-MM-dd 
# 定義日志記錄的格式  
# 各個(gè)字段的意義:  
# %{X-Forwarded-For}i: 請求頭中的X-Forwarded-For,通常用于記錄客戶端真實(shí)IP  
# %p: 本地端口  
# %l: 遠(yuǎn)程用戶,通常為'-'  
# %r: 請求的第一行(例如:GET / HTTP/1.1)  
# %t: 請求時(shí)間(格式由日志處理器決定)  
# 注意:這里有一個(gè)重復(fù)的%r,可能是個(gè)錯(cuò)誤,通常第二個(gè)%r不需要  
# %s: HTTP狀態(tài)碼  
# %b: 響應(yīng)字節(jié)數(shù),不包括HTTP頭,如果為0則不輸出  
# %T: 請求處理時(shí)間(以秒為單位)  
server.tomcat.accesslog.pattern=%{X-Forwarded-For}i %p %l %r %t %r %s %b %T
# 日志文件名前綴  
server.tomcat.accesslog.prefix=localhost_access_log
# 日志文件名后綴  
server.tomcat.accesslog.suffix=.log
server:  
  tomcat:  
    accesslog:  
      enabled: true  # 啟用Tomcat訪問日志
      buffered: true  # 啟用緩沖模式,日志會(huì)先寫入緩沖區(qū),然后定期刷新到磁盤 
      directory: logs  # 指定日志存儲(chǔ)目錄,這里是相對于項(xiàng)目根目錄的logs文件夾  
      file-date-format: ".yyyy-MM-dd"   # 定義日志文件名的日期格式
      pattern: "%{X-Forwarded-For}i %p %l %r %t %s %b %T"  # 定義日志記錄的格式   
      prefix: localhost_access_log   # 日志文件名前綴  
      suffix: .log # 日志文件名后綴

- 8080 - - [19/Jun/2024:00:00:09 +0800] GET /springboot/test1 HTTP/1.1 200 92 0.247 Ignored_Trace
- 8080 - - [19/Jun/2024:00:00:09 +0800] GET /springboot/test2 HTTP/1.1 200 92 0.247 Ignored_Trace
- 8080 - - [19/Jun/2024:09:49:55 +0800] POST /springboot/test3 HTTP/1.1 200 291556 0.314 Ignored_Trace

優(yōu)點(diǎn):

  • 集成性:Tomcat 內(nèi)置功能,無需額外代碼或配置。
  • 全面性:記錄所有通過 Tomcat 處理的請求和響應(yīng)信息。

缺點(diǎn):

  • 性能:訪問日志可能會(huì)對 Tomcat 性能產(chǎn)生一定影響。
  • 精度:同樣只能記錄整個(gè)請求的處理時(shí)間,無法精確到具體的方法執(zhí)行時(shí)間。
  • 配置復(fù)雜性:對于復(fù)雜的日志格式或需求,可能需要修改 Tomcat 的配置文件。

**常用性:**Tomcat 的訪問日志通常用于監(jiān)控 Web 服務(wù)器的訪問情況,如 IP 地址、請求路徑、HTTP 狀態(tài)碼等。雖然它可以記錄請求處理時(shí)間,但通常不會(huì)用于精確的性能分析或接口執(zhí)行時(shí)間記錄。

以上就是SpringBoot統(tǒng)計(jì)接口調(diào)用耗時(shí)的三種方式的詳細(xì)內(nèi)容,更多關(guān)于SpringBoot統(tǒng)計(jì)接口耗時(shí)的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • 輕輕松松吃透Java并發(fā)fork/join框架

    輕輕松松吃透Java并發(fā)fork/join框架

    fork/join是一個(gè)工具框架 ,本文詳細(xì)的介紹了fork/join框架的具體使用,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2021-07-07
  • SpringBoot如何通過Map實(shí)現(xiàn)策略模式

    SpringBoot如何通過Map實(shí)現(xiàn)策略模式

    策略模式是一種行為設(shè)計(jì)模式,它允許在運(yùn)行時(shí)選擇算法的行為,在Spring框架中,我們可以利用@Resource注解和Map集合來優(yōu)雅地實(shí)現(xiàn)策略模式,這篇文章主要介紹了SpringBoot如何通過Map實(shí)現(xiàn)策略模式,需要的朋友可以參考下
    2025-03-03
  • IntelliJ IDEA優(yōu)化配置的實(shí)現(xiàn)

    IntelliJ IDEA優(yōu)化配置的實(shí)現(xiàn)

    這篇文章主要介紹了IntelliJ IDEA優(yōu)化配置的實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-07-07
  • 淺析JDBC與數(shù)據(jù)庫如何進(jìn)行數(shù)據(jù)交互及類型轉(zhuǎn)換

    淺析JDBC與數(shù)據(jù)庫如何進(jìn)行數(shù)據(jù)交互及類型轉(zhuǎn)換

    本文主要介紹了JDBC在Java應(yīng)用程序與數(shù)據(jù)庫交互中的關(guān)鍵作用,詳細(xì)解釋了數(shù)據(jù)交互流程和數(shù)據(jù)類型轉(zhuǎn)換機(jī)制,并提供了高級數(shù)據(jù)交互機(jī)制、優(yōu)化建議及實(shí)際驅(qū)動(dòng)示例,希望對大家有所幫助
    2026-04-04
  • SpringBoot 監(jiān)聽Redis鍵過期事件(過期監(jiān)聽)

    SpringBoot 監(jiān)聽Redis鍵過期事件(過期監(jiān)聽)

    Redis鍵過期事件是SpringBoot中常用的緩存失效通知方式,通過配置可以監(jiān)聽特定鍵的過期事件,具有一定的參考價(jià)值,感興趣的可以了解一下
    2024-12-12
  • Java 實(shí)現(xiàn)對稱加密算法

    Java 實(shí)現(xiàn)對稱加密算法

    這篇文章主要介紹了Java 實(shí)現(xiàn)對稱加密算法的相關(guān)資料,幫助大家更好的理解和學(xué)習(xí)Java,感興趣的朋友可以了解下
    2020-11-11
  • 深入了解JVM字節(jié)碼增強(qiáng)技術(shù)

    深入了解JVM字節(jié)碼增強(qiáng)技術(shù)

    這篇文章主要介紹了深入了解JVM字節(jié)碼增強(qiáng)技術(shù),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2019-11-11
  • 詳解Nacos中注冊中心和配置中心的實(shí)現(xiàn)

    詳解Nacos中注冊中心和配置中心的實(shí)現(xiàn)

    Spring?Cloud?Alibaba?是阿里巴巴提供的一站式微服務(wù)開發(fā)解決方案。而?Nacos?作為?Spring?Cloud?Alibaba?的核心組件之一,提供了兩個(gè)非常重要的功能:注冊中心和配置中心,我們今天來了解和實(shí)現(xiàn)一下二者
    2022-08-08
  • 淺析Spring?Cloud?Gateway中的令牌桶限流算法

    淺析Spring?Cloud?Gateway中的令牌桶限流算法

    這篇文章主要為大家淺析了Spring?Cloud?Gateway中的令牌桶限流算法原理,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步
    2022-02-02
  • Spring?Boot集成validation實(shí)現(xiàn)參數(shù)校驗(yàn)功能

    Spring?Boot集成validation實(shí)現(xiàn)參數(shù)校驗(yàn)功能

    Bean?Validation?是一個(gè)運(yùn)行時(shí)的數(shù)據(jù)驗(yàn)證框架,在驗(yàn)證之后驗(yàn)證的錯(cuò)誤信息會(huì)被馬上返回,這篇文章主要介紹了Spring?Boot集成validation實(shí)現(xiàn)參數(shù)校驗(yàn)功能,需要的朋友可以參考下
    2024-05-05

最新評論

武宣县| 万全县| 原平市| 汉源县| 甘孜县| 沈丘县| 什邡市| 安徽省| 塔城市| 郸城县| 图木舒克市| 玉屏| 揭阳市| 阿荣旗| 织金县| 扎兰屯市| 宜宾县| 盐城市| 临夏市| 岢岚县| 东城区| 天全县| 余江县| 囊谦县| 德阳市| 江阴市| 舟山市| 高唐县| 黄平县| 敖汉旗| 靖远县| 新晃| 施甸县| 漠河县| 彰化市| 施秉县| 永济市| 黑水县| 图片| 衡阳市| 大厂|