在控制器春季启动@Async方法执行同步 [英] Spring Boot @Async method in controller is executing synchronously

查看:564
本文介绍了在控制器春季启动@Async方法执行同步的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的[基本]春季启动应用程序接受来自浏览器,通过 jQuery.get()发送一个请求,应该立即得到回复 - 如您的请求已被排队的。要做到这一点,我写了一个控制器:

My [basic] Spring Boot application accepts a request from the browser, sent via jQuery.get() and is supposed to immediately receive a response - such as "your request has been queued". To accomplish this, I wrote a controller:

@Controller
public class DoSomeWorkController {

  @Autowired
  private final DoWorkService workService;

  @RequestMapping("/doSomeWork")
  @ResponseBody
  public String doSomeWork() {

    workService.doWork(); // time consuming operation
    return "Your request has been queued.";
  }
}

DoWorkServiceImpl 类实现了 DoWorkService 界面,非常简单。它有一个单一的方法来执行耗时的任务。我并不需要从该服务调用返回任何东西,作为电子邮件将被传递的工作结束,无论对于失败或成功的场景。因此,这将有效地样子:

The DoWorkServiceImpl class implements a DoWorkService interface and is really simple. It has a single method to perform a time consuming task. I don't need anything returned from this service call, as an email will be delivered at the end of the work, both for failure or success scenarios. So it would effectively look like:

@Service
public class DoWorkServiceImpl implements DoWorkService {

  @Async("workExecutor")
  @Override
  public void doWork() {

    try {
        Thread.sleep(10 * 1000);
        System.out.println("completed work, sent email");
    }
    catch (InterruptedException ie) {
        System.err.println(ie.getMessage());
    }
  }
}

我想这会工作,但浏览器的Ajax请求返回响应之前等待10秒。因此,控制器映射的方法调用注解为的内部方法@Async 同步,这似乎。在传统的Spring应用程序,我通常把它添加到XML配置:

I thought this would work, but the browser's Ajax request waited for 10 seconds before returning the response. So the controller mapped method is calling the internal method annotated with @Async synchronously, it would seem. In a traditional Spring application, I typically add this to the XML configuration:

<task:annotation-driven />
<task:executor id="workExecutor" pool-size="1" queue-capacity="0" rejection-policy="DISCARD" />

于是我想到写这相当于在主应用程序类,将有助于:

So I thought writing the equivalent of this in the main application class would help:

@SpringBootApplication
@EnableAsync
public class Application {

  @Value("${pool.size:1}")
  private int poolSize;;

  @Value("${queue.capacity:0}")
  private int queueCapacity;

  @Bean(name="workExecutor")
  public TaskExecutor taskExecutor() {
      ThreadPoolTaskExecutor taskExecutor = new ThreadPoolTaskExecutor();
      taskExecutor.setMaxPoolSize(poolSize);
      taskExecutor.setQueueCapacity(queueCapacity);
      taskExecutor.afterPropertiesSet();
      return taskExecutor;
  }

  public static void main(String[] args) {
      SpringApplication.run(Application.class, args);
  }
}

这并没有改变行为。 Ajax响应10秒发送请求后仍然会到达。我在想什么?

This did not change the behavior. The Ajax response still arrives after 10 seconds of sending the request. What am I missing?

春季启动应用程序可以这里下载。如果安装的Maven,该项目可以通过简单的命令来运行:

The Spring Boot application can be downloaded here. With Maven installed, the project can be run with the simple command:

mvn clean spring-boot:run

注意的问题解决要归功于@戴夫Syer下面,谁指出,我错过 @EnableAsync 提供的答案我应用程序,即使我有在code段的线之上。

Note The issue was resolved thanks to the answer provided by @Dave Syer below, who pointed out that I was missing @EnableAsync in my application, even though I had the line in the code snippet above.

推荐答案

正在调用来自同一类的另一种方法的 @Async 方法。除非您启用AspectJ的代理模式为 @EnableAsync (并提供课程织布),将无法正常工作(谷歌代理自我调用)。最简单的解决方法是放在另一个 @Async 方法 @Bean

You are calling the @Async method from another method in the same class. Unless you enable AspectJ proxy mode for the @EnableAsync (and provide a weaver of course) that won't work (google "proxy self-invocation"). The easiest fix is to put the @Async method in another @Bean.

这篇关于在控制器春季启动@Async方法执行同步的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