用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或进行进一步处理。如果操作时间较长,可以显示一个加载动画来提升用户体验。