DeferredResult 是 Spring Framework 提供的一个用于处理异步请求的类
DeferredResult 使开发者可以将请求的处理结果延迟到另一个线程中完成
DeferredResult 适合处理耗时操作或需要等待事件触发的场景
DeferredResult 的核心思想是将请求挂起,直到在另一个线程中完成操作后,再将结果返回给客户端
@GetMapping("/setResultTest")
public DeferredResult<String> setResultTest() {
DeferredResult<String> deferredResult = new DeferredResult<>();
new Thread(() -> {
try {
Thread.sleep(5 * 1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
deferredResult.setResult("success");
}).start();
return deferredResult;
}
创建 DeferredResult 对象
启动一个新线程,模拟耗时操作
5 秒后调用 setResult 方法设置成功结果
由 Spring Framework 将结果返回给客户端
success
@GetMapping("/setErrorResultTest")
public DeferredResult<String> setErrorResultTest() {
DeferredResult<String> deferredResult = new DeferredResult<>();
new Thread(() -> {
try {
Thread.sleep(5 * 1000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
deferredResult.setErrorResult("error");
}).start();
return deferredResult;
}
创建 DeferredResult 对象
启动一个新线程,模拟耗时操作
5 秒后调用 setErrorResult 方法设置错误结果
由 Spring Framework 将结果返回给客户端
error
@GetMapping("/onTimeoutTest1")
public DeferredResult<String> onTimeoutTest1() {
DeferredResult<String> deferredResult = new DeferredResult<>(3 * 1000L);
new Thread(() -> {
try {
Thread.sleep(5 * 1000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
deferredResult.setErrorResult("error");
}).start();
deferredResult.onTimeout(() -> {
deferredResult.setResult("timeout 1");
});
return deferredResult;
}
创建 DeferredResult 对象,并设置超时时间为 3 秒
启动一个新线程,模拟耗时操作(5 秒)
设置超时回调,超时时调用 setResult 方法设置自定义超时结果
由于耗时操作需要 5 秒,而超时时间为 3 秒,因此会触发超时,同时触发回调
由 Spring Framework 将自定义超时结果返回给客户端
timeout 1
@GetMapping("/onTimeoutTest2")
public DeferredResult<String> onTimeoutTest2() {
DeferredResult<String> deferredResult = new DeferredResult<>(3 * 1000L);
new Thread(() -> {
try {
Thread.sleep(5 * 1000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
deferredResult.setResult("success");
}).start();
return deferredResult;
}
创建 DeferredResult 对象,并设置超时时间为 3 秒
启动一个新线程,模拟耗时操作(5 秒)
由于耗时操作需要 5 秒,而超时时间为 3 秒,因此会触发超时
由 Spring Framework 将默认超时结果返回给客户端
{
"timestamp": "2025-03-04T11:09:41.612+00:00",
"status": 503,
"error": "Service Unavailable",
"path": "/async/onTimeoutTest2"
}
@GetMapping("/onTimeoutTest3")
public DeferredResult<String> onTimeoutTest3() {
DeferredResult<String> deferredResult = new DeferredResult<>(3 * 1000L, "timeout 3");
new Thread(() -> {
try {
Thread.sleep(5 * 1000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
deferredResult.setResult("success");
}).start();
return deferredResult;
}
创建 DeferredResult 对象,设置超时时间为 3 秒,设置自定义超时结果
启动一个新线程,模拟耗时操作(5 秒)
由于耗时操作需要 5 秒,而超时时间为 3 秒,因此会触发超时
由 Spring Framework 将自定义超时结果返回给客户端
timeout 3
@GetMapping("/onTimeoutTest4")
public DeferredResult<String> onTimeoutTest4() {
DeferredResult<String> deferredResult = new DeferredResult<>(3 * 1000L, () -> {
return "timeout 4";
});
new Thread(() -> {
try {
Thread.sleep(5 * 1000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
deferredResult.setResult("success");
}).start();
return deferredResult;
}
创建 DeferredResult 对象,设置超时时间为 3 秒,通过回调函数设置自定义超时结果
启动一个新线程,模拟耗时操作(5 秒)
由于耗时操作需要 5 秒,而超时时间为 3 秒,因此会触发超时,同时触发回调
由 Spring Framework 将自定义超时结果返回给客户端
timeout 4
@GetMapping("/onCompletionTest")
public DeferredResult<String> onCompletionTest() {
DeferredResult<String> deferredResult = new DeferredResult<>();
new Thread(() -> {
try {
Thread.sleep(5 * 1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
deferredResult.setResult("success");
}).start();
deferredResult.onCompletion(() -> {
System.out.println("onCompletion");
});
return deferredResult;
}
创建 DeferredResult 对象
启动一个新线程,模拟耗时操作(5 秒)
设置完成回调
5 秒后设置结果,触发完成回调
success
onCompletion
@GetMapping("/isSetOrExpiredTest")
public DeferredResult<String> isSetOrExpiredTest() {
DeferredResult<String> deferredResult = new DeferredResult<>();
new Thread(() -> {
try {
Thread.sleep(5 * 1000); // 模拟耗时操作
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(deferredResult.isSetOrExpired()); // 检查是否已完成或超时
deferredResult.setResult("success");
System.out.println(deferredResult.isSetOrExpired());
}).start();
return deferredResult;
}
创建 DeferredResult 对象
启动一个新线程,模拟耗时操作(5 秒)
在设置结果前后,分别调用 isSetOrExpired 方法检查状态
success
false
true
DeferredResult()
功能:创建一个 DeferredResult 对象,不设置超时时间与默认超时结果
适用场景:适用于不需要超时处理或默认超时结果的场景
DeferredResult(Long timeoutValue)
功能:创建一个 DeferredResult 对象,并设置超时时间(单位为毫秒)
适用场景:适用于需要设置超时时间的场景
参数 | 类型 | 说明 |
---|---|---|
timeoutValue | Long | 超时时间,单位为毫秒 |
DeferredResult(@Nullable Long timeoutValue, Object timeoutResult)
功能:创建一个 DeferredResult 对象,设置超时时间,并指定自定义超时结果
使用场景:适用于需要设置超时时间和自定义超时结果的场景
参数 | 类型 | 说明 |
---|---|---|
timeoutValue | Long | 超时时间,单位为毫秒 |
timeoutResult | Object | 自定义超时结果 |
DeferredResult(@Nullable Long timeoutValue, Supplier<?> timeoutResult)
功能:创建一个 DeferredResult 对象,设置超时时间,并通过回调函数指定自定义超时结果
使用场景:适用于需要通过回调函数动态生成自定义超时结果的场景
参数 | 类型 | 说明 |
---|---|---|
timeoutValue | Long | 超时时间,单位为毫秒 |
timeoutCallback | Supplier> | 超时回调函数,用于生成自定义超时结果 |
boolean setResult(T result)
功能:设置成功结果
使用场景:当异步操作成功完成时,调用该方法设置结果
参数 | 类型 | 说明 |
---|---|---|
result | T | 成功结果 |
boolean setErrorResult(Object result)
功能:设置错误结果
使用场景:当异步操作失败时,调用该方法设置错误结果
参数 | 类型 | 说明 |
---|---|---|
result | T | 错误结果 |
void onTimeout(Runnable callback)
功能:设置超时回调
使用场景:当请求超时时,调用该方法执行自定义逻辑
参数 | 类型 | 说明 |
---|---|---|
callback | Runnable | 超时回调函数,在超时时执行 |
void onCompletion(Runnable callback)
功能:设置完成回调
使用场景:当请求完成时,调用该方法执行自定义逻辑
参数 | 类型 | 说明 |
---|---|---|
callback | Runnable | 完成回调函数,在请求完成时执行 |
boolean isSetOrExpired()
功能:检查 DeferredResult 是否已经设置了结果或已经超时
使用场景:用于在异步任务中检查 DeferredResult 的状态,避免重复设置结果或处理已经超时的请求