您好,登錄后才能下訂單哦!
這篇文章主要介紹“如何創建session對象”的相關知識,小編通過實際案例向大家展示操作過程,操作方法簡單快捷,實用性強,希望這篇“如何創建session對象”文章能幫助大家解決問題。
Session對象的創建一般是源于這樣的一條語句:
Session session = request.getSession(false);或者Session session = request.getSession();如果不在乎服務器壓力可能多那么一點點的話。
在Tomcat的實現中,這個request是org.apache.catalina.connector.Request類的包裝類org.apache.catalina.connector.RequestFacade的對象,它的兩個#getSession()方法如下:
public HttpSession getSession(boolean create) { if (request == null) { throw new IllegalStateException( sm.getString("requestFacade.nullRequest")); } if (SecurityUtil.isPackageProtectionEnabled()){ return (HttpSession)AccessController. doPrivileged(new GetSessionPrivilegedAction(create)); } else { return request.getSession(create); } }
public HttpSession getSession() { if (request == null) { throw new IllegalStateException( sm.getString("requestFacade.nullRequest")); } return getSession(true); }
其實差不太多,最后都會進入org.apache.catalina.connector.Request的#getSession()方法。這個方法的源代碼如下:
public HttpSession getSession(boolean create) { Session session = doGetSession(create); if (session != null) { return session.getSession(); } else { return null; } }
然后調用就到了#doGetSession()這個方法了。源代碼如下
protected Session doGetSession(boolean create) { // 沒有Context的話直接返回null if (context == null) return (null); // 判斷Session是否有效 if ((session != null) && !session.isValid()) session = null; if (session != null) return (session); // 返回Manager對象,這里是StandardManager類的對象 Manager manager = null; if (context != null) manager = context.getManager(); if (manager == null) return (null); // Sessions are not supported // 判斷是否有SessionID if (requestedSessionId != null) { try { // 在Manager中根據SessionID查找Session session = manager.findSession(requestedSessionId); } catch (IOException e) { session = null; } if ((session != null) && !session.isValid()) session = null; if (session != null) { // 更新訪問時間 session.access(); return (session); } } // 創建新的Session if (!create) return (null); if ((context != null) && (response != null) && context.getCookies() && response.getResponse().isCommitted()) { throw new IllegalStateException(sm.getString("coyoteRequest.sessionCreateCommitted")); } // 判斷是否使用 "/" 作為Session Cookie的存儲路徑 并且 是否SessionID來自Cookie if (connector.getEmptySessionPath() && isRequestedSessionIdFromCookie()) { // 創建Session session = manager.createSession(getRequestedSessionId()); } else { session = manager.createSession(null); } // 創建一個新的Session Cookies if ((session != null) && (getContext() != null) && getContext().getCookies()) { Cookie cookie = new Cookie(Globals.SESSION_COOKIE_NAME, session.getIdInternal()); // 配置Session Cookie configureSessionCookie(cookie); // 在響應中加入Session Cookie response.addCookieInternal(cookie); } if (session != null) { // 更新訪問時間 session.access(); return (session); } else { return (null); } }
這個方法說明了Session創建的大致過程,首先判斷requestedSessionId是否存在,如果存在,那么根據這個ID去查找Session對象。如果requestedSessionId不存在或者沒有取到Session,并且傳遞給#getSession(boolean)的參數為真,那么要創建一個新的Session,并且給客戶端寫回去一個Session Cookie。
首先,我感興趣的是requestedSessionId的賦值,它到底是什么時候被賦值的呢?
還要向回看Tomcat的請求處理過程,請求曾到過這一步,org.apache.catalina.connector.CoyoteAdapter的#service()方法。里邊有這樣一句方法調用:postParseRequest(req, request, res, response)。就是這一步處理了SessionID的獲取,這個方法調用了#parseSessionId()和parseSessionCookiesId()這兩個方法,就是它對Session ID進行了提取,源代碼分別如下:
protected void parseSessionId(org.apache.coyote.Request req, Request request) { ByteChunk uriBC = req.requestURI().getByteChunk(); // 判斷URL中是不是有";jsessionid="這個字符串 int semicolon = uriBC.indexOf(match, 0, match.length(), 0); if (semicolon > 0) { // Parse session ID, and extract it from the decoded request URI // 在URL中提取Session ID int start = uriBC.getStart(); int end = uriBC.getEnd(); int sessionIdStart = semicolon + match.length(); int semicolon2 = uriBC.indexOf(';', sessionIdStart); if (semicolon2 >= 0) { request.setRequestedSessionId(new String(uriBC.getBuffer(), start + sessionIdStart, semicolon2 - sessionIdStart)); byte[] buf = uriBC.getBuffer(); for (int i = 0; i < end - start - semicolon2; i++) { buf[start + semicolon + i] = buf[start + i + semicolon2]; } uriBC.setBytes(buf, start, end - start - semicolon2 + semicolon); } else { request.setRequestedSessionId(new String(uriBC.getBuffer(), start + sessionIdStart, (end - start) - sessionIdStart)); uriBC.setEnd(start + semicolon); } // 設定Session ID來自于URL request.setRequestedSessionURL(true); } else { request.setRequestedSessionId(null); request.setRequestedSessionURL(false); } }
protected void parseSessionCookiesId(org.apache.coyote.Request req, Request request) { Context context = (Context) request.getMappingData().context; if (context != null && !context.getCookies()) return; // 返回Cookie Cookies serverCookies = req.getCookies(); int count = serverCookies.getCookieCount(); if (count <= 0) return; for (int i = 0; i < count; i++) { ServerCookie scookie = serverCookies.getCookie(i); // 判斷是否有JSESSIONID這個名字的Cookie if (scookie.getName().equals(Globals.SESSION_COOKIE_NAME)) { // Override anything requested in the URL if (!request.isRequestedSessionIdFromCookie()) { // 設定Session ID convertMB(scookie.getValue()); request.setRequestedSessionId(scookie.getValue().toString()); // 如果之前在URL中讀到了SessionID,那么會覆蓋它 request.setRequestedSessionCookie(true); request.setRequestedSessionURL(false); if (log.isDebugEnabled()) log.debug(" Requested cookie session id is " + request.getRequestedSessionId()); } else { if (!request.isRequestedSessionIdValid()) { convertMB(scookie.getValue()); request.setRequestedSessionId(scookie.getValue().toString()); } } } } }
Tomcat就是通過上邊的兩個方法讀到URL或者Cookie中存放的Session ID的。
了解了Session ID的獲取,下面要看一下Session的查找過程,就是org.apache.catalina.session.StandardManager的#findSession()方法。這個方法是在它的基類中定義的,源代碼如下:
public Session findSession(String id) throws IOException { if (id == null) return (null); return (Session) sessions.get(id); }
代碼很短,其中sessions是一個ConcurrentHashMap<String, Session>對象。那么這個sessions的對象是什么時候載入的Session呢?
啟動的時候!可以看一下StandardManager#start()方法。最后調用了#load()方法,這個就是載入Session的方法了:
public void load() throws ClassNotFoundException, IOException { if (SecurityUtil.isPackageProtectionEnabled()) { try { AccessController.doPrivileged(new PrivilegedDoLoad()); } catch (PrivilegedActionException ex) { Exception exception = ex.getException(); if (exception instanceof ClassNotFoundException) { throw (ClassNotFoundException) exception; } else if (exception instanceof IOException) { throw (IOException) exception; } if (log.isDebugEnabled()) log.debug("Unreported exception in load() " + exception); } } else { doLoad(); } }
最后調用了#doLoad()方法來具體的載入Session,源代碼如下:
protected void doLoad() throws ClassNotFoundException, IOException { if (log.isDebugEnabled()) log.debug("Start: Loading persisted sessions"); // 清空Map sessions.clear(); // 對應work/Catalina/localhost/%app name%/SESSIONS.ser文件 File file = file(); if (file == null) return; if (log.isDebugEnabled()) log.debug(sm.getString("standardManager.loading", pathname)); FileInputStream fis = null; ObjectInputStream ois = null; Loader loader = null; ClassLoader classLoader = null; try { // 載入Session緩存文件 fis = new FileInputStream(file.getAbsolutePath()); BufferedInputStream bis = new BufferedInputStream(fis); if (container != null) loader = container.getLoader(); if (loader != null) classLoader = loader.getClassLoader(); if (classLoader != null) { if (log.isDebugEnabled()) log.debug("Creating custom object input stream for class loader "); ois = new CustomObjectInputStream(bis, classLoader); } else { if (log.isDebugEnabled()) log.debug("Creating standard object input stream"); ois = new ObjectInputStream(bis); } } catch (FileNotFoundException e) { if (log.isDebugEnabled()) log.debug("No persisted data file found"); return; } catch (IOException e) { log.error(sm.getString("standardManager.loading.ioe", e), e); if (ois != null) { try { ois.close(); } catch (IOException f) { ; } ois = null; } throw e; } synchronized (sessions) { try { // 讀出Session個數 Integer count = (Integer) ois.readObject(); int n = count.intValue(); if (log.isDebugEnabled()) log.debug("Loading " + n + " persisted sessions"); // 讀入Session for (int i = 0; i < n; i++) { StandardSession session = getNewSession(); session.readObjectData(ois); session.setManager(this); sessions.put(session.getIdInternal(), session); session.activate(); sessionCounter++; } } catch (ClassNotFoundException e) { log.error(sm.getString("standardManager.loading.cnfe", e), e); if (ois != null) { try { ois.close(); } catch (IOException f) { ; } ois = null; } throw e; } catch (IOException e) { log.error(sm.getString("standardManager.loading.ioe", e), e); if (ois != null) { try { ois.close(); } catch (IOException f) { ; } ois = null; } throw e; } finally { try { if (ois != null) ois.close(); } catch (IOException f) { } // 刪除Session緩存文件 if (file != null && file.exists()) file.delete(); } } if (log.isDebugEnabled()) log.debug("Finish: Loading persisted sessions"); }
大致知道了Session的讀取過程,后面就是Session沒找到時創建Session的過程了。具體就是org.apache.catalina.session.StandardManager的#createSession()方法:
public Session createSession(String sessionId) { if ((maxActiveSessions >= 0) && (sessions.size() >= maxActiveSessions)) { rejectedSessions++; throw new IllegalStateException(sm.getString("standardManager.createSession.ise")); } return (super.createSession(sessionId)); }
最后調用到了它的基類的#createSession()方法了。
public Session createSession(String sessionId) { // 創建一個新的Session Session session = createEmptySession(); // 初始化Session的屬性 session.setNew(true); session.setValid(true); session.setCreationTime(System.currentTimeMillis()); session.setMaxInactiveInterval(this.maxInactiveInterval); // 如果Session ID為null,那么就生成一個 if (sessionId == null) { sessionId = generateSessionId(); } session.setId(sessionId); sessionCounter++; return (session); }
通過上述過程,一個新的Session就創建出來了。
關于“如何創建session對象”的內容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業相關的知識,可以關注億速云行業資訊頻道,小編每天都會為大家更新不同的知識點。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。