事实上,我想不出更好的方式来表达这个问题。
我有一个 spring-boot 应用程序。它有一个特定的终点,比方说
/test
。
我提出休息请求。问题是,我可以通过 rest 调用一些函数,然后返回一些响应(比如 204 no content),并在 background thread 中执行函数本身吗?
考虑案例。
假设我有一个将用户添加到数据库的方法。在方法本身中,设置并保存了实体的必要字段。但与此同时,我想在后台运行一些进程(功能)来检查该用户是否在社交网络中(只是一个测试示例)。没有消息代理可以做到这一点吗?
public User addUser(UserRequest request){
/* (1)
functionality
*/
(2)
userRepository.save(user);
//And now, i want to start background process with socialmedia check.
//I also want to return the user's state at the moment
(3)
//background process
socialMediaService.check(request, user);
(4)
//In fact, I would agree not to return anything.
//It would be enough for me to return control to my controller and then to dispatcherServlet
return user;
}
顺便说一下,在步骤 (3) 中,我可以向消息代理(例如 Kafka)发送一条消息。然后另一种调度读取 kafka 的方法将在将来的某个时间执行此功能。
但是我想知道是否可以在没有消息代理的情况下解决这个问题?
我认为实现这个并留在 Spring 基础设施中的最简单方法是使用
@Async
- Spring 中的异步执行支持
简单来说,用
@Async
注解一个bean的方法,就会让它在一个单独的线程中执行。换句话说,调用者不会等待被调用方法的完成。
首先需要打上
@EnableAsync
注解进行配置,开启Spring的异步方法执行能力。它应该放在你的配置类中:
@Configuration
@EnableAsync
public class ApplicationConfig {
}
然后在您的服务中注释您想要异步处理的方法,如下所示:
// this is just an example. In your case your method check(request, user) should be annotated with @Async
@Async
public void asyncMethod() {
...
}
这应该足以异步运行此方法。
注1:你应该知道
@Async
有一些局限性:
public
方法。注 2: 默认情况下,Spring 使用
SimpleAsyncTaskExecutor
实际异步运行这些方法。但是如果你愿意,你可以定义你自己的执行者。
这取决于社交媒体任务的重要性,因此您可以做出正确的决定。基本上,使用 Kafka 或任何其他消息代理,您可以通过排队消息和一条一条地处理来更好地控制它。
如果您的任务非常简单,您只想在后台运行它,那么它完全可以通过 Java 的
CompletableFuture
类来完成,它代表了一个潜在的异步操作,可以在未来完成并返回结果或异常。
CompletableFuture的概念就像JS的promise:
CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> {
// perform some time-consuming operation in background
// it doesn't intercept the main thread
return 42;
});
future.thenApply(result -> {
// do something with the result
return result * 2;
}).thenAccept(result -> {
// do something with the final result
System.out.println("Final result: " + result);
});