Network Security Internet Technology Development Database Servers Mobile Phone Android Software Apple Software Computer Software News IT Information

In addition to Weibo, there is also WeChat

Please pay attention

WeChat public account

Shulou

How to manage session in Tomcat9

2025-02-25 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >

Share

Shulou(Shulou.com)06/02 Report--

This article mainly introduces how to manage session in Tomcat9. It is very detailed and has a certain reference value. Friends who are interested must finish it!

Source code parsing

There are two classes related to session:

StandardSession: the default session class, which is a system abstraction of session

StandardManager: the default session management class that manages the creation, loading, persistence of session, etc.

Org.apache.catalina.core.StandardContext.startInternal () protected synchronized void startInternal () throws LifecycleException {... Omit other code. Manager contextManager = null; Manager manager = getManager () If (manager = = null) {if (log.isDebugEnabled ()) {log.debug (sm.getString ("standardContext.cluster.noManager", Boolean.valueOf ((getCluster ()! = null)), Boolean.valueOf (distributable) } if ((getCluster ()! = null) & & distributable) {try {contextManager = getCluster () .createManager (getName ()) } catch (Exception ex) {log.error (sm.getString ("standardContext.cluster.managerError"), ex); ok = false;}} else {contextManager = new StandardManager () }} / / Configure default manager if none was specified if (contextManager! = null) {if (log.isDebugEnabled ()) {log.debug (sm.getString ("standardContext.manager", contextManager.getClass () .getName () } setManager (contextManager);} Omit other code... public void setManager (Manager manager) {Lock writeLock = managerLock.writeLock (); writeLock.lock (); Manager oldManager = null; try {/ / Change components if necessary oldManager = this.manager; if (oldManager = = manager) return; this.manager = manager / / Stop the old component if necessary if (oldManager instanceof Lifecycle) {try {((Lifecycle) oldManager) .stop (); ((Lifecycle) oldManager) .destroy ();} catch (LifecycleException e) {log.error (sm.getString ("standardContext.setManager.stop"), e) }} / / Start the new component if necessary if (manager! = null) {manager.setContext (this);} if (getState (). IsAvailable () & & manager instanceof Lifecycle) {try {((Lifecycle) manager) .start () } catch (LifecycleException e) {log.error (sm.getString ("standardContext.setManager.start"), e);} finally {writeLock.unlock ();} / Report this property change to interested listeners support.firePropertyChange ("manager", oldManager, manager);}}

In the start method of StandardContext, sessionManager is instantiated. Here is the cluster session that supports Tomcat. This article takes stand-alone session management as an example, that is, StandardManager, where StandardManager.start is called in setManager.

Org.apache.catalina.session.StandardManager.start () protected synchronized void startInternal () throws LifecycleException {super.startInternal (); / / Load unloaded sessions, if any try {load ();} catch (Throwable t) {ExceptionUtils.handleThrowable (t); log.error (sm.getString ("standardManager.managerLoad"), t);} setState (LifecycleState.STARTING) } protected String pathname = "SESSIONS.ser"; protected void doLoad () throws ClassNotFoundException, IOException {if (log.isDebugEnabled ()) {log.debug ("Start: Loading persisted sessions");} / / Initialize our internal data structures sessions.clear (); / / Open an input stream to the specified pathname, if any File file = file (); if (file = = null) {return } if (log.isDebugEnabled ()) {log.debug (sm.getString ("standardManager.loading", pathname));} Loader loader = null; ClassLoader classLoader = null; Log logger = null; try (FileInputStream fis = new FileInputStream (file.getAbsolutePath ()); BufferedInputStream bis = new BufferedInputStream (fis)) {Context c = getContext () Loader = c.getLoader (); logger = c.getLogger (); if (loader! = null) {classLoader = loader.getClassLoader ();} if (classLoader = = null) {classLoader = getClass () .getClassLoader () } / / Load the previously unloaded active sessions synchronized (sessions) {try (ObjectInputStream ois = new CustomObjectInputStream (bis, classLoader, logger, getSessionAttributeValueClassNamePattern (), getWarnOnSessionAttributeFilterFailure ()) {Integer count = (Integer) ois.readObject (); int n = count.intValue () If (log.isDebugEnabled ()) log.debug ("Loading" + n + "persisted sessions"); for (int I = 0; I

< n; i++) { StandardSession session = getNewSession(); session.readObjectData(ois); session.setManager(this); sessions.put(session.getIdInternal(), session); session.activate(); if (!session.isValidInternal()) { // If session is already invalid, // expire session to prevent memory leak. session.setValid(true); session.expire(); } sessionCounter++; } } finally { // Delete the persistent storage file if (file.exists()) { if (!file.delete()) { log.warn(sm.getString("standardManager.deletePersistedFileFail", file)); } } } } } catch (FileNotFoundException e) { if (log.isDebugEnabled()) { log.debug("No persisted data file found"); } return; } if (log.isDebugEnabled()) { log.debug("Finish: Loading persisted sessions"); } }protected void doUnload() throws IOException { if (log.isDebugEnabled()) log.debug(sm.getString("standardManager.unloading.debug")); if (sessions.isEmpty()) { log.debug(sm.getString("standardManager.unloading.nosessions")); return; // nothing to do } // Open an output stream to the specified pathname, if any File file = file(); if (file == null) { return; } if (log.isDebugEnabled()) { log.debug(sm.getString("standardManager.unloading", pathname)); } // Keep a note of sessions that are expired List list = new ArrayList(); try (FileOutputStream fos = new FileOutputStream(file.getAbsolutePath()); BufferedOutputStream bos = new BufferedOutputStream(fos); ObjectOutputStream oos = new ObjectOutputStream(bos)) { synchronized (sessions) { if (log.isDebugEnabled()) { log.debug("Unloading " + sessions.size() + " sessions"); } // Write the number of active sessions, followed by the details oos.writeObject(Integer.valueOf(sessions.size())); for (Session s : sessions.values()) { StandardSession session = (StandardSession) s; list.add(session); session.passivate(); session.writeObjectData(oos); } } } // Expire all the sessions we just wrote if (log.isDebugEnabled()) { log.debug("Expiring " + list.size() + " persisted sessions"); } for (StandardSession session : list) { try { session.expire(false); } catch (Throwable t) { ExceptionUtils.handleThrowable(t); } finally { session.recycle(); } } if (log.isDebugEnabled()) { log.debug("Unloading complete"); } } 在start方法中,会调用load方法,load方法最终调用doLoad方法,会读取文件名为SESSIONS.ser的文件,该文件存储了Tomcat关闭时session的内容,具体存储逻辑在doUnload方法中 Request.getSession()public HttpSession getSession() { Session session = doGetSession(true); if (session == null) { return null; } return session.getSession(); }protected Session doGetSession(boolean create) { // There cannot be a session if no context has been assigned yet Context context = getContext(); if (context == null) { return null; } // Return the current session if it exists and is valid if ((session != null) && !session.isValid()) { session = null; } if (session != null) { return session; } // Return the requested session if it exists and is valid Manager manager = context.getManager(); if (manager == null) { return null; // Sessions are not supported } if (requestedSessionId != null) { try { session = manager.findSession(requestedSessionId); //读取session } catch (IOException e) { session = null; } if ((session != null) && !session.isValid()) { session = null; } if (session != null) { session.access(); return session; } } // Create a new session if requested and the response is not committed if (!create) { return null; } boolean trackModesIncludesCookie = context.getServletContext().getEffectiveSessionTrackingModes().contains(SessionTrackingMode.COOKIE); if (trackModesIncludesCookie && response.getResponse().isCommitted()) { throw new IllegalStateException(sm.getString("coyoteRequest.sessionCreateCommitted")); } String sessionId = getRequestedSessionId(); if (requestedSessionSSL) { // If the session ID has been obtained from the SSL handshake then // use it. } else if (("/".equals(context.getSessionCookiePath()) && isRequestedSessionIdFromCookie())) { if (context.getValidateClientProvidedNewSessionId()) { boolean found = false; for (Container container : getHost().findChildren()) { Manager m = ((Context) container).getManager(); if (m != null) { try { if (m.findSession(sessionId) != null) { found = true; break; } } catch (IOException e) { // Ignore. Problems with this manager will be // handled elsewhere. } } } if (!found) { sessionId = null; } } } else { sessionId = null; } session = manager.createSession(sessionId); //创建新的session // Creating a new session cookie based on that session if (session != null && trackModesIncludesCookie) { Cookie cookie = ApplicationSessionCookieConfig.createSessionCookie( context, session.getIdInternal(), isSecure()); response.addSessionCookieInternal(cookie); } if (session == null) { return null; } session.access(); return session; } 在getSession方法中,会先根据sessionId在调用manager.findSession查找,如果查找不存在则会调用manager.createSession创建 findSession() & createSession()public Session findSession(String id) throws IOException { if (id == null) { return null; } return sessions.get(id); }public Session createSession(String sessionId) { if ((maxActiveSessions >

= 0) & & (getActiveSessions () > = maxActiveSessions) {rejectedSessions++; throw new TooManyActiveSessionsException (sm.getString ("managerBase.createSession.ise"), maxActiveSessions);} / / Recycle or create a Session instance Session session = createEmptySession (); / / Initialize the properties of the new session and return it session.setNew (true) Session.setValid (true); session.setCreationTime (System.currentTimeMillis ()); session.setMaxInactiveInterval (getContext (). GetSessionTimeout () * 60); String id = sessionId; if (id = = null) {id = generateSessionId ();} session.setId (id); sessionCounter++; SessionTiming timing = new SessionTiming (session.getCreationTime (), 0) Synchronized (sessionCreationTiming) {sessionCreationTiming.add (timing); sessionCreationTiming.poll ();} return session;}

All session is maintained in one HashMap, which is maintained in Map when created, and read from Map.

The above is all the contents of the article "how to manage session in Tomcat9". Thank you for reading! Hope to share the content to help you, more related knowledge, welcome to follow the industry information channel!

Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.

Views: 0

*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.

Share To

Development

Wechat

© 2024 shulou.com SLNews company. All rights reserved.

12
Report