zoukankan      html  css  js  c++  java
  • Shiro AbstractNativeSessionManager的设计概念

    AbstractNativeSessionManager具体实现了SessionManager的行为和NativeSessionManager的行为

    具备了Session监听器,session创建时监听器起作用

    具体实现SessionManager的行为之 Session start(SessionContext context);

    public Session start(SessionContext context) {
        // 抽象创建Session的行为,后文详解#1
        Session session = createSession(context);
        // 为Session设置过期时间,后文详解#2
        applyGlobalSessionTimeout(session);
        // 开启Session中的行为,后文详解#3
        onStart(session, context);
        // 通知监听器执行Session创建中行为,后文详解#4
        notifyStart(session);
        // 包装Session,最终要实现的Session可以存储在除了内存外的其他介质中(如Redis),后文详解#5
        return createExposedSession(session, context);
    }

    书接前文#1

    创建session的过程也会经过几道工序,所以需要抽象,让其子类在创建Session的过程中执行自身特有的行为

    protected abstract Session createSession(SessionContext context) throws AuthorizationException;

    AbstractValidatingSessionManager执行创建Session的行为

    protected Session createSession(SessionContext context) throws AuthorizationException {
    // 如果有必要的话对Session进行有效性校验 enableSessionValidationIfNecessary();
    // 具体创建Session的行为,继续抽象化
    return doCreateSession(context); }

    protected abstract Session doCreateSession(SessionContext initData) throws AuthorizationException;

    DefaultSessionManager具体执行创建Session的工作,因为其有SessionFactory和SessionDao其具体职能就是创建Session

    protected Session doCreateSession(SessionContext context) {
        Session s = newSessionInstance(context);
        if (log.isTraceEnabled()) {
            log.trace("Creating session for host {}", s.getHost());
        }
        create(s);
        return s;
    }
    
    // SessionFactory负责创建基础Session
    protected Session newSessionInstance(SessionContext context) { return getSessionFactory().createSession(context); } // SessionDao负责存储Session到介质中 protected void create(Session session) { if (log.isDebugEnabled()) { log.debug("Creating new EIS record for new session instance [" + session + "]"); } sessionDAO.create(session); }

    书接前文#2

    protected void applyGlobalSessionTimeout(Session session) {
        // 从AbstractSessionManager中获得全局Session过期时间,然后为Session设置上
        session.setTimeout(getGlobalSessionTimeout());
        // 执行Session更新时的行为,默认什么都不执行,子类可覆盖执行其特有的行为
        onChange(session);
    }
    
    protected void onChange(Session s) {
    }

    DefaultSessionManager具体执行Session更新时的行为,SessionDao负责更新介质中的Session

    protected void onChange(Session session) {
        sessionDAO.update(session);
    }

    书接前文#3

    在开启Session的过程中执行一些行为

    protected void onStart(Session session, SessionContext context) {
    }

    DefaultWebSessionManager在开启Session中创建了Cookie,并在Session中存储了一些内容

    protected void onStart(Session session, SessionContext context) {
        super.onStart(session, context);
    
        if (!WebUtils.isHttp(context)) {
            log.debug("SessionContext argument is not HTTP compatible or does not have an HTTP request/response " +
                    "pair. No session ID cookie will be set.");
            return;
    
        }
        HttpServletRequest request = WebUtils.getHttpRequest(context);
        HttpServletResponse response = WebUtils.getHttpResponse(context);
    
        if (isSessionIdCookieEnabled()) {
            Serializable sessionId = session.getId();
            storeSessionId(sessionId, request, response);
        } else {
            log.debug("Session ID cookie is disabled.  No cookie has been set for new session with id {}", session.getId());
        }
    
        request.removeAttribute(ShiroHttpServletRequest.REFERENCED_SESSION_ID_SOURCE);
        request.setAttribute(ShiroHttpServletRequest.REFERENCED_SESSION_IS_NEW, Boolean.TRUE);
    }

    书接前文#4

    protected void notifyStart(Session session) {
        for (SessionListener listener : this.listeners) {
            listener.onStart(session);
        }
    }

    书接前文#5

    protected Session createExposedSession(Session session, SessionContext context) {
        return new DelegatingSession(this, new DefaultSessionKey(session.getId()));
    }

    DelegatingSession中具备了NativeSessionManager(SessionManager管理器创建的Session中又包含了SessionManager管理器),Session获得过期时间的过程是这样的:Session.getTimeout() ==> sessionManager.getTimeout(sessionKey) ==> 去Redis或者什么地方获得Session ==> redisSession.getTimeout()

    public DelegatingSession(NativeSessionManager sessionManager, SessionKey key) {
        if (sessionManager == null) {
            throw new IllegalArgumentException("sessionManager argument cannot be null.");
        }
        if (key == null) {
            throw new IllegalArgumentException("sessionKey argument cannot be null.");
        }
        if (key.getSessionId() == null) {
            String msg = "The " + DelegatingSession.class.getName() + " implementation requires that the " +
                    "SessionKey argument returns a non-null sessionId to support the " +
                    "Session.getId() invocations.";
            throw new IllegalArgumentException(msg);
        }
        this.sessionManager = sessionManager;
        this.key = key;
    }

    具体实现SessionManager的行为之 Session getSession(SessionKey key);

    public Session getSession(SessionKey key) throws SessionException {
        // 根据Session的key查找Session(如在Redis介质中查找)
        Session session = lookupSession(key);
        // 如果Session存在就包装Session,最终要实现的Session可以存储在除了内存外的其他介质中(如Redis)
        return session != null ? createExposedSession(session, key) : null;
    }
    
    private Session lookupSession(SessionKey key) throws SessionException {
        if (key == null) {
            throw new NullPointerException("SessionKey argument cannot be null.");
        }
        return doGetSession(key);
    }
    
    // AbstractNativeSessionManager本身没有查询Session的职能,只能抽象化
    protected abstract Session doGetSession(SessionKey key) throws InvalidSessionException;

    AbstractValidatingSessionManager又来插一脚发挥其特性,校验Session,其本身也没有查询Session的职能,只能抽象化

    protected final Session doGetSession(final SessionKey key) throws InvalidSessionException {
        // 如果有必要的话对Session进行有效性校验
        enableSessionValidationIfNecessary();
    
        log.trace("Attempting to retrieve session with key {}", key);
    
        // 根据Session的key检索Session
        Session s = retrieveSession(key);
        if (s != null) {
            // 校验Session
            validate(s, key);
        }
        return s;
    }
    
    // AbstractValidatingSessionManager本身没有查询Session的职能,只能抽象化
    protected abstract Session retrieveSession(SessionKey key) throws UnknownSessionException;

    DefaultSessionManager有SessionDao,查询Session这个事只能是他来做

    protected Session retrieveSession(SessionKey sessionKey) throws UnknownSessionException {
        // 获得Session的主键(如Redis的key)
        Serializable sessionId = getSessionId(sessionKey);
        if (sessionId == null) {
            log.debug("Unable to resolve session ID from SessionKey [{}].  Returning null to indicate a " +
                    "session could not be found.", sessionKey);
            return null;
        }
        // 从数据源中检索Session
        Session s = retrieveSessionFromDataSource(sessionId);
        if (s == null) {
            //session ID was provided, meaning one is expected to be found, but we couldn't find one:
            String msg = "Could not find session with ID [" + sessionId + "]";
            throw new UnknownSessionException(msg);
        }
        return s;
    }
    
    protected Serializable getSessionId(SessionKey sessionKey) {
        return sessionKey.getSessionId();
    }
    
    protected Session retrieveSessionFromDataSource(Serializable sessionId) throws UnknownSessionException {
        return sessionDAO.readSession(sessionId);
    }

    具体实现NativeSessionManager的行为之 Date getStartTimestamp(SessionKey key);

    我们先来看DelegatingSession的构造方法,DelegatingSession构造时注入了NativeSessionManager和SessionKey

    public DelegatingSession(NativeSessionManager sessionManager, SessionKey key) {
        if (sessionManager == null) {
            throw new IllegalArgumentException("sessionManager argument cannot be null.");
        }
        if (key == null) {
            throw new IllegalArgumentException("sessionKey argument cannot be null.");
        }
        if (key.getSessionId() == null) {
            String msg = "The " + DelegatingSession.class.getName() + " implementation requires that the " +
                    "SessionKey argument returns a non-null sessionId to support the " +
                    "Session.getId() invocations.";
            throw new IllegalArgumentException(msg);
        }
        this.sessionManager = sessionManager;
        this.key = key;
    }

    DelegatingSession的 getStartTimestamp()方法

    public Date getStartTimestamp() {
        if (startTimestamp == null) {
            // 这件事DelegatingSession本身没有这个职能,只能交给SessionManager去做
            startTimestamp = sessionManager.getStartTimestamp(key);
        }
        return startTimestamp;
    }

    NativeSessionManager的 getStartTimestamp(SessionKey key)方法

    public Date getStartTimestamp(SessionKey key) {
        return lookupRequiredSession(key).getStartTimestamp();
    }
    
    private Session lookupRequiredSession(SessionKey key) throws SessionException {
        // 参见上述,根据Session的key获得Session(如去Redis介质中查找),并不像getSession(SessionKey key)那样对Session进行包装
        Session session = lookupSession(key);
        if (session == null) {
            String msg = "Unable to locate required Session instance based on SessionKey [" + key + "].";
            throw new UnknownSessionException(msg);
        }
        return session;
    }

    SimpleSession中具备了关乎于Session的各种信息他的 getStartTimestamp()方法

    public Date getStartTimestamp() {
        return startTimestamp;
    }
  • 相关阅读:
    观察者模式
    如何通过反射创建对象?
    java8新特性
    idea 常用快捷键--标蓝
    java多线程基础篇-01
    zookeeper单机版及操作
    redis和jedis常用api
    Mac连接服务器
    redis基本介绍及安装01
    docker 安装mobsf及部分命令01
  • 原文地址:https://www.cnblogs.com/BINGJJFLY/p/9267352.html
Copyright © 2011-2022 走看看