Java &引用;无法在没有AsyncContext的情况下进行调度;提供文件时
我需要在“文件下载控制器”之上编写一个“一次性文件下载”MVC控制器。文件传输到客户端后,必须将其从服务器上删除 最初,编写代码是为了提供文件服务 导入org.springframework.core.io.ResourceJava &引用;无法在没有AsyncContext的情况下进行调度;提供文件时,java,spring-mvc,asynchronous,servlet-3.0,Java,Spring Mvc,Asynchronous,Servlet 3.0,我需要在“文件下载控制器”之上编写一个“一次性文件下载”MVC控制器。文件传输到客户端后,必须将其从服务器上删除 最初,编写代码是为了提供文件服务 导入org.springframework.core.io.Resource @GetMapping("/get/{someParam}") public ResponseEntity<Resource> downloadFile(Long someParam) { Long fileId = identify(somePara
@GetMapping("/get/{someParam}")
public ResponseEntity<Resource> downloadFile(Long someParam)
{
Long fileId = identify(someParam);
return super.downloadFile(fileId); //This uses a "File repository" service binding file IDs to physical paths
}
protected ResponseEntity<Resource> downloadFile(Long fileId){
File theFile = resolve(fileId);
return new FileSystemResource(theFile);
}
我已经在我的web.xml
中配置了所有servlet和过滤器以支持异步操作。我做了一些研究,但没有任何帮助,因为我正在使用一个更新的Tomcat版本
我的代码有什么问题?我发布它并不是为了让它简单,但是调试时我发现写操作成功,负载正确。我也遇到了同样的问题。在我的例子中,解决方案是配置一个
AsyncTaskExecutor
:
@Configuration
public class WebConfig extends WebMvcConfigurerAdapter {
@Override
public void configureAsyncSupport(AsyncSupportConfigurer configurer) {
configurer.setDefaultTimeout(-1);
configurer.setTaskExecutor(asyncTaskExecutor());
}
@Bean
public AsyncTaskExecutor asyncTaskExecutor() {
// an implementaiton of AsyncTaskExecutor
return new SimpleAsyncTaskExecutor("async");
}
}
根据@MDenium的评论 不要使用仅供内部使用的WebAsyncTask。只需使用一个可完成的未来或返回一个可调用的。如果你把try/finally放在你的Callable中,它就会起作用 WebAsyncTask不是API,所以当您从MVC方法返回时,Spring不知道如何处理它。这不是执行异步执行的正确方法。它仅在内部用于执行任务和上下文 Spring MVC支持:
- 延期结果
- 可调用
- 完全未来
可能有少数人不使用内部使用的
WebAsyncTask
。只需使用一个CompletableFuture
或返回一个Callable
。如果你把try/finally
放在Callable
里面,它会工作的。你能扩展一下吗?我认为WebAsyncTask是可调用的ad(可选)执行器的包装器,退回到默认的执行器,WebAsyncTask
在内部使用它来包装可调用和特定于调用的方法,并构建异步上下文。你不能用你的方法做那件事,因此它不起作用。但是如上所述,只要将所有内容都放在可调用的中,然后从方法中简单地返回即可。解决这个问题的运气好吗?我也刚开始讨论这个问题。在发送完整响应之前,客户端关闭连接的次数占50%。我使用@M.Deinum的注释修复了此问题。简单地说,WebAsyncTask
不是API
10-Sep-2018 12:20:37.551 AVVERTENZA [ajp-nio-8009-exec-3] org.apache.catalina.core.AsyncContextImpl.setErrorState onError() failed for listener of type [org.apache.catalina.core.AsyncListenerWrapper]
java.lang.IllegalArgumentException: Cannot dispatch without an AsyncContext
at org.springframework.util.Assert.notNull(Assert.java:134)
at org.springframework.web.context.request.async.StandardServletAsyncWebRequest.dispatch(StandardServletAsyncWebRequest.java:128)
at org.springframework.web.context.request.async.WebAsyncManager.setConcurrentResultAndDispatch(WebAsyncManager.java:369)
at org.springframework.web.context.request.async.WebAsyncManager.access$200(WebAsyncManager.java:60)
at org.springframework.web.context.request.async.WebAsyncManager$3.handle(WebAsyncManager.java:311)
at org.springframework.web.context.request.async.StandardServletAsyncWebRequest.onError(StandardServletAsyncWebRequest.java:144)
at org.apache.catalina.core.AsyncListenerWrapper.fireOnError(AsyncListenerWrapper.java:49)
at org.apache.catalina.core.AsyncContextImpl.setErrorState(AsyncContextImpl.java:421)
at org.apache.catalina.connector.CoyoteAdapter.asyncDispatch(CoyoteAdapter.java:370)
at org.apache.coyote.ajp.AbstractAjpProcessor.asyncDispatch(AbstractAjpProcessor.java:745)
at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:666)
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1539)
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.run(NioEndpoint.java:1495)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
at java.lang.Thread.run(Thread.java:745)
@Configuration
public class WebConfig extends WebMvcConfigurerAdapter {
@Override
public void configureAsyncSupport(AsyncSupportConfigurer configurer) {
configurer.setDefaultTimeout(-1);
configurer.setTaskExecutor(asyncTaskExecutor());
}
@Bean
public AsyncTaskExecutor asyncTaskExecutor() {
// an implementaiton of AsyncTaskExecutor
return new SimpleAsyncTaskExecutor("async");
}
}