zoukankan      html  css  js  c++  java
  • request.getSession(true/false)的区别

    【原文链接】:https://blog.tecchen.tech ,博文同步发布到博客园。
    由于精力有限,对文章的更新可能不能及时同步,请点击上面的原文链接访问最新内容。
    欢迎访问我的个人网站:https://www.tecchen.tech

    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)。

    @Override
    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);
        }
    }
    
    @Override
    public 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。

  • 相关阅读:
    zabbix中文配置指南(转)-服务器监控
    Native Fullscreen JavaScript API (plus jQuery plugin)
    浅谈 HTML5 的 DOM Storage 机制 (转)
    How to Customize Server Header using NginX headers-more module
    编译安装nginx并修改版本头信息—参考实例
    nginx 去掉服务器版本和名称和nginx_status 状态说明
    修改NGINX版本名称为任意WEB SERVER
    php加速缓存Xcache的安装与配置
    nginx-rrd监控nginx访问数
    Egret3D初步笔记二 (Unity导出场景使用)
  • 原文地址:https://www.cnblogs.com/Candies/p/10635414.html
Copyright © 2011-2022 走看看