Java 如何使用Spring实现异步REST?
我想用弹簧靴休息一下。 我很久以前从未使用过Spring和Java(Java7) 在过去的两年中,我只使用了Python和C(但正如我所说,我已经使用了Java) 所以,现在,我尝试使用异步方法进行休息,并检查了几个示例,但我仍然不太清楚如何“正确地”进行休息 查看以下文档:,Java 8有Java 如何使用Spring实现异步REST?,java,spring,rest,asynchronous,Java,Spring,Rest,Asynchronous,我想用弹簧靴休息一下。 我很久以前从未使用过Spring和Java(Java7) 在过去的两年中,我只使用了Python和C(但正如我所说,我已经使用了Java) 所以,现在,我尝试使用异步方法进行休息,并检查了几个示例,但我仍然不太清楚如何“正确地”进行休息 查看以下文档:,Java 8有CompletableFuture,我可以与Spring一起使用,因此,我编写了以下代码: 服务: @Service public class UserService { private UserRepo
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
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;
})
}
}
@服务
公共类用户服务{
私有用户存储库用户存储库;
//依赖注入
//这里不需要自动连线
// https://docs.spring.io/spring-boot/docs/current/reference/html/using-boot-spring-beans-and-dependency-injection.html
公共用户服务(用户存储库用户存储库){
this.userRepository=userRepository;
}
@异步的
公共CompletableFuture findByEmail(字符串电子邮件)引发InterrupedException{
User=userRepository.findByEmail(电子邮件);
返回CompletableFuture.completedFuture(用户);
}
}
存储库:
@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
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;
})
}
}
public interface UserRepository扩展了MongoRepository{
@异步的
findByEmail(字符串电子邮件);
}
RestController:
@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
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;
})
}
}
@RestController
公共类测试控制器{
私人用户服务;
公共测试控制器(用户服务用户服务){
this.userService=userService;
}
@请求映射(value=“test”)
public@ResponseBody CompletableFuture测试(@RequestParam(value=“email”,required=true)字符串电子邮件)引发InterruptedException{
返回userService.findByEmail(电子邮件)。然后返回applyasync(用户->{
返回用户;
})
}
}
这段代码给出了预期的输出。
然后,查看另一个文档(抱歉,我丢失了链接),我看到Spring接受以下代码(这也给了我预期的输出):
@RequestMapping(value=“test”)
public@ResponseBody CompletableFuture测试(@RequestParam(value=“email”,required=true)字符串电子邮件)引发InterruptedException{
返回userService.findByEmail(电子邮件);
}
}
这两种方法有区别吗
然后,看看下面的指南:,在SpringBootApplication
类中有一个@EnableAsync
注释。
如果我包括@EnableAsync
注释,并像上一个链接中的代码一样创建一个asynceducer
Bean,那么我的应用程序不会在/test
端点上返回任何内容(只有一个200 OK响应,但主体为空)
那么,我的rest是异步的,没有@enablesync
注释?
为什么当我使用
@EnableAsync
时,响应正文是空的?响应正文是空的,因为@Async
注释用于UserRepository类的findEmail方法,这意味着没有返回到以下句子的数据User User=UserRepository.findByEmail(email)因为findByEmail方法正在其他不同的线程上运行,并且将返回null而不是列表对象
当您声明@enablesync
时,@Async
注释被启用,这就是为什么只有当您使用@enablesync
时才会发生注释的原因,因为它会激活findEmail的@Async方法在其他线程上运行它
方法returnuserservice.findByEmail(email)
将返回一个从UserService
类创建的CompletableFuture
对象
与第二个方法调用不同的是,theapplyasync
方法将从来自userService.findByEmail(email)
的前一个方法创建一个全新的CompletableFuture
,并且只返回来自第一个CompletableFuture
的用户对象
return userService.findByEmail(email).thenApplyAsync(user -> {
return user;
})
如果希望获得预期的结果,只需从findByEmail方法中删除@Async
注释,最后添加@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);
}
@Async
公共CompletableFuture veryLongMethod(){
试一试{
睡眠(2000L);
}捕捉(中断异常e){
e、 printStackTrace();
}
返回CompletableFuture.completedFuture(true);
}
从控制器中调用三次,如下所示
@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);
}
@RequestMapping(value=“test”)
public@ResponseBody CompletableFuture测试(@RequestParam(value=“email”,required=true)字符串电子邮件)引发InterruptedException{
CompletableFuture boolean1=siteService.veryLongMethod();
CompletableFuture boolean2=siteService.veryLongMethod();
CompletableFuture boolean3=siteService.veryLongMethod();
CompletableFuture.allOf(boolean1,boolean2,boolean3).join();
返回userService.findByEmail(电子邮件);
}
最后测量响应所需的时间,如果超过6秒,则表示您没有运行异步方法,如果仅需2秒,则表示您成功
另请参见以下文档:
希望能有所帮助。触发异步方法时,我面临性能问题。异步子线程开始执行得很晚(大约延迟20到30秒)。我正在主SpringBoot应用程序类中使用ThreadPoolTaskExecutor()。如果你认为性能是一个因素,你也可以尝试同样的方法。你可以在Control.Test.()和Service。FixByEnter()中记录线程名。我怀疑