我正在尝试使用Spring Boot创建一个小的REST。我很久以前从未使用过Spring,也没有使用过Java(Java 7)!
在过去的两年中,我只使用了Python和C#(但正如我所说,我已经使用过Java)。
因此,现在,我正在尝试使用异步方法制作REST,并检查了几个示例,但是,我仍然不太了解执行此操作的“正确方法”。
CompletableFuture
我可以将Java 8 与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/,@EnableAsync
在SpringBootApplication
类中有一个注释。如果我包括@EnableAsync
注解并asyncExecutor
像上一个链接中的代码一样创建一个Bean,则我的应用程序在/test
端点上什么也不返回(仅返回200
OK,但正文为空)。
所以,我的其余部分没有@EnableAsync
注释就异步了吗?为什么在使用时@EnableAsync
,响应正文为空白?
响应正文为空,因为在@Async
UserRepository类的findEmail方法中使用了注释,这意味着没有数据返回到下面的句子,User user = userRepository.findByEmail(email);
因为findByEmail方法正在其他线程上运行,并且将返回null而不是List对象。
@Async
当您声明该注释@EnableAsync
仅在使用时才发生时@EnableAsync
,便启用了该注释,因为它激活了findEmail方法的@Async以便在其他线程上运行它。
该方法return userService.findByEmail(email);
将返回CompletableFuture
从UserService
类创建的对象。
与第二个方法调用的不同之处在于,该thenApplyAsync
方法将创建一个CompletableFuture
与前一个方法完全不同的新方法,userService.findByEmail(email)
并且仅返回第一个方法的用户对象CompletableFuture
。
return userService.findByEmail(email).thenApplyAsync(user -> {
return user;
})
如果要获得预期的结果,只需@Async
从findByEmail方法中删除注释,最后添加@EnableAsync
注释
如果您需要澄清如何使用异步方法的想法,可以说您必须调用三个方法,每个方法需要2秒钟才能完成,在正常情况下,您将其称为method1,然后称为method2,最后称为method3。整个请求将花费6秒。激活异步方法后,您可以调用其中三个,而只需等待2秒钟而不是6秒钟。
将此长方法添加到用户服务中:
@Async
public CompletableFuture<Boolean> veryLongMethod() {
try {
Thread.sleep(2000L);
} catch (InterruptedException e) {
e.printStackTrace();
}
return CompletableFuture.completedFuture(true);
}
然后从Controller调用它三遍
@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异步方法,CompletableFuture类
希望对您有所帮助。
我的应用程序是简单的3-层Spring Boot rest Web服务,具有通常的同步endpoint。但是由于从我的服务发送请求的下游系统获得响应的时间相当长(有点像60秒),我需要向我的服务添加对异步REST调用的支持,以保存上游系统免于等待响应。换句话说,如果对下游系统的响应需要超过60秒(超时),那么上游系统会断开与我的服务的连接并继续运行... 但是当响应到来时,我的服务使用来自上游系统
我需要在函数中运行各种步骤,但步骤必须按特定顺序运行。我尝试实现一个函数,如下所示: 控制台中的预期结果应该是1,2,3,但我得到了3,2,1。似乎忽略了参数。 编辑功能在上面的示例中仅用于模拟繁重的任务。在我的项目中,我不会使用它。事实上,我需要连接到一个数据库,然后在进入下一步之前重新格式化结果。即使包括,2也会在1之前登录。换句话说,空列表被传递到我的图形,因为没有考虑。以下是我当前的代码:
我正在为一家德国公司评估Dart,将各种Java程序移植到Dart,并对结果进行比较和分析。在浏览器中,飞镖轻松获胜。对于服务器来说,软件性能似乎是一个严重的问题(请看我的这个问题),但这基本上得到了缓解。 现在我正在移植一些“简单”的命令行工具,我没想到会有任何严重的问题,但至少有一个问题。一些工具确实会发出HTTP请求来收集一些数据,独立的Dart虚拟机只以异步方式支持它们。纵观所有我能找到的
我遵循了spring批处理文档,无法异步运行我的作业。 因此,我从一个web容器运行该作业,该作业将通过RESTendpoint触发。 我想让JobInstance ID在完成整个作业之前传递它作为响应。因此,他们可以稍后使用JobInstance ID检查作业的状态,而不是等待。但我没能让它工作。下面是我尝试过的示例代码。请让我知道我错过了什么或错了什么。 BatchConfig创建异步JobL
在Facebook关于Flux架构的演讲中,Jing在12:17提到dispatcher强制要求,在当前操作被商店完全处理之前,不能调度任何操作。 这里的调度员是执行没有级联效应的主要部分;一旦一个操作进入商店,在商店完全处理完它之前,您不能再放入另一个操作。 那么,我的问题是,如何正确地处理可能从存储区中删除的长时间运行的异步操作(例如,Ajax请求,或处理其他外部异步API)--任何阻止完成操
问题内容: 如何从异步函数返回值?我试图喜欢这个 它给了我, 问题答案: 您不能超出范围。为了获得预期的结果,您应该将其包装到异步IIFE中,即 样品。 有关更多信息 由于返回一个Promise,因此可以将其省略,如下所示: 然后像以前一样做