springmvc异步请求的实现原理
一、mvc异步请求的主要3种方式:
(1)Callable
@PostMapping public Callable<String> processUpload(final MultipartFile file) { return new Callable<String>() { public String call() throws Exception { // ... return "someView"; } }; }
(2)DeferredResult
@GetMapping("/quotes")
@ResponseBody
public DeferredResult<String> quotes() {
DeferredResult<String> deferredResult = new DeferredResult<String>();
// Save the deferredResult somewhere..
return deferredResult;
}
// From some other thread...
deferredResult.setResult(data);
(3)HTTP Streaming
@GetMapping("/events")
public ResponseBodyEmitter handle() {
ResponseBodyEmitter emitter = new ResponseBodyEmitter();
// Save the emitter somewhere..
return emitter;
}
// In some other thread
emitter.send("Hello once");
// and again later on
emitter.send("Hello again");
// and done at some point
emitter.complete();
二、springmvc的异步请求的本质,其实就是对servlet3.0的异步servlet的封装
@RequestMapping(value = "/AsyncServlet",method = RequestMethod.GET) public void asyncServlet(HttpServletRequest request) throws IOException { //开启异步请求 AsyncContext asyncContext = request.startAsync(); //设置超时时间 asyncContext.setTimeout(60*1000L); asyncContext.addListener(new AsyncListener() { @Override public void onComplete(AsyncEvent asyncEvent) throws IOException { System.out.println("异步请求完成"); } @Override public void onTimeout(AsyncEvent asyncEvent) throws IOException { } @Override public void onError(AsyncEvent asyncEvent) throws IOException { } @Override public void onStartAsync(AsyncEvent asyncEvent) throws IOException { } }); ServletResponse response = asyncContext.getResponse(); // Save the response somewhere.. }
// From some other thread... //response 响应内容给客户端
三、springmvc的封装(以DeferredResult为例)
通过方法的返回值处理器DeferredResultMethodReturnValueHandler
public void handleReturnValue(@Nullable Object returnValue, MethodParameter returnType, ModelAndViewContainer mavContainer, NativeWebRequest webRequest)
throws Exception { if (returnValue == null) { mavContainer.setRequestHandled(true); } else { DeferredResult result; if (returnValue instanceof DeferredResult) { result = (DeferredResult)returnValue; } else if (returnValue instanceof ListenableFuture) { result = this.adaptListenableFuture((ListenableFuture)returnValue); } else { if (!(returnValue instanceof CompletionStage)) { throw new IllegalStateException("Unexpected return value type: " + returnValue); } result = this.adaptCompletionStage((CompletionStage)returnValue); } //主要代码,调用AsyncManager开启DeferredResult流程
WebAsyncUtils.getAsyncManager(webRequest).startDeferredResultProcessing(result, new Object[]{mavContainer}); } }
然后调用WebAsyncManager#startDeferredResultProcessing方法实现:
public void startDeferredResultProcessing(DeferredResult<?> deferredResult, Object... processingContext) throws Exception { Assert.notNull(deferredResult, "DeferredResult must not be null"); Assert.state(this.asyncWebRequest != null, "AsyncWebRequest must not be null"); Long timeout = deferredResult.getTimeoutValue(); if (timeout != null) { this.asyncWebRequest.setTimeout(timeout); } List<DeferredResultProcessingInterceptor> interceptors = new ArrayList(); interceptors.add(deferredResult.getInterceptor()); interceptors.addAll(this.deferredResultInterceptors.values()); interceptors.add(timeoutDeferredResultInterceptor); DeferredResultInterceptorChain interceptorChain = new DeferredResultInterceptorChain(interceptors); this.asyncWebRequest.addTimeoutHandler(() -> { try { interceptorChain.triggerAfterTimeout(this.asyncWebRequest, deferredResult); } catch (Throwable var4) { this.setConcurrentResultAndDispatch(var4); } }); this.asyncWebRequest.addErrorHandler((ex) -> { try { if (!interceptorChain.triggerAfterError(this.asyncWebRequest, deferredResult, ex)) { return; } deferredResult.setErrorResult(ex); } catch (Throwable var5) { this.setConcurrentResultAndDispatch(var5); } }); this.asyncWebRequest.addCompletionHandler(() -> { interceptorChain.triggerAfterCompletion(this.asyncWebRequest, deferredResult); }); interceptorChain.applyBeforeConcurrentHandling(this.asyncWebRequest, deferredResult);
//开启异步请求就是,request.startAsync(); this.startAsyncProcessing(processingContext); try { interceptorChain.applyPreProcess(this.asyncWebRequest, deferredResult); deferredResult.setResultHandler((result) -> { result = interceptorChain.applyPostProcess(this.asyncWebRequest, deferredResult, result); this.setConcurrentResultAndDispatch(result); }); } catch (Throwable var7) { this.setConcurrentResultAndDispatch(var7); } }
其中很重要的就是this.asyncWebRequest,查看发现是StandardServletAsyncWebRequest,而StandardServletAsyncWebRequest是实现了AsyncListener的,就是servlet中asyncContext#addListener
方法的参数中的监听器,其中开启异步的代码如下:
public void startAsync() { Assert.state(this.getRequest().isAsyncSupported(), "Async support must be enabled on a servlet and for all filters involved in async request processing. This is done in Java code using the Servlet API or by adding \"<async-supported>true</async-supported>\" to servlet and filter declarations in web.xml."); Assert.state(!this.isAsyncComplete(), "Async processing has already completed"); if (!this.isAsyncStarted()) { this.asyncContext = this.getRequest().startAsync(this.getRequest(), this.getResponse()); this.asyncContext.addListener(this); if (this.timeout != null) { this.asyncContext.setTimeout(this.timeout); } } }
发现其实就是servlet中异步的方法。

浙公网安备 33010602011771号