如何使用Springboot对控制器执行异步REST请求?

我正在尝试使用SprintBoot实现异步控制器。我想向控制器发出REST请求,以便控制器在工作继续在服务器上的同时立即返回。

我正在关注这个Spring示例:http :

//spring.io/blog/2012/05/07/spring-mvc-3-2-preview-introducing-

servlet-3-async-support

我怀疑这是配置问题。有人可以告诉我我所缺少的吗?我是Spring的新手,所以请您提供尽可能多的详细信息,我们将不胜感激。

使用工作的控制器,我进行了以下更改:

// Before

@RequestMapping(method=RequestMethod.POST)

public String processUpload(final MultipartFile file) {

// ...

return "someView";

}

// After

@RequestMapping(method=RequestMethod.POST)

public Callable<String> processUpload(final MultipartFile file) {

return new Callable<String>() {

public Object call() throws Exception {

// ...

return "someView";

}

};

}

我可以给新的控制器打电话,但是下面有两个问题:

  1. 新的控制器不是异步调用的。通话期间浏览器挂起。调用确实会执行代码。
  2. 请求因以下错误而超时:

2015-03-06 16:36:10.592错误13012 — [MvcAsync1]

oswcrequest.async.WebAsyncManager:由于超时或网络错误,无法完成异步处理

通过在应用程序文件中创建以下bean,我能够解决超时问题:

@Bean

public EmbeddedServletContainerFactory servletContainer() {

TomcatEmbeddedServletContainerFactory factory = new TomcatEmbeddedServletContainerFactory();

factory.addConnectorCustomizers(new TomcatConnectorCustomizer() {

@Override

public void customize(Connector connector) {

connector.setPort(9000);

connector.setAsyncTimeout(60000);

}

});

return factory;

}

但是对控制器的调用仍然不是异步的。在通话过程中,浏览器仍然挂起。

我仍在寻求有关如何在后台进行工作时如何立即返回对控制器的REST调用的帮助。

谢谢戴夫。我试图在bean中实现一个异步方法。

这是我的应用程序类:

@SpringBootApplication

@EnableAsync

public class Application {

public static void main(String[] args) {

SpringApplication.run(Application.class, args);

}

@Bean

public EmbeddedServletContainerFactory servletContainer() {

TomcatEmbeddedServletContainerFactory factory = new TomcatEmbeddedServletContainerFactory();

factory.addConnectorCustomizers(new TomcatConnectorCustomizer() {

@Override

public void customize(Connector connector) {

connector.setPort(9000);

connector.setAsyncTimeout(60000);

}

});

return factory;

}

}

这是我的bean类:

public class LongProcess {

@Async

public Future<String> call() {

try {

System.out.println("Sleeping now...");

Thread.sleep(10000);

return new AsyncResult<String>("Hey");

} catch (InterruptedException e) {

// TODO Auto-generated catch block

e.printStackTrace();

return null;

}

}

}

我的配置类:

@Configuration

@EnableAsync

public class LongProcessConfiguration implements AsyncConfigurer {

@Bean

public LongProcess longProcessBean() {

return new LongProcess();

}

@Override

public Executor getAsyncExecutor() {

ThreadPoolTaskExecutor taskExecutor = new ThreadPoolTaskExecutor();

taskExecutor.setMaxPoolSize(10);

taskExecutor.setThreadNamePrefix("LULExecutor-");

taskExecutor.initialize();

return taskExecutor;

}

@Override

public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {

return new SimpleAsyncUncaughtExceptionHandler();

}

}

我的控制器方法:

@RequestMapping("/utilities/longProcess")

public String longProcess() {

System.out.println("Starting long process...");

CsvFileDifferConfiguration context = new CsvFileDifferConfiguration();

LongProcess process = context.longProcessBean();

Future<String> result = process.call();

System.out.println("Done!");

return "{success: 1}";

}

不幸的是,这仍然不会立即返回。请注意,我不在乎LongProcess的结果。该方法已成功调用,但未在后台调用。知道我可能会缺少什么吗?

作为测试,如果更改控制器方法以等待结果,则永远不会输入wait块:

@RequestMapping("/utilities/longProcess")

public String longProcess() throws InterruptedException {

System.out.println("Starting long process...");

CsvFileDifferConfiguration context = new CsvFileDifferConfiguration();

LongProcess process = context.longProcessBean();

Future<String> result = process.call();

while (!(result.isDone())) {

Thread.sleep(1); //10-millisecond pause between each check

System.out.println("Waiting for Long Process...");

}

System.out.println("Done!");

return "{success: 1}";

}

我更换了

CsvFileDifferConfiguration context = new CsvFileDifferConfiguration();

LongProcess process = context.longProcessBean();

@Autowired

private LongProcess process;

这样就解决了问题。

回答:

我认为您误解了MVC异步(和Servlet

3)功能。如果您的控制器方法需要很长时间才能完成,它将在与用于处理传入请求的线程不同的线程中调用,但是它仍必须在同一HTTP连接上将数据返回给客户端,因此它可能会超时这种观点。要立即返回但在后台执行处理,则不需要异步MVC,您只需要在后台线程中进行昂贵的处理(例如,通过@Async在另一个方法中调用方法@Bean)。

以上是 如何使用Springboot对控制器执行异步REST请求? 的全部内容, 来源链接: utcz.com/qa/422208.html

回到顶部