spring MVC即使请求超时后,可调用执行是否仍继续?


问题内容

我有一个这样的异步处理程序方法

@RequestMapping("/custom-timeout-handling")
public @ResponseBody WebAsyncTask<String> callableWithCustomTimeoutHandling() {

    Callable<String> callable = new Callable<String>() {

        public String call() throws Exception {
            while(i==0){
            System.out.println("inside while loop->");
            }

            return "Callable result";
        }
    };

    return new WebAsyncTask<String>(10000, callable);
}

这将执行while循环,直到指定的timeout(10sec)。

当请求超时时,它将从TimeoutCallableProcessingInterceptor执行handleTimeout方法

public class TimeoutCallableProcessingInterceptor extends CallableProcessingInterceptorAdapter {

@Override
public <T> Object handleTimeout(NativeWebRequest request, Callable<T> task) throws Exception {
    throw new IllegalStateException("[" + task.getClass().getName() + "] timed out");
}

}

资料来源:我已取代

Thread.sleep(2000)

while(i==0){
System.out.println("inside while loop->");
}

我的问题是,即使从handletimeout方法发送了超时(完成了执行句柄超时方法)响应之后,while循环仍在处理,直到i的值更改为除零以外的其他值。

服务器仍然保留请求吗?请求超时的用途是什么?

提前致谢…


问题答案:

当Servlet容器线程检测到异步可调用对象已超时时,它将调用handleTimeout()(在其自己的上下文中)。这就是您看到handleTimeout()被执行的原因。它由Servlet容器线程而不是由运行Callable的线程执行。

如果要自定义超时处理,则需要做两件事:

  1. 在您的WebAsyncTask中重写onTimeout()。当提供给onTimeout()回调的回调函数提供的任何可调用对象都将在servlet容器线程中被调用时,它将检测到您的可调用对象已超时。
  2. 检查您在控制器内部创建的Callable中的超时/中断。如果您的Callable不期望并尊重中断(“如果目标线程未轮询中断状态,则该中断将被有效忽略”),无法中断它!请参考答案以了解如何期望并尊重中断。