Rob*_*eia 16 java rest spring asynchronous
我正在尝试使用Spring Boot制作一个小型REST.从未使用过Spring并且很久以前使用过Java(Java 7)!
在过去的两年里,我只使用了Pyhton和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);
}
}
Run Code Online (Sandbox Code Playgroud)
存储库:
public interface UserRepository extends MongoRepository<User, String> {
@Async
findByEmail(String email);
}
Run Code Online (Sandbox Code Playgroud)
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;
})
}
}
Run Code Online (Sandbox Code Playgroud)
这段代码给了我预期的输出.然后,查看另一个文档(抱歉,我丢失了链接),我看到Spring接受以下代码(它也给我预期的输出):
@RequestMapping(value = "test")
public @ResponseBody CompletableFuture<User> test(@RequestParam(value = "email", required = true) String email) throws InterruptedException {
return userService.findByEmail(email);
}
}
Run Code Online (Sandbox Code Playgroud)
这两种方法有区别吗?
然后,查看以下指南:https://spring.io/guides/gs/async-method/,类中有一个@EnableAsync注释SpringBootApplication.如果我包含@EnableAsync注释并asyncExecutor像上一个链接中的代码一样创建一个Bean,我的应用程序不会在/test端点上返回任何内容(只有200 OK响应,但是空白主体).
那么,我的休息是没有@EnableAsync注释的异步?为什么当我使用时@EnableAsync,响应体是空白的?
谢谢!
Dan*_* C. 12
响应主体是空白的,因为@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;
})
Run Code Online (Sandbox Code Playgroud)
如果要获得预期结果,只需@Async从findByEmail方法中删除注释,最后添加@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);
}
Run Code Online (Sandbox Code Playgroud)
并从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);
}
Run Code Online (Sandbox Code Playgroud)
最后测量您的响应时间,如果超过6秒,那么您没有运行异步方法,如果只需2秒,那么您就成功了.
另请参阅以下文档:@Async Annotation,Spring异步方法,CompletableFuture类
希望它有所帮助.
| 归档时间: |
|
| 查看次数: |
28321 次 |
| 最近记录: |