一、什么是 DeferredResult
DeferredResult 是 Spring MVC 3.2 引入的一个类,用于支持异步请求处理。它允许在一个线程中接收 HTTP 请求,而在另一个线程中生成响应结果,从而实现真正的异步非阻塞处理。
1.1 为什么需要 DeferredResult
在传统的 Servlet 模型中,每个请求会占用一个线程,直到响应完成。这种模型存在以下问题:
-
线程资源浪费:当处理耗时操作(如调用远程服务、查询数据库)时,线程会一直阻塞等待 -
并发能力受限:服务器线程池大小有限,大量长时间请求会耗尽线程资源 -
响应延迟:在高并发场景下,请求可能在线程池队列中等待很久
DeferredResult 通过异步处理解决了这些问题,使得处理线程可以立即释放,去处理其他请求。
二、DeferredResult 工作原理
2.1 处理流程
-
请求到达 → DispatcherServlet 接收 -
Controller 创建并返回 DeferredResult 对象 -
Servlet 容器线程立即释放 -
业务线程异步处理任务 -
业务线程调用 DeferredResult.setResult() 设置结果 -
Spring MVC 获取结果并返回给客户端
2.2 核心特点
-
线程分离:接收请求的线程和生成响应的线程可以不同 -
长连接支持:适合长轮询、服务器推送等场景 -
超时处理:支持设置超时时间和超时回调 -
异常处理:支持异步异常处理机制
三、基本使用示例
3.1 简单的异步处理
@RestController
@RequestMapping("/api")
publicclass AsyncController {
@GetMapping("/async")
public DeferredResult<String> asyncRequest() {
// 创建 DeferredResult,设置超时时间为 5 秒
DeferredResult<String> deferredResult = new DeferredResult<>(5000L);
// 在另一个线程中处理业务逻辑
CompletableFuture.runAsync(() -> {
try {
// 模拟耗时操作
Thread.sleep(2000);
// 设置返回结果
deferredResult.setResult("异步处理完成");
} catch (Exception e) {
// 设置错误结果
deferredResult.setErrorResult(e);
}
});
// 立即返回 DeferredResult,释放请求线程
return deferredResult;
}
}
3.2 带超时处理的示例
@GetMapping("/async-with-timeout")
public DeferredResult<String> asyncWithTimeout() {
DeferredResult<String> deferredResult = new DeferredResult<>(3000L);
// 设置超时回调
deferredResult.onTimeout(() -> {
deferredResult.setErrorResult("请求超时");
});
// 设置完成回调
deferredResult.onCompletion(() -> {
System.out.println("请求处理完成");
});
// 异步处理
CompletableFuture.runAsync(() -> {
try {
Thread.sleep(5000); // 模拟超过超时时间
deferredResult.setResult("处理完成");
} catch (Exception e) {
if (!deferredResult.isSetOrExpired()) {
deferredResult.setErrorResult(e);
}
}
});
return deferredResult;
}
DeferredResult vs Callable
Spring MVC 还提供了另一种异步处理方式 Callable,两者的区别:
|
|
|
|
|---|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Callable 示例:
@GetMapping("/callable")
public Callable<String> callableRequest() {
return () -> {
Thread.sleep(2000);
return "Callable 处理完成";
};
}
总结
DeferredResult 是 Spring MVC 提供的强大异步处理机制,特别适合以下场景:
-
长时间运行的任务:避免阻塞请求线程 -
事件驱动架构:等待外部事件触发响应 -
长轮询:实现服务器推送功能 -
并发请求聚合:同时调用多个服务并聚合结果 -
提高系统吞吐量:释放线程资源,处理更多并发请求

