当前位置:首页 > 技术分析 > 正文内容

用CompletableFuture当做SpringBoot的返回值会发生什么情况?

在Spring Boot中,如果将CompletableFuture作为控制器方法的返回值,它会被自动处理为一个异步的请求,也就是说在Spring MVC中会自动检测返回值为CompletableFuture的请求处理,然后在这个CompletableFuture返回成功的时候异步的发送响应请求。

具体情况

也就是说当返回了一个CompletableFuture的时候,Spring Boot应用程序是不会阻塞线程的执行的而是直接进行了返回,然后在CompletableFuture完成之后将结果发送给客户端,这种需要进行异步处理场景有很多例如文件处理、远程服务调用等

当CompletableFuture处理完成的时候,Spring会将结果转换为HTTP响应并返回给客户端,这个时候如果在CompletableFuture包含的是一个异常信息的话,Spring也会将异常转换为适当的HTTP错误响应。

在Spring Boot中内置了很多异步的处理返回支持,所以不需要开发者去做额外的配置处理,只需要将返回类型声明为CompletableFuture<T>即可,Spring会自动对其进行处理。

示例代码

@RestController
public class AsyncController {

    @GetMapping("/async")
    public CompletableFuture<String> asyncMethod() {
        return CompletableFuture.supplyAsync(() -> {
            // 模拟长时间操作
            try {
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return "Hello, World!";
        });
    }
}

在上面的例子中,客户端发送请求到/async路径时,SpringBoot会立即返回一个CompletableFuture,但并不会阻塞。在后台,
CompletableFuture.supplyAsync会异步执行,完成后返回"Hello, World!",并且Spring会将该值返回给客户端。

这里需要注意,
CompletableFuture.supplyAsync默认使用ForkJoinPool.commonPool(),因此我们可以自定义线程池来管理异步任务的执行。由于是异步操作,如果请求执行时间较长,可能需要处理超时逻辑。

前端如何处理上面的这个返回

在前端处理Spring Boot返回的CompletableFuture异步结果时,假设前端是使用JavaScript(例如,通过Fetch API或Axios),可以通过如下的方式来对CompletableFuture进行处理。

使用fetch示例

// 发送异步请求到 /async
fetch('/async')
    .then(response => {
        if (!response.ok) {
            // 处理HTTP错误
            throw new Error('Network response was not ok');
        }
        return response.text(); // 假设返回的是文本内容
    })
    .then(data => {
        console.log('Received:', data); // 处理响应数据
    })
    .catch(error => {
        console.error('There was a problem with the fetch operation:', error);
    });

使用axios示例

// 使用 axios 发送请求到 /async
axios.get('/async')
    .then(response => {
        console.log('Received:', response.data); // 处理响应数据
    })
    .catch(error => {
        console.error('There was an error!', error);
    });

无论使用fetch还是axios,前端都在等待一个Promise的完成。在上面的Spring Boot例子中,当CompletableFuture完成后,Spring会自动将结果发送到前端。前端接收到响应后可以处理数据,例如更新UI或执行其他逻辑。

展示加载状态

由于后端的操作是异步的,前端通常会在等待期间显示一个加载指示器来提升用户体验,如下所示。

const loadData = async () => {
    try {
        // 显示加载状态
        document.getElementById('loader').style.display = 'block';

        // 发送异步请求
        const response = await fetch('/async');
        if (!response.ok) {
            throw new Error('Network response was not ok');
        }

        // 处理响应
        const data = await response.text();
        console.log('Received:', data);

        // 更新UI
        document.getElementById('result').textContent = data;

    } catch (error) {
        console.error('Fetch error:', error);
    } finally {
        // 隐藏加载状态
        document.getElementById('loader').style.display = 'none';
    }
};

// 调用函数
loadData();

总结

在前端处理Spring Boot返回的异步CompletableFuture响应时,我们只需像处理普通的HTTP请求一样,使用fetch或axios发送请求并等待结果。前端会根据后端的返回值更新UI或进行进一步处理。如果操作时间较长,可以显示一个加载动画来提升用户体验。

扫描二维码推送至手机访问。

版权声明:本文由ruisui88发布,如需转载请注明出处。

本文链接:http://www.ruisui88.com/post/3832.html

分享给朋友:

“用CompletableFuture当做SpringBoot的返回值会发生什么情况?” 的相关文章

Vue组件通信之props深入详解!

props 是 Vue 组件中一个很重要的概念。它是用来从父组件向子组件传递数据的。为什么需要props?这是因为在Vue中,组件是相互隔离的。每个组件都有自己的作用域,子组件无法直接访问父组件的状态或值。通过props,父组件可以将数据传递给子组件。使用props的步骤:1. 在子组件中定义pro...

「干货」通俗易懂的Deno 入门教程

作者: semlinker转发链接:https://mp.weixin.qq.com/s/2eqRTsf_z7Bcs6dziXe73Q一、Deno 简介Deno 是一个 JavaScript/TypeScript 的运行时,默认使用安全环境执行代码,有着卓越的开发体验。Deno 含有以下功能亮点:默...

掌握版本控制:Git的那些常见用法与技巧

Git作为现代开发中最常用的版本控制系统,它的普及和高效性使得程序员几乎每天都在与它打交道。无论是个人项目,还是团队协作,Git都能帮助我们追踪代码的修改历史,保证代码版本的管理井井有条,并在多人协作时有效地避免冲突。本文将分享一些常见的Git用法与技巧,帮助你更好地掌握Git的强大功能,并提升你在...

使用cgroup限制进程资源

这里使用containerd项目中的cgroup包来实现进程资源限制。先写一个耗费一个CPU并且一秒增加10m内存的测试进程package mainimport ( "fmt" "math/rand" "time")func main() { go f...

佳能 EOS R8 深度评测

佳能 EOS R8 的定位是入门级全画幅无反光镜可换镜头相机。尽管在产品阵容中处于这一位置,R8 仍然是一个强大的相机,配备了先进的 R6 II 同款成像传感器、快速处理器和令人难以置信的自动对焦系统,体积小、重量轻、价格低。这款相机是发烧友、旅行者、家庭以及任何想要全画幅传感器相机的人的绝佳选择。...

Vue学习笔记之动态路由的参数传递应用及技巧

路由的参数传递:①通过params的类型· 配置路由格式:/router/:id· 传递的方式:在path后面跟上对应的值· 传递后形成的路径:/router/list,/router/profile这个就是前两篇中提到的"动态路由"中有应用过这个方法:②通过query的类型(对象方...