ehcache配置文件:
<defaultCache
maxEntriesLocalHeap="0"
eternal="true"
timeToIdleSeconds="0"
timeToLiveSeconds="0"
overflowToDisk="false"
diskPersistent="false"
/>
要想让Shiro的SessionManager完全管理和控制会话的缓存,最好将缓存设置成永不过期。
但是SessionManager的配置要注意,不然很可能会造成内存溢出。因为如果用户不主动点击退出登录,而是将浏览器关闭或者清理浏览器cookie后,用户会话会丢失,这些异常的会话关闭方式会让缓存中的无效session越来越多,最终导致内存溢出。需要按照如下
@Bean(name = "sessionManager")
public DefaultWebSessionManager sessionManager(EhCacheManager ehCacheManager,SimpleCookie sessionIdCookie) {
DefaultWebSessionManager sessionManager = new DefaultWebSessionManager();
// 设置session过期时间3600s
//sessionManager.setGlobalSessionTimeout(3600000L);
sessionManager.setSessionIdUrlRewritingEnabled(false);
sessionManager.setDeleteInvalidSessions(true);
sessionManager.setCacheManager(ehCacheManager);
Collection<SessionListener> listeners = new ArrayList<SessionListener>();
listeners.add(new MySessionListener());
sessionManager.setSessionListeners(listeners);
sessionManager.setSessionValidationSchedulerEnabled(false);
sessionManager.setSessionIdCookieEnabled(true);
//会话超时时间,默认30分钟
int sessionOut = PropertyUtil.getIntegerValue("app.properties","session.timeout",30);
int sessionTTl = PropertyUtil.getIntegerValue("app.properties","session.check_ttl",180);
LOGGER.info("会话超时时间:"+sessionOut+"分钟");
sessionManager.setGlobalSessionTimeout(sessionOut*60000);
sessionManager.setSessionDAO(sessionDAO());
//定时清理失效会话, 清理用户直接关闭浏览器造成的孤立会话
sessionManager.setSessionValidationInterval(sessionTTl * 1000);
sessionManager.setSessionValidationSchedulerEnabled(true);
sessionManager.setDeleteInvalidSessions(true);
sessionManager.setSessionIdCookieEnabled(true);
sessionManager.setSessionIdCookie(sessionIdCookie);
return sessionManager;
}
其中setGlobalSessionTimeout方法设置的是全局会话超时时间,单位为毫秒,我这里默认的是30分钟,即无操作30分钟后会话超时。
另外我们需要配置setSessionValidationInterval来配置session的检查线程,这个线程会定时去检查缓存的session是否过期,过期就会将其清除,这样就避免了内存溢出。setSessionValidationSchedulerEnabled要配置为true,线程才会工作。
检查线程的执行时间要如何配置?
经过我的测试,我将会话超时时间设置为5分钟,检查时间设置为3分钟,然后分别在两个浏览器中登录了,一个浏览器登录创建会话后立即关闭,session就会丢失,在另一个浏览器来观察所有有效的session,我想试试,无操作3分钟后,检查线程是否会立即清除丢失的session。
但是发现3分钟时无效session没有被清除:
但是到6分钟时,session才被清除,因此检查线程清除的只是过期的session,用户关闭浏览器后,session只是丢失,并没有失效,因此不会被SessionManager清理。当超过5分钟时,丢失的session才真正失效,那么检查线程下次执行时才会去清理这个失效session。
因此检查线程的时间配置不能过大,也不能太小,太小会增加服务器压力,个人觉得一般几分钟就可以了