spring session的生命周期

spring session的生命周期

spring session生命周期

Session获取

spring-session实现了HttpServletRequest的子类–SessionRepositoryRequestWrapper,由它覆盖getSession方法,将由web容器处理的逻辑接管过来。




public HttpSession getSession(boolean create) {
            HttpSessionWrapper currentSession = getCurrentSession();
            if(currentSession != null) {
                return currentSession;
            }
            String requestedSessionId = getRequestedSessionId();
            if(requestedSessionId != null) {
                S session = sessionRepository.getSession(requestedSessionId);
                if(session != null) {
                    this.requestedSessionIdValid = true;
                    currentSession = new HttpSessionWrapper(session, getServletContext());
                    //从数据仓库提取出来的session状态不为new
                    currentSession.setNew(false);
                    setCurrentSession(currentSession);
                    return currentSession;
                }
            }
            if(!create) {
                return null;
            }
            S session = sessionRepository.createSession();
            currentSession = new HttpSessionWrapper(session, getServletContext());
            setCurrentSession(currentSession);
            return currentSession;
        }

session id存在的情况下,如果通过session id能找到持久化的session就直接返回,否则根据create是否为true决定是否新建一个Session。Session在后续的使用中会陆续更改,添加、删除或者修改属性值。从数据仓库中提取出来的session会默认修改lastAccessTime属性以避免session失效。

数据仓库中的持久化session也存在失效时间,消费端可以通过RedisHttpSessionConfiguration.setMaxInactiveIntervalInSeconds(long timemills)来设置,默认是1800秒。redis会定时清除过期数据。

spring-session的Session实现

Spring为了将Session与具体的协议分开,单独提炼出Session实体,再通过HttpSessionWrapper将session包装起来,从而扩展HttpSession.如果以后还需要支持另外一种应用协议,就只要增加一种应用类型的wrapper就行了。

private final class HttpSessionWrapper implements HttpSession {

            public HttpSessionWrapper(S session, ServletContext servletContext) {
                this.session = session;
                this.servletContext = servletContext;
            }
            //省略了大部分方法,都是委托给被包装的Session处理的

            //对session坐invalidate时去数据仓库删掉对应的数据
            public void invalidate() {
                checkState();
                this.invalidated = true;
                requestedSessionInvalidated = true;
                setCurrentSession(null);
                sessionRepository.delete(getId());
            }

            public void setNew(boolean isNew) {
                this.old = !isNew;
            }

            public boolean isNew() {
                checkState();
                return !old;
            }
        }
    }

Session实体主要定义通用的getAttribute和setAttribute等方法。此外扩展了一个ExpiringSession,这是spring的默认session,它主要用来判断session是否失效。

public interface ExpiringSession extends Session {


    //session的创建时间
    long getCreationTime();


    //session的上次访问时间
    long getLastAccessedTime();


    //设置最大访问间隔,超过这个间隔session会被invalidate
    void setMaxInactiveIntervalInSeconds(int interval);

    int getMaxInactiveIntervalInSeconds();


    //session是否失效
    boolean isExpired();

}

session提交

        private void commitSession() {
            HttpSessionWrapper wrappedSession = getCurrentSession();
            if(wrappedSession == null) {
                if(isInvalidateClientSession()) {
                    httpSessionStrategy.onInvalidateSession(this, response);
                }
            } else {
                S session = wrappedSession.session;
                sessionRepository.save(session);
                if(!isRequestedSessionIdValid() || !session.getId().equals(getRequestedSessionId())) {
                    httpSessionStrategy.onNewSession(session, this, response);
                }
            }
        }
  1. getSession时会通过setCurrentSession把新建或者提取出来的session放到request的HttpServletRequestWrapper.class.getName()属性上;相应的在session invalidate时也会将session从request里移除掉,此时通过getCurrentSession将取不到数据。
  2. 在做session持久化时,会首先判断session是否被invalidate,如果是则会删除

猜你喜欢

转载自m635674608.iteye.com/blog/2398532