接口请求超时需分层捕获并统一响应:HTTP客户端超时捕获ResourceAccessException,MVC异步超时捕获AsyncRequestTimeoutException,数据库超时捕获SQLTimeoutException,配合过滤器预设超时阈值并主动抛出异常,返回504/408状态码及结构化错误信息。

接口请求超时属于运行时异常,但不是 Java 或 Spring 默认捕获的“业务异常”,它通常发生在网络层或框架底层(如 HttpClient 超时、Tomcat 连接超时、Feign 超时等),**不会自动抛出标准 RuntimeException 子类供 @ExceptionHandler 直接捕获**。因此,全局异常处理器无法直接 catch “超时”本身,而要从源头识别、标记、再统一响应。
明确超时发生的位置和类型
不同层级的超时需区别对待:
-
HTTP 客户端超时(如 RestTemplate / Feign / WebClient):触发的是
ResourceAccessException(含SocketTimeoutException)、ConnectException等底层 I/O 异常; -
Spring MVC 请求处理超时(如 Tomcat 的
connectionTimeout或asyncTimeout):可能表现为AsyncRequestTimeoutException; -
数据库连接/查询超时(如 HikariCP、MyBatis):抛出
SQLTimeoutException或PersistenceException; - 前端 Axios/Fetch 超时:属于前端行为,后端无感知,不进入 Java 异常链。
在全局异常处理器中捕获超时相关异常
需在 @ControllerAdvice 类中显式注册对这些底层异常的处理逻辑,而不是等待“超时异常”自动出现:
- 添加
@ExceptionHandler(ResourceAccessException.class)捕获 RestTemplate 网络超时; - 添加
@ExceptionHandler(AsyncRequestTimeoutException.class)处理异步请求超时; - 添加
@ExceptionHandler(SQLTimeoutException.class)处理 DB 查询超时; - 可统一 fallback 到
@ExceptionHandler(TimeoutException.class)(注意:这是java.util.concurrent.TimeoutException,需确认是否被实际抛出)。
每个 handler 返回结构化错误响应(如统一 Result<Void> 或 ErrorResponse),状态码建议用 504 Gateway Timeout 或 408 Request Timeout,并附带可读提示:“请求处理超时,请稍后重试”。
Java项目代码review工具。分析Git变更+完整调用链路上下文,推断业务需求,进行多维度评分和分类汇总,生成完整PRD文档。包含细粒度Java代码审查清单(Null安全、异常处理、Streams、并发、equals/hashCode、资源管理、API设计、性能、MyBatis/ORM、事务边界、SQL/DD...
配合中间件/过滤器提前识别超时意图
单纯靠异常捕获不够主动。可在请求入口处埋点:
- 使用
OncePerRequestFilter解析请求头(如X-Timeout-Ms: 8000),记录预期超时阈值; - 结合
HandlerInterceptor.preHandle设置线程本地超时上下文; - 当后续检测到耗时接近阈值,可主动抛出自定义
RequestTimeoutException,便于 @ExceptionHandler 精准捕获并返回一致响应。
避免误捕与日志可追溯
超时异常容易和网络中断、服务不可用混淆,需增强可观测性:
- 在异常处理器中打印完整堆栈 + 请求 URI + client IP + 耗时(若能获取);
- 区分
SocketTimeoutException(读超时)和ConnectException(连不上),前者更可能是服务慢,后者更倾向网络或服务宕机; - 避免把所有
ResourceAccessException都当成超时——需检查 cause 是否为SocketTimeoutException或其子类。
不复杂但容易忽略

















