SpringBoot統(tǒng)計接口請求耗時的方法詳解
寫在前面
接口請求時間的快慢就代表著獲取到對應(yīng)的數(shù)據(jù)的快慢,也代表著用戶請求頁面數(shù)據(jù)的快慢,常??梢越柚涌谡埱罂炻M(jìn)行相應(yīng)的優(yōu)化!
以往我們的做法可能是在每一個接口的方法中的開始添加當(dāng)前時間,結(jié)尾用當(dāng)前時間減去開始時間就表示該接口的訪問時間。
具體代碼如下:
@RequestMapping("/test") public String test(){ long startTime = System.currentTimeMillis(); //此處的調(diào)用業(yè)務(wù)代碼省略 System.out.println("訪問時間為:"+(System.currentTimeMillis()-startTime)); return "訪問接口成功"; }
那如果有幾百個接口的話,每一個接口都需要統(tǒng)計對應(yīng)的訪問時間的話,那就要寫幾百遍,這很不符合我們的常理,所以有沒有一種辦法是可以不修改對應(yīng)的接口方法,并且只需要寫一遍就能夠應(yīng)用到所有的接口上面或者指定的接口上面。
我們第一時間就可以想到AOP技術(shù),AOP是在Spring當(dāng)中比較常見的技術(shù), AOP就是在不修改原來的代碼就可以對接口方法進(jìn)行增強(qiáng)的作用,利用AOP可以對業(yè)務(wù)邏輯的各個部分進(jìn)行隔離,從而使得業(yè)務(wù)邏輯各部分之間的耦合度降低,提高程序的可重用性,同時提高了開發(fā)的效率。
解決方案
根據(jù)上述,我們需要到AOP,第一個不能少的則是對應(yīng)的依賴。
引入對應(yīng)依賴
<!--aspectj--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-aop</artifactId> <version>2.7.4</version> </dependency>
自定義注解
統(tǒng)計接口的耗時和訪問次數(shù)也不需要每一個接口都使用,比如說一些不經(jīng)常訪問的接口就沒有統(tǒng)計他的訪問次數(shù),所以我們可以自定義一個注解,只要對應(yīng)的接口方法上應(yīng)用了這個注解,Spring會進(jìn)行掃描,并執(zhí)行對應(yīng)的統(tǒng)計耗時操作即可。
import java.lang.annotation.Documented; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; /** * 統(tǒng)計 方法/接口耗時 注解 * * @author devcheng */ @Documented @Target(ElementType.METHOD) @Retention(RetentionPolicy.RUNTIME) public @interface CostTime { }
定義AOP切面
如果接口方法上應(yīng)用了自定義的注解,那么就會被Spring掃描到,這里我用的是 @Pointcut 和 @Around 配合使用。
import lombok.extern.slf4j.Slf4j; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.Around; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Pointcut; import org.springframework.stereotype.Component; /** * 統(tǒng)計 方法/接口耗時 注解 * * @author devcheng */ @Aspect @Component @Slf4j public class CostTimeAspect { @Pointcut(value = "@annotation(net.devcheng.www.data.annotation.CostTime)") public void costTime() { } @Around("costTime()") public Object costTimeAround(ProceedingJoinPoint joinPoint) { Object obj = null; try { long beginTime = System.currentTimeMillis(); obj = joinPoint.proceed(); //獲取方法名稱 String method = joinPoint.getSignature().getName(); //獲取類名稱 String className=joinPoint.getSignature().getDeclaringTypeName(); //計算耗時 long cost = System.currentTimeMillis() - beginTime; log.error("類:[{}],方法:[{}] 接口耗時:[{}]", className,method, cost + "毫秒"); } catch (Throwable throwable) { throwable.printStackTrace(); } return obj; } }
用在統(tǒng)計接口上
@GetMapping("/V4/getSignsPredictDetail") @ResponseBody @CostTime public String getSignsPredictDetail(String name) { if (StringUtils.isEmpty(name)) { return "[]"; } return cityBrain4Service.getSignsPredictDetailByName(name); }
用在統(tǒng)計定時任務(wù)上
@Scheduled(cron = "55 */5 * * * ?") @CostTime public void scenesSignTask() { // 業(yè)務(wù)邏輯 }
運(yùn)行輸出
2022-11-18 10:31:51.523 [http-nio-8886-exec-8] ERROR net.devcheng.www.data.config.CostTimeAspect Line:32 - 類:[net.devcheng.www.data.controller.SpecialInterfaceController],方法:[getWeather] 接口耗時:[0毫秒] 2022-11-18 10:31:52.122 [http-nio-8886-exec-9] ERROR net.devcheng.www.data.config.CostTimeAspect Line:32 - 類:[net.devcheng.www.data.controller.SpecialInterfaceController],方法:[getWeather] 接口耗時:[1毫秒] 2022-11-18 10:31:55.073 [http-nio-8886-exec-15] ERROR net.devcheng.www.data.config.CostTimeAspect Line:32 - 類:[net.devcheng.www.data.controller.CityBrain4Controller],方法:[getScrollingMessages] 接口耗時:[2毫秒] 2022-11-18 10:31:55.076 [http-nio-8886-exec-3] ERROR net.devcheng.www.data.config.CostTimeAspect Line:32 - 類:[net.devcheng.www.data.controller.SpecialInterfaceController],方法:[getWeather] 接口耗時:[1毫秒]
以上就是SpringBoot統(tǒng)計接口請求耗時的方法詳解的詳細(xì)內(nèi)容,更多關(guān)于SpringBoot接口請求耗時的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
淺談StringEntity 和 UrlEncodedFormEntity之間的區(qū)別
這篇文章主要介紹了StringEntity 和 UrlEncodedFormEntity之間的區(qū)別,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2021-06-06MyBatis使用<foreach>標(biāo)簽報錯問題及解決
這篇文章主要介紹了MyBatis使用<foreach>標(biāo)簽報錯問題及解決,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2024-03-03springboot中EasyPoi實(shí)現(xiàn)自動新增序號的方法
本文主要介紹了EasyPoi實(shí)現(xiàn)自動新增序號,文中通過示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下2021-09-09Java中HashTable和HashMap的區(qū)別_動力節(jié)點(diǎn)Java學(xué)院整理
HashTable和HashMap主要的區(qū)別有:線程安全性,同步(synchronization),以及速度。接下來通過本文給大家簡單介紹下HashTable和HashMap的區(qū)別,需要的的朋友參考下吧2017-04-04SpringBoot中Tomcat和SpringMVC整合源碼分析
Tomcat和SpringMVC都是通過這樣的方式進(jìn)行集成的,SpringBoot出現(xiàn)之前SpringMVC項(xiàng)目是直接部署在Tomcat服務(wù)器中的,這篇文章主要介紹了SpringBoot中Tomcat和SpringMVC整合源碼分析,需要的朋友可以參考下2022-07-07