大数跨境
0
0

DeferredResult:Spring MVC 异步请求处理

DeferredResult:Spring MVC 异步请求处理 王老师运营实战
2025-10-23
1
导读:一、什么是 DeferredResultDeferredResult 是 Spring MVC 3.2 引入的

一、什么是 DeferredResult

DeferredResult 是 Spring MVC 3.2 引入的一个类,用于支持异步请求处理。它允许在一个线程中接收 HTTP 请求,而在另一个线程中生成响应结果,从而实现真正的异步非阻塞处理。

1.1 为什么需要 DeferredResult

在传统的 Servlet 模型中,每个请求会占用一个线程,直到响应完成。这种模型存在以下问题:

  • 线程资源浪费:当处理耗时操作(如调用远程服务、查询数据库)时,线程会一直阻塞等待
  • 并发能力受限:服务器线程池大小有限,大量长时间请求会耗尽线程资源
  • 响应延迟:在高并发场景下,请求可能在线程池队列中等待很久

DeferredResult 通过异步处理解决了这些问题,使得处理线程可以立即释放,去处理其他请求。

二、DeferredResult 工作原理

2.1 处理流程

  1. 请求到达 → DispatcherServlet 接收
  2. Controller 创建并返回 DeferredResult 对象
  3. Servlet 容器线程立即释放
  4. 业务线程异步处理任务
  5. 业务线程调用 DeferredResult.setResult() 设置结果
  6. 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,两者的区别:

特性
DeferredResult
Callable
控制粒度
完全控制,可以在任何线程设置结果
由 Spring 管理线程池执行
适用场景
事件驱动、长轮询、消息队列等
简单的异步计算任务
灵活性
高,支持复杂的异步场景
低,适合简单场景
超时处理
需要手动处理
自动处理

Callable 示例:

@GetMapping("/callable")
public Callable<String> callableRequest() {
    return () -> {
        Thread.sleep(2000);
        return "Callable 处理完成";
    };
}

总结

DeferredResult 是 Spring MVC 提供的强大异步处理机制,特别适合以下场景:

  • 长时间运行的任务:避免阻塞请求线程
  • 事件驱动架构:等待外部事件触发响应
  • 长轮询:实现服务器推送功能
  • 并发请求聚合:同时调用多个服务并聚合结果
  • 提高系统吞吐量:释放线程资源,处理更多并发请求

【声明】内容源于网络
0
0
王老师运营实战
跨境分享园 | 每天记录实用知识
内容 42170
粉丝 1
王老师运营实战 跨境分享园 | 每天记录实用知识
总阅读204.3k
粉丝1
内容42.2k