Shiro AbstractValidatingSessionManager设计概念
AbstractValidatingSessionManager具体实现了ValidatingSessionManager的行为,覆盖AbstractNativeSessionManager的行为,定义抽象行为
具备了SessionValidationScheduler(Session校验任务调度器,set注入方式)、sessionValidationSchedulerEnabled(Session校验任务调度器开关,set注入方式,默认开启);
// 如果有必要的话开启Session校验 private void enableSessionValidationIfNecessary() { SessionValidationScheduler scheduler = getSessionValidationScheduler(); // Session校验开关开启并且Session校验任务调度器为空或者是不可用 if (isSessionValidationSchedulerEnabled() && (scheduler == null || !scheduler.isEnabled())) { // 开启Session校验 enableSessionValidation(); } }
开启Session校验
protected synchronized void enableSessionValidation() { SessionValidationScheduler scheduler = getSessionValidationScheduler(); if (scheduler == null) { // 创建Session校验任务调度器,后文详解#1 scheduler = createSessionValidationScheduler(); // 为AbstractValidatingSessionManager设置Session校验任务调度器 setSessionValidationScheduler(scheduler); } // 可能Session校验任务调度器已经被创建只不过还没有启用 if (!scheduler.isEnabled()) { if (log.isInfoEnabled()) { log.info("Enabling session validation scheduler..."); } // 启用Session校验任务调度器,后文详解#2 scheduler.enableSessionValidation(); // 启用Session校验任务调度器后需要做的事情 afterSessionValidationEnabled(); } } // 一个空的方法,等待覆盖 protected void afterSessionValidationEnabled() { }
书接前文#1
protected SessionValidationScheduler createSessionValidationScheduler() { ExecutorServiceSessionValidationScheduler scheduler; if (log.isDebugEnabled()) { log.debug("No sessionValidationScheduler set. Attempting to create default instance."); } // SessionValidationScheduler注入AbstractValidatingSessionManager scheduler = new ExecutorServiceSessionValidationScheduler(this); // 设置任务调度器的时间间隔,默认60分钟 scheduler.setInterval(getSessionValidationInterval()); if (log.isTraceEnabled()) { log.trace("Created default SessionValidationScheduler instance of type [" + scheduler.getClass().getName() + "]."); } return scheduler; }
书接前文#2
import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.ThreadFactory; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicInteger; private ScheduledExecutorService service; public void enableSessionValidation() { if (this.interval > 0l) { this.service = Executors.newSingleThreadScheduledExecutor(new ThreadFactory() { private final AtomicInteger count = new AtomicInteger(1); public Thread newThread(Runnable r) { Thread thread = new Thread(r); thread.setDaemon(true); thread.setName(threadNamePrefix + count.getAndIncrement()); return thread; } }); this.service.scheduleAtFixedRate(this, interval, interval, TimeUnit.MILLISECONDS); } this.enabled = true; } public void run() { if (log.isDebugEnabled()) { log.debug("Executing session validation..."); } long startTime = System.currentTimeMillis(); // ValidatingSessionManager执行校验Session的任务 this.sessionManager.validateSessions(); long stopTime = System.currentTimeMillis(); if (log.isDebugEnabled()) { log.debug("Session validation completed successfully in " + (stopTime - startTime) + " milliseconds."); } }
校验所有有效的Session
public void validateSessions() { if (log.isInfoEnabled()) { log.info("Validating all active sessions..."); } int invalidCount = 0; // 获得所有有效的Session,从其他介质中获得(如Redis) Collection<Session> activeSessions = getActiveSessions(); if (activeSessions != null && !activeSessions.isEmpty()) { for (Session s : activeSessions) { try { SessionKey key = new DefaultSessionKey(s.getId());
// 执行具体的校验任务 validate(s, key); } catch (InvalidSessionException e) { if (log.isDebugEnabled()) { boolean expired = (e instanceof ExpiredSessionException); String msg = "Invalidated session with id [" + s.getId() + "]" + (expired ? " (expired)" : " (stopped)"); log.debug(msg); } invalidCount++; } } } if (log.isInfoEnabled()) { String msg = "Finished session validation."; if (invalidCount > 0) { msg += " [" + invalidCount + "] sessions were stopped."; } else { msg += " No sessions were stopped."; } log.info(msg); } } // 空方法,AbstractValidatingSessionManager本身是没有这个职能的只能交给子类去实现,待子类覆盖 protected abstract Collection<Session> getActiveSessions();
具体的校验任务
protected void validate(Session session, SessionKey key) throws InvalidSessionException { try { // Session为基础Session:SimpleSession doValidate(session); } catch (ExpiredSessionException ese) { onExpiration(session, ese, key); throw ese; } catch (InvalidSessionException ise) { onInvalidation(session, ise, key); throw ise; } } protected void doValidate(Session session) throws InvalidSessionException { if (session instanceof ValidatingSession) { // 面向对象,只有Session自己能校验自己是否过期了(类似于门把自己关上了) ((ValidatingSession) session).validate(); } else { String msg = "The " + getClass().getName() + " implementation only supports validating " + "Session implementations of the " + ValidatingSession.class.getName() + " interface. " + "Please either implement this interface in your session implementation or override the " + AbstractValidatingSessionManager.class.getName() + ".doValidate(Session) method to perform validation."; throw new IllegalStateException(msg); } }