我可以 return 一个 API 响应而不等待 Spring 引导中的其他外部 API 调用吗?
Can I return an API response without waiting on other external API calls in Spring Boot?
这是在 Spring 引导中使用 @Async
的正确方法吗?
@Service
class someServiceImpl {
...
public someResponseDTO getUsers(int userId) {
// Do some logic
...
// Call external API with another service method from another service impl
anotherService.emailUserInTheBackground(userId);
return someResponseDTO;
}
...
}
@Service
public class AnotherService {
@Async
public void emailUserInTheBackground(int userId) {
// This might take a while...
...
}
}
由于 emailUserInTheBackground()
有 @Async
注释和 void
return 类型,它是否完全阻塞行 return someResponseDTO
?
我想要的只是 return 对调用者的响应而不等待,因为 emailUserInTheBackground()
完成时间太长并且没有直接绑定到响应对象。
是的,这是 运行 在后台执行任务的正确方法,您可以通过引入延迟来模仿线程阻塞行为。
@SpringBootApplication
@EnableAsync
public class MyApplication {
public static void main(String[] arg) {
SpringApplication.run(MyApplication.class);
}
}
然后你需要用@Async
注释标记emailUserInTheBackground方法。
@Service
class AnotherService {
@Async
public void emailUserInTheBackground(int userId) {
try {
TimeUnit.SECONDS.sleep(10);
System.out.println("Print from async: "+ Thread.currentThread().getName());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
现在在方法调用后再添加一个记录器,您会看到 getUsers(...)
调用首先在另一个线程中完成,即使 emailService 线程被阻塞了 10 秒。
anotherService.emailUserInTheBackground(userId);
System.out.println("Print from service: "+ Thread.currentThread().getName());
您还可以使用 CompletableFuture 运行 后台任务。
public someResponseDTO getUsers(int userId) {
// Do some logic
...
// Call external API with another service method from another service impl
CompletableFuture.runAsync(() -> anotherService.emailUserInTheBackground(userId))
return someResponseDTO;
}
@Async
的相关行为记录在 Spring documentation:
You can provide the @Async
annotation on a method so that invocation of that method occurs asynchronously. In other words, the caller returns immediately upon invocation, while the actual execution of the method occurs in a task that has been submitted to a Spring TaskExecutor
.
在您描述的情况下,由于 emailUserInTheBackground
方法使用 @Async
注释并且启用了 Spring 的异步方法执行功能,因此 emailUserInTheBackground
方法将立即 return,调用将在单独的线程中处理。 someResponseDTO
值将从 getUsers
方法 return 编辑,而 emailUserInTheBackground
方法继续在后台处理。
这是在 Spring 引导中使用 @Async
的正确方法吗?
@Service
class someServiceImpl {
...
public someResponseDTO getUsers(int userId) {
// Do some logic
...
// Call external API with another service method from another service impl
anotherService.emailUserInTheBackground(userId);
return someResponseDTO;
}
...
}
@Service
public class AnotherService {
@Async
public void emailUserInTheBackground(int userId) {
// This might take a while...
...
}
}
由于 emailUserInTheBackground()
有 @Async
注释和 void
return 类型,它是否完全阻塞行 return someResponseDTO
?
我想要的只是 return 对调用者的响应而不等待,因为 emailUserInTheBackground()
完成时间太长并且没有直接绑定到响应对象。
是的,这是 运行 在后台执行任务的正确方法,您可以通过引入延迟来模仿线程阻塞行为。
@SpringBootApplication
@EnableAsync
public class MyApplication {
public static void main(String[] arg) {
SpringApplication.run(MyApplication.class);
}
}
然后你需要用@Async
注释标记emailUserInTheBackground方法。
@Service
class AnotherService {
@Async
public void emailUserInTheBackground(int userId) {
try {
TimeUnit.SECONDS.sleep(10);
System.out.println("Print from async: "+ Thread.currentThread().getName());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
现在在方法调用后再添加一个记录器,您会看到 getUsers(...)
调用首先在另一个线程中完成,即使 emailService 线程被阻塞了 10 秒。
anotherService.emailUserInTheBackground(userId);
System.out.println("Print from service: "+ Thread.currentThread().getName());
您还可以使用 CompletableFuture 运行 后台任务。
public someResponseDTO getUsers(int userId) {
// Do some logic
...
// Call external API with another service method from another service impl
CompletableFuture.runAsync(() -> anotherService.emailUserInTheBackground(userId))
return someResponseDTO;
}
@Async
的相关行为记录在 Spring documentation:
You can provide the
@Async
annotation on a method so that invocation of that method occurs asynchronously. In other words, the caller returns immediately upon invocation, while the actual execution of the method occurs in a task that has been submitted to a SpringTaskExecutor
.
在您描述的情况下,由于 emailUserInTheBackground
方法使用 @Async
注释并且启用了 Spring 的异步方法执行功能,因此 emailUserInTheBackground
方法将立即 return,调用将在单独的线程中处理。 someResponseDTO
值将从 getUsers
方法 return 编辑,而 emailUserInTheBackground
方法继续在后台处理。