DeferredResult 的核心目的是将耗时操作从 Web 容器线程剥离,及时释放线程池资源以提升并发能力;其用法是控制器立即返回 DeferredResult 实例,再由独立线程调用 setResult() 或 setErrorResult() 触发响应,支持超时回调、异常处理及 Servlet 3.0+ 异步配置。

Spring MVC 中使用 DeferredResult 的核心目的,是把耗时操作(如远程调用、数据库慢查询、消息队列等待)从 Web 容器线程中剥离出来,让 Tomcat/Jetty 等容器线程能及时归还给线程池,避免被长时间阻塞,从而提升并发处理能力。
DeferredResult 基本用法:立即返回并异步设值
控制器方法直接返回 DeferredResult 实例,不阻塞当前请求线程;后续在其他线程(如线程池、回调线程)中调用 setResult() 或 setErrorResult() 触发响应写入。
- 声明一个带泛型的
DeferredResult<String>(泛型类型即响应体类型) - 构造时可传入超时毫秒数,超时后自动触发默认响应或异常
- 必须在某个非容器线程里调用
setResult(),否则仍会阻塞
配合线程池执行耗时逻辑,真正释放容器线程
不能在 Controller 方法里直接 sleep 或同步调用慢服务 —— 那样只是把阻塞延迟到 setResult(),容器线程仍在等待。正确做法是交由独立线程池异步执行:
- 注入
TaskExecutor(如ThreadPoolTaskExecutor) - 在 Controller 中提交任务,任务完成后再调用
deferredResult.setResult(...) - 确保该线程池与 Web 容器线程池物理隔离(不复用 Tomcat 的
exec-*线程)
超时与异常处理必须显式覆盖
DeferredResult 超时默认返回 503,业务通常需自定义行为:
立即学习“Java免费学习笔记(深入)”;
- 通过
onTimeout(Runnable)注册超时回调,例如记录日志、设置降级响应 - 通过
onCompletion(Runnable)处理最终完成(成功/超时/异常),用于清理资源 - 若异步逻辑抛异常,应捕获后调用
deferredResult.setErrorResult(e),避免静默失败
注意 Servlet 容器兼容性与配置
启用异步支持是前提:
- Servlet 3.0+ 必须开启(Spring Boot 默认已开,传统 XML 需确认
<servlet>中async-supported=true) - Tomcat 中建议调大
connectionTimeout和asyncTimeout,避免底层连接提前关闭 - 反向代理(如 Nginx)要配置
proxy_read_timeout大于业务预期最大延迟


















