tomcat原始碼解析第6課-一次http請求過程
阿新 • • 發佈:2019-01-28
目錄
1、啟動8080埠監聽http請求時序圖
2、啟動8080埠監聽http請求程式碼解析
3、http請求時序圖
4、http請求request和response的封裝
5、查詢自定義過濾器和servlet
6、自定義的過濾器和servlet呼叫
一、啟動8080埠監聽http請求時序圖
二、啟動8080埠監聽http請求程式碼解析
NioEndpoint的方法startInternal啟動socket的監聽,監聽http請求
@Override public void startInternal() throws Exception { if (!running) { running = true; paused = false; processorCache = new SynchronizedStack<>(SynchronizedStack.DEFAULT_SIZE, socketProperties.getProcessorCache()); eventCache = new SynchronizedStack<>(SynchronizedStack.DEFAULT_SIZE, socketProperties.getEventCache()); nioChannels = new SynchronizedStack<>(SynchronizedStack.DEFAULT_SIZE, socketProperties.getBufferPool()); // Create worker collection if ( getExecutor() == null ) { createExecutor(); } initializeConnectionLatch(); // Start poller threads pollers = new Poller[getPollerThreadCount()]; for (int i=0; i<pollers.length; i++) { pollers[i] = new Poller(); Thread pollerThread = new Thread(pollers[i], getName() + "-ClientPoller-"+i); pollerThread.setPriority(threadPriority); pollerThread.setDaemon(true); pollerThread.start(); } //開啟執行緒監聽http請求 startAcceptorThreads(); } }
NioEndpoint的內部類Acceptor,啟動監聽,在瀏覽器輸入http地址,此內部類接受到請求
protected class Acceptor extends AbstractEndpoint.Acceptor { @Override public void run() { int errorDelay = 0; // Loop until we receive a shutdown command while (running) { // Loop if endpoint is paused while (paused && running) { state = AcceptorState.PAUSED; try { Thread.sleep(50); } catch (InterruptedException e) { // Ignore } } if (!running) { break; } state = AcceptorState.RUNNING; try { //if we have reached max connections, wait countUpOrAwaitConnection(); SocketChannel socket = null; try { // Accept the next incoming connection from the server // 監聽http請求 socket = serverSock.accept(); } catch (IOException ioe) { // We didn't get a socket countDownConnection(); if (running) { // Introduce delay if necessary errorDelay = handleExceptionWithDelay(errorDelay); // re-throw throw ioe; } else { break; } } // Successful accept, reset the error delay errorDelay = 0; // Configure the socket if (running && !paused) { // setSocketOptions() will hand the socket off to // an appropriate processor if successful //重要的方法,將socket連線新增到一個快取佇列,這裡使用的是生產者和消費者模式 //關於生產者和消費者的學習地址 //http://blog.csdn.net/c275046758/article/details/50492107 if (!setSocketOptions(socket)) { closeSocket(socket); } } else { closeSocket(socket); } } catch (Throwable t) { ExceptionUtils.handleThrowable(t); log.error(sm.getString("endpoint.accept.fail"), t); } } state = AcceptorState.ENDED; } 。。。。。 }
三、http請求時序圖
四、http請求request和response的封裝
類AbstractProtocol,完成tomcat的不能被繼承org.apache.coyote.Request和org.apache.coyote.Response的初始化
@Override public SocketState process(SocketWrapperBase<S> wrapper, SocketEvent status) { 。。。。。 if (processor == null) { //初始化tomcat內部的request和response processor = getProtocol().createProcessor(); register(processor); } SocketState state = SocketState.CLOSED; do { //重點 state = processor.process(wrapper, status); }
類CoyoteAdapter,完成org.apache.coyote.Request、org.apache.coyote.Response到org.apache.catalina.connector.Request、org.apache.catalina.connector.Response的轉換;
@Override
public void service(org.apache.coyote.Request req, org.apache.coyote.Response res)
throws Exception {
Request request = (Request) req.getNote(ADAPTER_NOTES);
Response response = (Response) res.getNote(ADAPTER_NOTES);
//request和response的轉換
if (request == null) {
// Create objects
request = connector.createRequest();
request.setCoyoteRequest(req);
response = connector.createResponse();
response.setCoyoteResponse(res);
// Link objects
request.setResponse(response);
response.setRequest(request);
}
try {
// Parse and set Catalina and configuration specific
// 查詢servlet
postParseSuccess = postParseRequest(req, request, res, response);
if (postParseSuccess) {
//check valves if we support async
request.setAsyncSupported(
connector.getService().getContainer().getPipeline().isAsyncSupported());
// 重點
connector.getService().getContainer().getPipeline().getFirst().invoke(
request, response);
}
}
StandardContextValve類,如果訪問的是WEB-INF目錄則阻止
public final void invoke(Request request, Response response)
throws IOException, ServletException {
// 對指定的訪問目錄做控制 WEB-INF or META-INF
MessageBytes requestPathMB = request.getRequestPathMB();
if ((requestPathMB.startsWithIgnoreCase("/META-INF/", 0))
|| (requestPathMB.equalsIgnoreCase("/META-INF"))
|| (requestPathMB.startsWithIgnoreCase("/WEB-INF/", 0))
|| (requestPathMB.equalsIgnoreCase("/WEB-INF"))) {
response.sendError(HttpServletResponse.SC_NOT_FOUND);
return;
}
五、查詢自定義的過濾器和servlet
CoyoteAdapter類的方法postParseRequest,查詢servlet
protected boolean postParseRequest(org.apache.coyote.Request req, Request request,
org.apache.coyote.Response res, Response response) throws IOException, ServletException {
。。。。。。。。。。
while (mapRequired) {
// 查詢到servlet
connector.getService().getMapper().map(serverName, decodedURI,
version, request.getMappingData());
}
六、自定義的過濾器和servlet的呼叫
類ApplicationFilterChain,呼叫自定義的過濾器和自定義servlet
private void internalDoFilter(ServletRequest request,
ServletResponse response)
throws IOException, ServletException {
if( Globals.IS_SECURITY_ENABLED ) {
final ServletRequest req = request;
final ServletResponse res = response;
Principal principal =
((HttpServletRequest) req).getUserPrincipal();
Object[] args = new Object[]{req, res, this};
SecurityUtil.doAsPrivilege ("doFilter", filter, classType, args, principal);
} else {
//呼叫自定義過濾器
filter.doFilter(request, response, this);
}
} catch (IOException | ServletException | RuntimeException e) {
throw e;
} catch (Throwable e) {
e = ExceptionUtils.unwrapInvocationTargetException(e);
ExceptionUtils.handleThrowable(e);
throw new ServletException(sm.getString("filterChain.filter"), e);
}
return;
}
} else {
//呼叫自定義servlet
servlet.service(request, response);
}
}