gpt4 book ai didi

java - 如何使用 Spring 制作异步 REST?

转载 作者:IT老高 更新时间:2023-10-28 13:55:08 26 4
gpt4 key购买 nike

我正在尝试使用 Spring Boot 制作一个小型 REST。没用过Spring,很久以前用过Java(Java 7)!

在过去的 2 年里,我只使用过 Python 和 C#(但就像我说的,我已经使用过 Java)。

所以,现在,我正在尝试使用异步方法制作 REST,并检查了几个示例,但我仍然不太了解执行此操作的“正确方法”。

查看以下文档:http://carlmartensen.com/completablefuture-deferredresult-async ,Java 8 有 CompletableFuture 可以与 Spring 一起使用,所以,我编写了以下代码:

服务:

@Service
public class UserService {
private UserRepository userRepository;

// dependency injection
// don't need Autowire here
// https://docs.spring.io/spring-boot/docs/current/reference/html/using-boot-spring-beans-and-dependency-injection.html
public UserService(UserRepository userRepository) {
this.userRepository = userRepository;
}

@Async
public CompletableFuture<User> findByEmail(String email) throws InterrupedException {
User user = userRepository.findByEmail(email);
return CompletableFuture.completedFuture(user);
}
}

存储库:

public interface UserRepository extends MongoRepository<User, String> {
@Async
findByEmail(String email);
}

RestController:

@RestController
public class TestController {

private UserService userService;

public TestController(UserService userService) {
this.userService = userService;
}

@RequestMapping(value = "test")
public @ResponseBody CompletableFuture<User> test(@RequestParam(value = "email", required = true) String email) throws InterruptedException {
return userService.findByEmail(email).thenApplyAsync(user -> {
return user;
})
}
}

这段代码给了我预期的输出。然后,查看另一个文档(对不起,我丢失了链接),我看到 Spring 接受以下代码(这也给了我预期的输出):

  @RequestMapping(value = "test")
public @ResponseBody CompletableFuture<User> test(@RequestParam(value = "email", required = true) String email) throws InterruptedException {
return userService.findByEmail(email);
}
}

这两种方法有区别吗?

然后,查看以下指南:https://spring.io/guides/gs/async-method/ ,在 SpringBootApplication 类中有一个 @EnableAsync 注释。如果我包含 @EnableAsync 注释并像上一个链接中的代码一样创建一个 asyncExecutor Bean,我的应用程序不会在 /test 上返回任何内容端点(只有 200 OK 响应,但正文为空白)。

那么,没有 @EnableAsync 注释,我的其余部分是异步的吗?为什么当我使用 @EnableAsync 时,响应正文是空白的?

最佳答案

响应体是空白的,因为在UserRepository类的findEmail方法中使用了@Async注解,这意味着没有数据返回到下面这句User user = userRepository.findByEmail (email); 因为 findByEmail 方法正在其他不同的线程上运行,并且将返回 null 而不是 List 对象。

@Async 注释在您声明 @EnableAsync 时启用,这就是它仅在您使用 @EnableAsync 时发生的原因,因为它激活 findEmail 方法的 @Async 以在其他线程上运行它。

return userService.findByEmail(email); 方法将返回从 UserService 类创建的 CompletableFuture 对象。

与第二个方法调用的不同之处在于 thenApplyAsync 方法将从 userService.findByEmail(email) 的前一个方法创建一个全新的 CompletableFuture 并且只会返回来自第一个 CompletableFuture 的用户对象。

 return userService.findByEmail(email).thenApplyAsync(user -> {
return user;
})

如果你想得到预期的结果,只需从 findByEmail 方法中删除 @Async 注释,最后添加 @EnableAsync 注释

如果你需要弄清楚如何使用异步方法,假设你必须调用三个方法,每个方法需要 2 秒才能完成,在正常情况下你会调用它们 method1,然后是 method2,最后是 method3在这种情况下,您的整个请求将需要 6 秒。当您激活 Async 方法时,您可以调用其中三个,然后等待 2 秒而不是 6 秒。

将此长方法添加到用户服务:

@Async
public CompletableFuture<Boolean> veryLongMethod() {

try {
Thread.sleep(2000L);
} catch (InterruptedException e) {
e.printStackTrace();
}

return CompletableFuture.completedFuture(true);
}

然后从 Controller 调用 3 次,像这样

  @RequestMapping(value = "test")
public @ResponseBody CompletableFuture<User> test(@RequestParam(value = "email", required = true) String email) throws InterruptedException {
CompletableFuture<Boolean> boolean1= siteService.veryLongMethod();
CompletableFuture<Boolean> boolean2= siteService.veryLongMethod();
CompletableFuture<Boolean> boolean3= siteService.veryLongMethod();

CompletableFuture.allOf(boolean1,boolean2,boolean3).join();
return userService.findByEmail(email);
}

最后测量你的响应时间,如果超过 6 秒,那么你没有运行 Async 方法,如果只需要 2 秒,那么你就成功了。

另请参阅以下文档:@Async Annotation , Spring async methods , CompletableFuture class

希望对您有所帮助。

关于java - 如何使用 Spring 制作异步 REST?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45473215/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com