Spring Boot 处理异步请求(DeferredResult 基础案例、DeferredResult 超时案例、DeferredResult 扩展案例、DeferredResult 方法汇总)

一、DeferredResult

  1. DeferredResult 是 Spring Framework 提供的一个用于处理异步请求的类

  2. DeferredResult 使开发者可以将请求的处理结果延迟到另一个线程中完成

  3. DeferredResult 适合处理耗时操作或需要等待事件触发的场景

  4. DeferredResult 的核心思想是将请求挂起,直到在另一个线程中完成操作后,再将结果返回给客户端


二、DeferredResult 基础案例

1、setResultTest 案例
@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;
}
(1)案例解析
  • 模拟一个耗时操作,5 秒后返回成功结果
  1. 创建 DeferredResult 对象

  2. 启动一个新线程,模拟耗时操作

  3. 5 秒后调用 setResult 方法设置成功结果

  4. 由 Spring Framework 将结果返回给客户端

(2)测试结果
  • 请求测试结果
success
2、setErrorResultTest 案例
@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;
}
(1)案例解析
  • 模拟一个耗时操作,5 秒后返回错误结果
  1. 创建 DeferredResult 对象

  2. 启动一个新线程,模拟耗时操作

  3. 5 秒后调用 setErrorResult 方法设置错误结果

  4. 由 Spring Framework 将结果返回给客户端

(2)测试结果
  • 请求测试结果
error

三、DeferredResult 超时案例

1、onTimeoutTest1 案例
@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;
}
(1)案例解析
  • 模拟一个耗时操作,设置超时时间为 3 秒,如果超时,返回自定义超时结果
  1. 创建 DeferredResult 对象,并设置超时时间为 3 秒

  2. 启动一个新线程,模拟耗时操作(5 秒)

  3. 设置超时回调,超时时调用 setResult 方法设置自定义超时结果

  4. 由于耗时操作需要 5 秒,而超时时间为 3 秒,因此会触发超时,同时触发回调

  5. 由 Spring Framework 将自定义超时结果返回给客户端

(2)测试结果
  • 请求测试结果
timeout 1
2、onTimeoutTest2 案例
@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;
}
(1)案例解析
  • 模拟一个耗时操作,设置超时时间为 3 秒,如果超时,返回默认超时结果
  1. 创建 DeferredResult 对象,并设置超时时间为 3 秒

  2. 启动一个新线程,模拟耗时操作(5 秒)

  3. 由于耗时操作需要 5 秒,而超时时间为 3 秒,因此会触发超时

  4. 由 Spring Framework 将默认超时结果返回给客户端

(2)测试结果
  • 请求测试结果
{
    "timestamp": "2025-03-04T11:09:41.612+00:00",
    "status": 503,
    "error": "Service Unavailable",
    "path": "/async/onTimeoutTest2"
}
3、onTimeoutTest3 案例
@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;
}
(1)案例解析
  • 模拟一个耗时操作,设置超时时间为 3 秒,如果超时,返回自定义超时结果
  1. 创建 DeferredResult 对象,设置超时时间为 3 秒,设置自定义超时结果

  2. 启动一个新线程,模拟耗时操作(5 秒)

  3. 由于耗时操作需要 5 秒,而超时时间为 3 秒,因此会触发超时

  4. 由 Spring Framework 将自定义超时结果返回给客户端

(2)测试结果
  • 请求测试结果
timeout 3
4、onTimeoutTest4 案例
@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;
}
(1)案例解析
  • 模拟一个耗时操作,设置超时时间为 3 秒,如果超时,返回自定义超时结果
  1. 创建 DeferredResult 对象,设置超时时间为 3 秒,通过回调函数设置自定义超时结果

  2. 启动一个新线程,模拟耗时操作(5 秒)

  3. 由于耗时操作需要 5 秒,而超时时间为 3 秒,因此会触发超时,同时触发回调

  4. 由 Spring Framework 将自定义超时结果返回给客户端

