javax.servlet.http.HttpServletRequest接口有两个方法:getSession(boolean)和getSession()。
具体什么区别,跟踪源码分析下,先摆出结论: request.getSession(true):获取session,如果session不存在,就新建一个。 reqeust.getSession(false)获取session,如果session不存在,则返回null。 Debug时,查看HttpServletRequest接口的实现类为RequestFacade。 使用Idea查看RequestFacade的代码实现,可以看出是通过Facade外观模式对org.apache.catalina.connector.Request进行了封装。 继续看getSession()的源码,其实是调用了getSession(true)。具体是调用了request.getSession(create)。@Overridepublic HttpSession getSession(boolean create) { if (request == null) { throw new IllegalStateException( sm.getString("requestFacade.nullRequest")); } if (SecurityUtil.isPackageProtectionEnabled()){ return AccessController. doPrivileged(new GetSessionPrivilegedAction(create)); } else { return request.getSession(create); }}@Overridepublic HttpSession getSession() { if (request == null) { throw new IllegalStateException( sm.getString("requestFacade.nullRequest")); } // 直接调用getSession(true) return getSession(true);}
进入到Request.getSession(boolean),根据注释看出,create为true时,如果HttpSession不存在,会创建一个新的HttpSession。
/** * @return the session associated with this Request, creating one * if necessary and requested. * * @param create Create a new session if one does not exist */ @Override public HttpSession getSession(boolean create) { Session session = doGetSession(create); if (session == null) { return null; } return session.getSession(); }
继续进入到doGetSession(boolean create)方法,继续分析。
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 // 如果当前session存在且有效,返回当前session 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); } 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 // create为false时,返回null;create为true时创建一个新的session if (!create) { return (null); } if (response != null && context.getServletContext() .getEffectiveSessionTrackingModes() .contains(SessionTrackingMode.COOKIE) && response.getResponse().isCommitted()) { throw new IllegalStateException( sm.getString("coyoteRequest.sessionCreateCommitted")); } // Re-use session IDs provided by the client in very limited // circumstances. 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())) { /* This is the common(ish) use case: using the same session ID with * multiple web applications on the same host. Typically this is * used by Portlet implementations. It only works if sessions are * tracked via cookies. The cookie must have a path of "/" else it * won't be provided for requests to all web applications. * * Any session ID provided by the client should be for a session * that already exists somewhere on the host. Check if the context * is configured for this to be confirmed. */ 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); // Creating a new session cookie based on that session if (session != null && context.getServletContext() .getEffectiveSessionTrackingModes() .contains(SessionTrackingMode.COOKIE)) { Cookie cookie = ApplicationSessionCookieConfig.createSessionCookie( context, session.getIdInternal(), isSecure()); response.addSessionCookieInternal(cookie); } if (session == null) { return null; } session.access(); return session; }
StandardContext跟session没有啥关系,就是学习下StandardContext的源码及ReentrantReadWriteLock。
@Override public Manager getManager() { Lock readLock = managerLock.readLock(); readLock.lock(); try { return manager; } finally { readLock.unlock(); } } @Override 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("StandardContext.setManager: stop-destroy: ", 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("StandardContext.setManager: start: ", e); } } } finally { writeLock.unlock(); } // Report this property change to interested listeners support.firePropertyChange("manager", oldManager, manager); }
结论:
request.getSession(true):获取session,如果session不存在,就新建一个。 reqeust.getSession(false)获取session,如果session不存在,则返回null。