我可以 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 方法继续在后台处理。