当前位置 主页 > 服务器问题 > Linux/apache问题 >
isAsync()
判断,就会进入 dispatch(status)
,最终会调用 CoyoteAdapter
的 asyncDispatch
方法
public boolean asyncDispatch(org.apache.coyote.Request req, org.apache.coyote.Response res, SocketEvent status) throws Exception { //省略部分代码 Request request = (Request) req.getNote(ADAPTER_NOTES); Response response = (Response) res.getNote(ADAPTER_NOTES); boolean success = true; AsyncContextImpl asyncConImpl = request.getAsyncContextInternal(); try { if (!request.isAsync()) { response.setSuspended(false); } if (status==SocketEvent.TIMEOUT) { if (!asyncConImpl.timeout()) { asyncConImpl.setErrorState(null, false); } } else if (status==SocketEvent.ERROR) { } if (!request.isAsyncDispatching() && request.isAsync()) { WriteListener writeListener = res.getWriteListener(); ReadListener readListener = req.getReadListener(); if (writeListener != null && status == SocketEvent.OPEN_WRITE) { ClassLoader oldCL = null; try { oldCL = request.getContext().bind(false, null); res.onWritePossible();//这里执行浏览器响应,写入数据 if (request.isFinished() && req.sendAllDataReadEvent() && readListener != null) { readListener.onAllDataRead(); } } catch (Throwable t) { } finally { request.getContext().unbind(false, oldCL); } } } } //这里判断异步正在进行,说明这不是一个完成方法的回调,是一个正常异步请求,继续调用容器。 if (request.isAsyncDispatching()) { connector.getService().getContainer().getPipeline().getFirst().invoke( request, response); Throwable t = (Throwable) request.getAttribute(RequestDispatcher.ERROR_EXCEPTION); if (t != null) { asyncConImpl.setErrorState(t, true); } } //注意,这里,如果超时或者出错,request.isAsync()会返回false,这里是为了尽快的输出错误给客户端。 if (!request.isAsync()) { //这里也是输出逻辑 request.finishRequest(); response.finishResponse(); } //销毁request和response if (!success || !request.isAsync()) { updateWrapperErrorCount(request, response); request.recycle(); response.recycle(); } } return success; }
上面的代码就是 ctx.complete()
执行最终的方法了(当然省略了很多细节),完成了数据的输出,最终输出到浏览器。
这里有同学可能会说,我知道异步执行完后,调用 ctx.complete()
会输出到浏览器,但是,第一次doGet请求执行完成后,Tomcat是怎么知道不用返回到客户端的呢?关键代码在 CoyoteAdapter
中的 service
方法,部分代码如下:
postParseSuccess = postParseRequest(req, request, res, response); //省略部分代码 if (postParseSuccess) { request.setAsyncSupported( connector.getService().getContainer().getPipeline().isAsyncSupported()); connector.getService().getContainer().getPipeline().getFirst().invoke( request, response); } if (request.isAsync()) { async = true; } else { //输出数据到客户端 request.finishRequest(); response.finishResponse(); if (!async) { updateWrapperErrorCount(request, response); //销毁request和response request.recycle(); response.recycle(); }