在 Spring 的控制器方法中运行后台任务

问题描述 投票:0回答:2

事实上,我想不出更好的方式来表达这个问题。

我有一个 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 的方法将在将来的某个时间执行此功能。

但是我想知道是否可以在没有消息代理的情况下解决这个问题?

java multithreading spring-boot apache-kafka background-process
2个回答
1
投票

我认为实现这个并留在 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
实际异步运行这些方法。但是如果你愿意,你可以定义你自己的执行者。

更多细节可以在这篇文章中找到


0
投票

这取决于社交媒体任务的重要性,因此您可以做出正确的决定。基本上,使用 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);
});
© www.soinside.com 2019 - 2024. All rights reserved.