springboot集成shiro使用ehcache的会话管理的完美实现方案

ehcache配置文件:

要想让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 listeners = new ArrayList();
        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。

因此检查线程的时间配置不能过大,也不能太小,太小会增加服务器压力,个人觉得一般几分钟就可以了

你可能感兴趣的:(java,SpringBoot,session,java,shiro)