Spring Session 學習記錄1

先寫些廢話

  新公司項目是有用到redis,以前老公司使用的緩存框架是ehcache.我redis並不熟悉.看過介紹之後知道是個nosql..既然是個數據庫,那我想操做方法和jdbc操做關係數據庫應該差很少吧..百度了一些例子之後發現確實差很少...好比注入一個spring的template之後使用template就好了. 好比:web

  很好理解,使用也蠻簡單..就像jdbcTemplate...redis

  一次偶然的調試,我發現了一個有趣的地方(公司用的是本身的框架,封裝了springboot...因此啓動默認配置了什麼bean,很難看出來...)...spring

我記得session在tomcat啓動服務器的時候好像是XXXSessionFacade..這裏倒是和Redis相關的一個實現類..而後向這個session存進去的東西再redis裏也能夠找到.sql

這說明這個session數據存取都是向redis去操做的.數據庫

看來一下maven的POM文件發現公司的項目依賴於srping-session-data-redis這個框架.緩存

 

Spring整合SpringSession

實驗了一下,發現其實spring只要額外配置2個bean就能夠集成springsession了.tomcat

    <context:annotation-config />
     <bean class="org.springframework.session.data.redis.config.annotation.web.http.RedisHttpSessionConfiguration">
    </bean> 

    <bean id="jedisConnectionFactory" class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory">
        <property name="hostName" value="10.86.87.173" />
        <property name="password" value="mesRedis+)" />
    </bean>

稍微研究了下發現JedisConnectionFactory這個bean就是配置了Spring怎麼經過jedis去鏈接redis服務器.springboot

RedisHttpSessionConfiguration這個bean是真正和session相關的,它自己類上有註解@Configuration和@EnableScheduling.
服務器

@Configuration配合它方法上的@Bean能夠配置一些其餘的bean,好比SessionRepositoryFilter 就配置了一個bean,對應web.xmlXML裏配置的那個filter...session

@EnableScheduling這個註解我沒用過,估計是要定時作一些事情,好比session過時了要去redis刪除數據吧(可是redis好像也有超時刪除數據的功能,爲啥還要這麼作呢..redis和Springsession都是第一次用,不太瞭解)..

除了上面2個bean,只要在web.xml裏配置一個filter就好了.

1     <filter>
2         <filter-name>springSessionRepositoryFilter</filter-name>
3         <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
4     </filter>
5     <filter-mapping>
6         <filter-name>springSessionRepositoryFilter</filter-name>
7         <url-pattern>/*</url-pattern>
8     </filter-mapping>

 

原理

由於第一次用,不少代碼都沒看過,因此不必定對.我以爲原理是這樣的:

1.RedisHttpSessionConfiguration裏會配置一個filter

    @Bean
    public <S extends ExpiringSession> SessionRepositoryFilter<? extends ExpiringSession> springSessionRepositoryFilter(SessionRepository<S> sessionRepository, ServletContext servletContext) {
        SessionRepositoryFilter<S> sessionRepositoryFilter = new SessionRepositoryFilter<S>(sessionRepository);
        sessionRepositoryFilter.setServletContext(servletContext);
        if(httpSessionStrategy != null) {
            sessionRepositoryFilter.setHttpSessionStrategy(httpSessionStrategy);
        }
        return sessionRepositoryFilter;
    }

注入一個sessionRepository.這個repository其實就是redis的repository.只是哪裏生成的我並不知道...

    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
        request.setAttribute(SESSION_REPOSITORY_ATTR, sessionRepository);

        SessionRepositoryRequestWrapper wrappedRequest = new SessionRepositoryRequestWrapper(request, response, servletContext);
        SessionRepositoryResponseWrapper wrappedResponse = new SessionRepositoryResponseWrapper(wrappedRequest,response);

        HttpServletRequest strategyRequest = httpSessionStrategy.wrapRequest(wrappedRequest, wrappedResponse);
        HttpServletResponse strategyResponse = httpSessionStrategy.wrapResponse(wrappedRequest, wrappedResponse);

        try {
            filterChain.doFilter(strategyRequest, strategyResponse);
        } finally {
            wrappedRequest.commitSession();
        }
    }

這個filter會把request和response外面包裝一層,就是裝飾着模式.當調用request的getSession的時候

        @Override
        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());
                    currentSession.setNew(false);
                    setCurrentSession(currentSession);
                    return currentSession;
                }
            }
            if(!create) {
                return null;
            }
            S session = sessionRepository.createSession();
            currentSession = new HttpSessionWrapper(session, getServletContext());
            setCurrentSession(currentSession);
            return currentSession;
        }

實際上是從sessionRepository裏去拿session的.因此咱們使用的HttpSession的實現類應該是 HttpSessionWrapper 裏面包裹着 RedisSession.

 1     private RedisSession getSession(String id, boolean allowExpired) {
 2         Map<Object, Object> entries = getSessionBoundHashOperations(id).entries();
 3         if(entries.isEmpty()) {
 4             return null;
 5         }
 6         MapSession loaded = new MapSession();
 7         loaded.setId(id);
 8         for(Map.Entry<Object,Object> entry : entries.entrySet()) {
 9             String key = (String) entry.getKey();
10             if(CREATION_TIME_ATTR.equals(key)) {
11                 loaded.setCreationTime((Long) entry.getValue());
12             } else if(MAX_INACTIVE_ATTR.equals(key)) {
13                 loaded.setMaxInactiveIntervalInSeconds((Integer) entry.getValue());
14             } else if(LAST_ACCESSED_ATTR.equals(key)) {
15                 loaded.setLastAccessedTime((Long) entry.getValue());
16             } else if(key.startsWith(SESSION_ATTR_PREFIX)) {
17                 loaded.setAttribute(key.substring(SESSION_ATTR_PREFIX.length()), entry.getValue());
18             }
19         }
20         if(!allowExpired && loaded.isExpired()) {
21             return null;
22         }
23         RedisSession result = new RedisSession(loaded);
24         result.originalLastAccessTime = loaded.getLastAccessedTime() + TimeUnit.SECONDS.toMillis(loaded.getMaxInactiveIntervalInSeconds());
25         result.setLastAccessedTime(System.currentTimeMillis());
26         return result;
27     }
View Code
 1         @Override
 2         public HttpSession getSession(boolean create) {
 3             HttpSessionWrapper currentSession = getCurrentSession();
 4             if(currentSession != null) {
 5                 return currentSession;
 6             }
 7             String requestedSessionId = getRequestedSessionId();
 8             if(requestedSessionId != null) {
 9                 S session = sessionRepository.getSession(requestedSessionId);
10                 if(session != null) {
11                     this.requestedSessionIdValid = true;
12                     currentSession = new HttpSessionWrapper(session, getServletContext());
13                     currentSession.setNew(false);
14                     setCurrentSession(currentSession);
15                     return currentSession;
16                 }
17             }
18             if(!create) {
19                 return null;
20             }
21             S session = sessionRepository.createSession();
22             currentSession = new HttpSessionWrapper(session, getServletContext());
23             setCurrentSession(currentSession);
24             return currentSession;
25         }
View Code

相關文章
相關標籤/搜索