盤點多種方法耗時統計的實操解法
前言
在應用開發里,精準把控方法執行耗時,對優化系統性能、提升用戶體驗意義重大。下面將介紹幾種不同的方法耗時統計方式,每種都有其獨特的適用場景。
System.currentTimeMillis ()
在方法內借助System.currentTimeMillis()記錄起始和結束時間,進而算出方法執行耗時。這種方式簡單直接,無需引入額外依賴。
@Service
public class BookService {
public Book getBookById(Long id) {
long startTime = System.currentTimeMillis();
// 模擬從數據庫獲取書籍信息的業務邏輯
Book book = bookRepository.findById(id).orElse(null);
long endTime = System.currentTimeMillis();
long elapsedTime = endTime - startTime;
System.out.println("getBookById方法耗時:" + elapsedTime + "ms");
return book;
}
}
利用 StopWatch
@Service
public class UserService {
public User findUserById(Long id) {
StopWatch stopWatch = new StopWatch();
stopWatch.start();
// 模擬業務邏輯,這里從數據庫查詢用戶信息
User user = userRepository.findById(id).orElse(null);
stopWatch.stop();
System.out.println("findUserById方法執行耗時:" + stopWatch.getTotalTimeMillis() + "毫秒");
return user;
}
}
使用AOP實現全局方法
在 項目中配置aop依賴后,就能利用它進行方法耗時統計
@Aspect
@Component
public class MethodTimeAspect {
@Around("execution(* com.example.demo.service.*.*(..))")
public Object measureTime(ProceedingJoinPoint joinPoint) throws Throwable {
long startTime = System.currentTimeMillis();
Object result = joinPoint.proceed();
long endTime = System.currentTimeMillis();
long elapsedTime = endTime - startTime;
String methodName = joinPoint.getSignature().getName();
System.out.println("方法[" + methodName + "]耗時:" + elapsedTime + "ms");
return result;
}
}
利用 HandlerInterceptor 統計
Spring的HandlerInterceptor可用于監控Controller層接口的耗時情況
public class ControllerTimeInterceptor implements HandlerInterceptor {
private ThreadLocal<Long> startTime = new ThreadLocal<>();
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
startTime.set(System.currentTimeMillis());
returntrue;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) {
long endTime = System.currentTimeMillis();
long elapsedTime = endTime - startTime.get();
String uri = request.getRequestURI();
System.out.println("接口[" + uri + "]耗時:" + elapsedTime + "ms");
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {
// 可在此處進行資源清理等操作
startTime.remove();
}
}
@Configuration
public class WebMvcConfig implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new ControllerTimeInterceptor())
.addPathPatterns("/api/**");
}
}
基于 Servlet Filter 統計
通過創建Servlet Filter,可記錄HTTP請求的整體耗時
@WebFilter("/*")
public class RequestTimeFilter implements Filter {
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
long startTime = System.currentTimeMillis();
chain.doFilter(request, response);
long endTime = System.currentTimeMillis();
long elapsedTime = endTime - startTime;
String requestUri = ((HttpServletRequest) request).getRequestURI();
System.out.println("請求[" + requestUri + "]耗時:" + elapsedTime + "ms");
}
@Override
public void init(FilterConfig filterConfig) throws ServletException {}
@Override
public void destroy() {}
}
使用ServletRequestHandledEvent統計
在Spring框架中,監控接口請求的性能可以通過ServletRequestHandledEvent事件實現
@Component
public class TimeCountListener implements ApplicationListener<ServletRequestHandledEvent> {
@Override
public void onApplicationEvent(ServletRequestHandledEvent event) {
Throwable failureCause = event.getFailureCause();
if (failureCause != null) {
System.err.printf("錯誤原因: %s%n", failureCause.getMessage());
}
System.err.println("========================================");
System.err.printf("請求客戶端地址:%s\n請求URL: %s\n請求Method: %s\n請求耗時: %d毫秒%n",
event.getClientAddress(),
event.getRequestUrl(),
event.getMethod(),
event.getProcessingTimeMillis());
System.err.println("========================================");
}
}
實際開發時,需根據項目規模、業務場景、性能需求等因素綜合考慮,選擇最合適的方法,從而高效地進行性能優化。