jetty接受到連接請求,首先要解析請求;jetty中定義了一個HttpParser類來解析http。類中的部分定義以下java
// States public static final int STATE_START=-14; public static final int STATE_FIELD0=-13; public static final int STATE_SPACE1=-12; public static final int STATE_STATUS=-11; public static final int STATE_URI=-10; public static final int STATE_SPACE2=-9; public static final int STATE_END0=-8; public static final int STATE_END1=-7; public static final int STATE_FIELD2=-6; public static final int STATE_HEADER=-5; public static final int STATE_HEADER_NAME=-4; public static final int STATE_HEADER_IN_NAME=-3; public static final int STATE_HEADER_VALUE=-2; public static final int STATE_HEADER_IN_VALUE=-1; public static final int STATE_END=0; public static final int STATE_EOF_CONTENT=1; public static final int STATE_CONTENT=2; public static final int STATE_CHUNKED_CONTENT=3; public static final int STATE_CHUNK_SIZE=4; public static final int STATE_CHUNK_PARAMS=5; public static final int STATE_CHUNK=6; public static final int STATE_SEEKING_EOF=7; private final EventHandler _handler; private final Buffers _buffers; // source of buffers private final EndPoint _endp; private Buffer _header; // Buffer for header data (and small _content) private Buffer _body; // Buffer for large content private Buffer _buffer; // The current buffer in use (either _header or _content)
從這定義的狀態來看,http解析是順序執行的,從請求頭到content,並把解析出來的http頭和內容保存在自定義的Buffer裏;redis
再來看具體的parse方法:cookie
/** * Parse until {@link #STATE_END END} state. * If the parser is already in the END state, then it is {@link #reset reset} and re-parsed. * @throws IllegalStateException If the buffers have already been partially parsed. */ public void parse() throws IOException { if (_state==STATE_END) reset(); if (_state!=STATE_START) throw new IllegalStateException("!START"); // continue parsing while (_state != STATE_END) if (parseNext()<0) return; }
沒錯,關鍵的解析是在parseNext方法中的,因爲這個方法實在太大,就不貼出來了;session
也就是解析完http頭再解析http體;初始化各類以下:
app
/* ------------------------------------------------------------ */ public AbstractHttpConnection(Connector connector, EndPoint endpoint, Server server) { super(endpoint); _uri = StringUtil.__UTF8.equals(URIUtil.__CHARSET)?new HttpURI():new EncodedHttpURI(URIUtil.__CHARSET); _connector = connector; HttpBuffers ab = (HttpBuffers)_connector; _parser = newHttpParser(ab.getRequestBuffers(), endpoint, new RequestHandler()); _requestFields = new HttpFields(); _responseFields = new HttpFields(); _request = new Request(this); _response = new Response(this); _generator = newHttpGenerator(ab.getResponseBuffers(), endpoint); _generator.setSendServerVersion(server.getSendServerVersion()); _server = server; }
我關心的是request的信息何時被設置;方法就在AbstractHttpConnection類中,部分代碼以下async
protected void handleRequest() throws IOException { boolean error = false; String threadName=null; Throwable async_exception=null; try { if (LOG.isDebugEnabled()) { threadName=Thread.currentThread().getName(); Thread.currentThread().setName(threadName+" - "+_uri); } // Loop here to handle async request redispatches. // The loop is controlled by the call to async.unhandle in the // finally block below. If call is from a non-blocking connector, // then the unhandle will return false only if an async dispatch has // already happened when unhandle is called. For a blocking connector, // the wait for the asynchronous dispatch or timeout actually happens // within the call to unhandle().
解析完就是一個jetty的httpRequest了;
ide
剩下還有一個咱們關心的session;jetty的Request中有兩個屬性與session相關,一個是_session,另外一個是_sessionManager;函數
其中setSession()方法只在兩個地方調用了,兩個調用的地方都在SessionHandler裏;oop
一、檢查requst cookies中的值,或者uri中的參數this
/** * Look for a requested session ID in cookies and URI parameters * * @param baseRequest * @param request */ protected void checkRequestedSessionId(Request baseRequest, HttpServletRequest request)
二、再一個
@Override public void doScope(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { SessionManager old_session_manager = null; HttpSession old_session = null; HttpSession access = null; try { old_session_manager = baseRequest.getSessionManager(); old_session = baseRequest.getSession(false); if (old_session_manager != _sessionManager) { // new session context baseRequest.setSessionManager(_sessionManager); baseRequest.setSession(null); checkRequestedSessionId(baseRequest,request);//即1中指的那個方法 }
比較這兩個地方發現,只有在SessionHandler的doScope方法中設置session;
其中_sessionManager是存儲和維護session的地方;默認是HashSessionManager存儲在內存中,重啓即失效;
在看看Request中的_seesionManager的set方法,也只有SessionHander的doScope調用了;也就是說整個過程只有在這裏給設置_sessionManager。那麼每一次請求過來,Request中的_sessionManager必然是null的;
而後reqest的SessionManager別設置爲SessionHandler的_sessionManager;而這個_sessionManager只有在SessionHander的構造函數中調用setSessionManager方法;全部要找到SessionHander在何時初始化的;
- -! 因爲找了很久仍是不知道怎麼初始化的,大概是執行鏈中獲取的;ScopedHandler中的_nextScope被設置爲SessionHandler; 乏力。。。
-----------------
那麼就無論怎麼初始化SessionHandler中的_sessionMananger的了,只知道最後request中的_sessionManager回等於該_sesionManager;
仍是來看看requet的getSesion方法吧:
/* * @see javax.servlet.http.HttpServletRequest#getSession() */ public HttpSession getSession() { return getSession(true); }
以及
public HttpSession getSession(boolean create) { if (_session != null) { if (_sessionManager != null && !_sessionManager.isValid(_session)) _session = null; else return _session; } if (!create) return null; if (_sessionManager == null) throw new IllegalStateException("No SessionManager"); _session = _sessionManager.newHttpSession(this); HttpCookie cookie = _sessionManager.getSessionCookie(_session,getContextPath(),isSecure()); if (cookie != null) _connection.getResponse().addCookie(cookie); return _session; }
得知調用getSession方法會在sessionManager中建立一個session實例並保存起來;也同時向response中寫入cookie;
若是當前requet已經有sesion直接返回該session;