新公司項目是有用到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只要額外配置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 }
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 }