request.getsession()方法说明

HttpServletRequest接口中getSession()方法有3种用法,说明如下:

  1. request.getSession()就是request.getSession(true)
  2. request.getSession(false)与上二者的区别在于,如果当前Context中没有Session时(如用户第一次访问网站时),并不创建新Session对象,直接返回null

以下根据tomcat-8.0.24中的源码进行简单说明。

getSession()与getSession(true)

从这个org.apache.catalina.connector.RequestFacade类中可以看到getSession()方法其实就是调用getSession(true)

public 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"));    }    return getSession(true);}

getSession(false)

上面的方法会调用此org.apache.catalina.connector.Request类中的getSession()doGetSession(true)方法,然后由session.getSession()返回结果。

如果是getSession(false),则会进入doGetSession(false)方法,当用户初次访问时,requestedSessionId为空,所以sessionnull,因为此时参数create传入的值为false,所以直接返回null

@Overridepublic HttpSession getSession() {    Session session = doGetSession(true);    if (session == null) {        return null;    }    return session.getSession();}public HttpSession getSession(boolean create) {    Session session = doGetSession(create);    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);        } 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) {        // request.getSession(false)时,在此返回null        return (null);    }    if (response != null            && context.getServletContext()                    .getEffectiveSessionTrackingModes()                    .contains(SessionTrackingMode.COOKIE)            && response.getResponse().isCommitted()) {        throw new IllegalStateException(                sm.getString("coyoteRequest.sessionCreateCommitted"));    }    // Attempt to reuse session id if one was submitted in a cookie    // Do not reuse the session id if it is from a URL, to prevent possible    // phishing attacks    // Use the SSL session ID if one is present.    if (("/".equals(context.getSessionCookiePath())            && isRequestedSessionIdFromCookie()) || requestedSessionSSL ) {        session = manager.createSession(getRequestedSessionId());    } else {        session = manager.createSession(null);    }    // 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;}

findSession(String)

再通过org.apache.catalina.session.ManagerBase看一下servlet是如何通过requestedSessionId查找到对应的用户session的,由下面代码可以看到tomcat中用户session使用ConcurrentHashMap作为容器进行管理的。

/** * Return the active Session, associated with this Manager, with the specified session id (if any); otherwise return null. * Parameters: * id The session id for the session to be returned * Throws: * java.lang.IllegalStateException if a new session cannot be instantiated for any reason * java.io.IOException if an input/output error occurs while processing this request */@Overridepublic Session findSession(String id) throws IOException {    if (id == null)        return (null);    return sessions.get(id);}/** * The set of currently active Sessions for this Manager, keyed by session identifier. */protected Map<String, Session> sessions = new ConcurrentHashMap<>();

favicon.ico和session

在浏览器中访问favicon.ico文件时,HTTP请求的header中不会发送用户当前的cookie信息,当服务器上使用MVC的拦截器时,就需要注意,不要拦截这个favicon.ico文件,因为在这个请求中不能获得用户的session,因此也不要在拦截器中使用request.getSession()方法来获得session,不小心可能会重置用户的session,最好是使用request.getSession(false)方法。

References

  1. grepCode org.apache.catalina.connector.RequestFacade
  2. tomcat-8.0-doc