(2)测试结果
  • 请求测试结果
timeout 4

四、DeferredResult 扩展案例

1、onCompletionTest 案例
@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;
}
(1)案例解析
  • 模拟一个耗时操作,并在请求完成时执行回调
  1. 创建 DeferredResult 对象

  2. 启动一个新线程,模拟耗时操作(5 秒)

  3. 设置完成回调

  4. 5 秒后设置结果,触发完成回调

(2)测试结果
  • 请求测试结果
success
  • 服务端输出结果
onCompletion
2、isSetOrExpiredTest 案例
@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;
}
(1)案例解析
  • 模拟一个耗时操作,并检查 DeferredResult 是否已完成或超时
  1. 创建 DeferredResult 对象

  2. 启动一个新线程,模拟耗时操作(5 秒)

  3. 在设置结果前后,分别调用 isSetOrExpired 方法检查状态

(2)测试结果
  • 请求测试结果
success
  • 服务端输出结果
false
true

五、DeferredResult 方法汇总

1、构造方法
(1)无参构造方法
DeferredResult()
  • 功能:创建一个 DeferredResult 对象,不设置超时时间与默认超时结果

  • 适用场景:适用于不需要超时处理或默认超时结果的场景

(2)带超时时间的构造方法
DeferredResult(Long timeoutValue)
  • 功能:创建一个 DeferredResult 对象,并设置超时时间(单位为毫秒)

  • 适用场景:适用于需要设置超时时间的场景

参数 类型 说明
timeoutValue Long 超时时间,单位为毫秒
(3)带超时时间和自定义超时结果的构造方法
DeferredResult(@Nullable Long timeoutValue, Object timeoutResult)
  • 功能:创建一个 DeferredResult 对象,设置超时时间,并指定自定义超时结果

  • 使用场景:适用于需要设置超时时间和自定义超时结果的场景

参数 类型 说明
timeoutValue Long 超时时间,单位为毫秒
timeoutResult Object 自定义超时结果
(4)带超时时间和回调函数的构造方法
DeferredResult(@Nullable Long timeoutValue, Supplier<?> timeoutResult)
  • 功能:创建一个 DeferredResult 对象,设置超时时间,并通过回调函数指定自定义超时结果

  • 使用场景:适用于需要通过回调函数动态生成自定义超时结果的场景

参数 类型 说明
timeoutValue Long 超时时间,单位为毫秒
timeoutCallback Supplier 超时回调函数,用于生成自定义超时结果
2、核心方法
(1)setResult 方法
boolean setResult(T result)
  • 功能:设置成功结果

  • 使用场景:当异步操作成功完成时,调用该方法设置结果

参数 类型 说明
result T 成功结果
(2)setErrorResult 方法
boolean setErrorResult(Object result)
  • 功能:设置错误结果

  • 使用场景:当异步操作失败时,调用该方法设置错误结果

参数 类型 说明
result T 错误结果
(3)onTimeout 方法
void onTimeout(Runnable callback)
  • 功能:设置超时回调

  • 使用场景:当请求超时时,调用该方法执行自定义逻辑

参数 类型 说明
callback Runnable 超时回调函数,在超时时执行
(4)onCompletion 方法
void onCompletion(Runnable callback)
  • 功能:设置完成回调

  • 使用场景:当请求完成时,调用该方法执行自定义逻辑

参数 类型 说明
callback Runnable 完成回调函数,在请求完成时执行
(5)isSetOrExpired 方法
boolean isSetOrExpired()
  • 功能:检查 DeferredResult 是否已经设置了结果或已经超时

  • 使用场景:用于在异步任务中检查 DeferredResult 的状态,避免重复设置结果或处理已经超时的请求

你可能感兴趣的:(Java,-,简化库与框架编程,spring,boot,java,java-ee,后端,spring,intellij-idea,intellij,idea)