spring - 在没有冻结浏览器作为客户端的情况下,在 Spring 中使用 deferredResult 在后台运行任务
问题描述
我已经实现了一个简单Rest service
的,我想从中deferredResult
测试Spring
。虽然我按该顺序收到文本:
- 测试
- 测试 1
- 延迟结果后的测试
我很感兴趣为什么在浏览器(客户端)中我需要等待 8 秒。那不deferedResult
应该是非阻塞的并在后台运行任务吗?如果不是,如何创建一个非阻塞的休息服务并在后台运行任务而不使用Java 9
和反应流?
@RestController("/")
public class Controller {
@GetMapping
public DeferredResult<Person> test() {
System.out.println("TEST");
DeferredResult<Person> result = new DeferredResult<>();
CompletableFuture.supplyAsync(this::test1)
.whenCompleteAsync((res, throwable) -> {
System.out.println("TEST AFTER DEFERRED RESULT");
result.setResult(res);
});
System.out.println("TEST 1");
return result;
}
private Person test1() {
try {
Thread.sleep(8000);
} catch (InterruptedException e) {
e.printStackTrace();
}
return new Person("michal", 20);
}
}
class Person implements Serializable {
private String name;
private int age;
}
解决方案
DeferredResult
是 a 的持有者,WebRequest
允许服务线程释放并服务另一个传入的 HTTP 请求,而不是等待当前的结果。之后setResult
orsetError
方法将被调用 - Spring 将释放存储WebRequest
的内容,您的客户端将收到响应。
DeferredResult
holder 是用于非阻塞 IO 线程的 Spring Framework 抽象。延迟结果抽象与后台任务无关。在没有线程抽象的情况下调用它会导致预期的相同线程执行。您的test1
方法正在后台运行,因为CompletableFuture.supplyAsync
方法调用将执行提供给公共池。
结果在 8 秒内返回,因为whenCompleteAsync
传递的回调只有在test1
方法返回后才会被调用。
尽管您在后台执行“服务调用逻辑”需要 8 秒,但您无法立即收到结果。如果您想释放 HTTP 请求 - 只需返回一个可用的适当对象(它可能包含一个 UUID,例如,以便稍后获取创建的人员)或从控制器方法中返回任何内容。您可以在N秒后尝试GET
创建的用户。有特定的 HTTP 响应代码(202 ACCEPTED),这意味着服务器端正在处理请求。最后只需获取您创建的对象。
第二种方法(如果您应该通知您的客户端 - 但如果这是唯一的原因,我不会建议您这样做) - 您可以使用 WebSockets 通知客户端并使用它发送消息。
推荐阅读
- reactjs - 使用 react-router-dom (
) - python - IndexError:TensorFlow Python中的列表索引超出范围
- python - 如何通过带有文件路径的 Telegram Bot 发送照片?
- java - 应用程序在设置 Android Studio 中的 PreferenceSwitch 后冻结
- xml-parsing - 无法在生成的 xml 中生成正确的命名空间
- elasticsearch - 弹性搜索分数计算
- javascript - 如何避免在html中播放两个视频
- reactjs - 将不同类型的道具传递给组件并能够映射它们
- android - 如何从开始硬编码 TextView 对齐距离?
- python - Python Ctypes,C++ 字符串到浮点数的转换在 python 中调用 Matplotlib 后给出错误/舍入的结果