本文目录导读:

- 基础方案:手动计算时间(最直接)
- AOP 方案:统一拦截(推荐)
- Spring Boot Actuator + Micrometer(生产环境推荐)
- 使用 Spring Cloud Sleuth(分布式追踪)
- 过滤器/拦截器方案(Web 层)
- 高级方案:慢查询日志与告警
- 总结与最佳实践
在Java开发中,统计接口耗时(API响应时间)是一个非常常见的需求,主要用于性能监控、问题排查和优化,以下是几种从简单到复杂的实现方案:
基础方案:手动计算时间(最直接)
1 使用 System.currentTimeMillis()
@GetMapping("/example")
public String example() {
long startTime = System.currentTimeMillis();
// 业务逻辑
// ...
long endTime = System.currentTimeMillis();
long duration = endTime - startTime;
System.out.println("接口耗时: " + duration + " ms");
return "success";
}
2 使用 StopWatch(Spring 提供)
import org.springframework.util.StopWatch;
@GetMapping("/stopwatch")
public String stopwatchExample() {
StopWatch stopWatch = new StopWatch("接口耗时统计");
stopWatch.start();
// 业务逻辑
// ...
stopWatch.stop();
log.info("接口耗时: {} ms", stopWatch.getTotalTimeMillis());
// 可以统计多个步骤
System.out.println(stopWatch.prettyPrint());
return "success";
}
AOP 方案:统一拦截(推荐)
使用 Spring AOP 或自定义注解,统一统计耗时,避免代码侵入。
1 创建自定义注解
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface TimeLog {
String value() default "";
}
2 编写 AOP 切面
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
@Aspect
@Component
public class TimeLogAspect {
private static final Logger log = LoggerFactory.getLogger(TimeLogAspect.class);
@Around("@annotation(timeLog)")
public Object around(ProceedingJoinPoint joinPoint, TimeLog timeLog) throws Throwable {
long startTime = System.currentTimeMillis();
try {
Object result = joinPoint.proceed();
long duration = System.currentTimeMillis() - startTime;
log.info("接口: {} 耗时: {} ms",
joinPoint.getSignature().toShortString(),
duration);
return result;
} catch (Throwable throwable) {
long duration = System.currentTimeMillis() - startTime;
log.error("接口: {} 执行异常,耗时: {} ms",
joinPoint.getSignature().toShortString(),
duration);
throw throwable;
}
}
}
3 使用注解
@RestController
public class DemoController {
@TimeLog("查询用户信息")
@GetMapping("/user/{id}")
public User getUser(@PathVariable String id) {
// 业务逻辑
return userService.findById(id);
}
}
4 更通用的切面(拦截所有 Controller)
@Aspect
@Component
public class ControllerTimeAspect {
@Around("execution(* com.example.controller.*.*(..))")
public Object aroundController(ProceedingJoinPoint joinPoint) throws Throwable {
long start = System.currentTimeMillis();
Object result = joinPoint.proceed();
long duration = System.currentTimeMillis() - start;
// 获取请求路径(如果是 Spring MVC)
RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
if (requestAttributes != null) {
HttpServletRequest request = ((ServletRequestAttributes) requestAttributes).getRequest();
String uri = request.getRequestURI();
String method = request.getMethod();
log.info("[{}] {} 耗时: {} ms", method, uri, duration);
}
return result;
}
}
Spring Boot Actuator + Micrometer(生产环境推荐)
用于生产环境的监控,配合 Prometheus + Grafana。
1 添加依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>io.micrometer</groupId>
<artifactId>micrometer-registry-prometheus</artifactId>
</dependency>
2 配置
management:
endpoints:
web:
exposure:
include: health,metrics,prometheus
metrics:
tags:
application: your-appname
3 自定义 Metrics(可选)
import io.micrometer.core.instrument.MeterRegistry;
import org.springframework.stereotype.Component;
@Component
public class ApiMetricsCollector {
private final MeterRegistry meterRegistry;
public ApiMetricsCollector(MeterRegistry meterRegistry) {
this.meterRegistry = meterRegistry;
}
public void recordTime(String apiName, long durationMs) {
meterRegistry.timer("api.response.time", "api", apiName)
.record(durationMs, TimeUnit.MILLISECONDS);
}
}
使用 Spring Cloud Sleuth(分布式追踪)
用于微服务场景,可以查看一次请求经过的所有服务的耗时。
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-sleuth</artifactId>
</dependency>
配置后,日志会自动包含 Trace ID 和 Span ID,配合 Zipkin 可以可视化查看调用链路。
过滤器/拦截器方案(Web 层)
1 实现 HandlerInterceptor
@Component
public class TimeInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
request.setAttribute("startTime", System.currentTimeMillis());
return true;
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response,
Object handler, Exception ex) {
Long startTime = (Long) request.getAttribute("startTime");
if (startTime != null) {
long duration = System.currentTimeMillis() - startTime;
log.info("[{}] {} 耗时: {} ms",
request.getMethod(),
request.getRequestURI(),
duration);
}
}
}
2 注册拦截器
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Autowired
private TimeInterceptor timeInterceptor;
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(timeInterceptor)
.addPathPatterns("/**");
}
}
高级方案:慢查询日志与告警
结合 AOP 和告警逻辑,超过阈值时发送告警。
@Around("@annotation(timeLog)")
public Object around(ProceedingJoinPoint joinPoint, TimeLog timeLog) throws Throwable {
long start = System.currentTimeMillis();
Object result = joinPoint.proceed();
long duration = System.currentTimeMillis() - start;
// 慢查询告警
if (duration > 1000) { // 超过1秒
log.warn("慢接口警告: {} 耗时 {} ms",
joinPoint.getSignature().toShortString(),
duration);
// 发送告警邮件/钉钉通知等
alertService.sendSlowApiAlert(joinPoint.getSignature().toShortString(), duration);
}
return result;
}
总结与最佳实践
| 方案 | 适用场景 | 优点 | 缺点 |
|---|---|---|---|
| 手动计算 | 临时调试 | 简单直接 | 代码侵入强 |
| AOP 注解 | 日常开发 | 无侵入,统一管理 | 需要引入 AOP |
| Actuator + Micrometer | 生产监控 | 可视化,与监控系统集成 | 部署复杂 |
| 过滤器/拦截器 | Web 层统一 | 无需修改业务代码 | 无法统计 Service 层 |
| Sleuth | 微服务 | 全链路追踪 | 依赖 Zipkin |
推荐方案:
- 开发测试:使用 AOP + 自定义注解
- 生产环境:Actuator + Micrometer + Prometheus + Grafana
- 微服务:Sleuth + Zipkin
选择哪种方案取决于你的项目复杂度和监控需求,对于大多数中小项目,AOP 方案是最实用且侵入性最低的选择。
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播