使用Spring Session和Redis解決分散式Session跨域共享問題
現象闡述:
在專案中前後端程式碼未做分離,在兩個實例的情況下服務正常運行偶爾會彈出類似需要重新登錄的提示,後台報錯信息
這是處理器異常 原因並不明顯
增加機器實例後,在訪問前端頁面的時候,一直重複訪問登錄頁面,導致頁面302,種種跡象表明是登錄配置的問題引起的。
相關專題推薦:php session (包含圖文、影片、案例)
問題引入:Session不能共享導致不同機器之間輪詢要求登入導致最終的服務異常
解決方案:使用Spring Session和Redis解決分散式Session跨域共享問題
解決設定:
1 )新增依賴
<dependency> <groupId>org.springframework.session</groupId> <artifactId>spring-session-data-redis</artifactId> <version>1.2.0.RELEASE</version> </dependency> <dependency> <groupId>org.apache.velocity</groupId> <artifactId>velocity</artifactId> <version>1.7</version> </dependency>
2 )web.xml設定檔新增:
<!-- 分布式Session共享Filter --> <filter> <filter-name>springSessionRepositoryFilter</filter-name> <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class> </filter> <filter-mapping> <filter-name>springSessionRepositoryFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>
3) Spring.xml的設定
<!-- 将session放入redis --> <context:annotation-config/> <bean id="redisHttpSessionConfiguration" class="org.springframework.session.data.redis.config.annotation.web.http.RedisHttpSessionConfiguration"> <property name="maxInactiveIntervalInSeconds" value="120" /> </bean> <bean class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory"> <!-- redis 配置 --> <property name="hostName" value="192.168.0.48" /> <property name="port" value="6379" /> </bean>
解析:
1、web中DelegatingFilterProxy 類別:屬於代理fiter,它會在tomcat啟動後開始載入在。的方式將springSessionRepositoryFilter注入到容器中
3、
SessionRepositoryFilter這個過濾器就是前邊DelegatingFilterProxy尋找的過濾器SessionRepositoryFilter是關鍵,具體怎麼關聯起來的呢?如果未指定init-param參數的話,DelegatingFilterProxy就會把filter-name作為要查找的Bean對象,這也是DelegatingFilterProxy類別的作用。可以看出每一個請求都會經過該filter,經過該filter的請求也會相應的經過springSessionRepositoryFilter這個過濾器,那麼我們就接著看一下
這個過濾器 4、
的作用就是替換容器預設的javax.servlet.http.HttpSession支援為org.springframework.session.Session
。 SessionRepositoryFilter的主要方法與屬性如下:
5、其中
SessionRepositoryResponseWrapper、SessionRepositoryRequestWrapper
、# #HttpSessionWrapper
為內部類,這個也是很關鍵的。例如SessionRepositoryRequestWrapper類別
6、因為SessionRepositoryRequestWrapper實作了HttpServletRequestWrapper,而HttpServletRequestWrapper實作了HttpServletRequest接口,在SessionRepositoryRequestWrapper又重寫了HttpServletRequest接口,在SessionRepositoryRequestWrapper又重寫了HttpServletRequestp.方法。到此,我們應該大致明白了,原有的request請求和response都被重新進行了包裝。我們也就明白了原有的HttpSeesion是如何被Spring Session替換掉的。
我們透過快速鍵查看request.getSession() 的具體實現,就可以看出已經有了SessionRepositoryRequestWrapper 重寫的方法。上述有兩個預設的實現,一個是原始的,一個是Spring Session實現的,具體選用哪一種作為實現,這就是我們上邊說的DelegatingFilterProxy 代理的作用了,他會將每一個請求過濾,經過DelegatingFilterProxy的每一個請求也會經過springSessionRepositoryFilter過濾器,springSessionRepositoryFilter過濾器就實現了將原有request到SessionRepositoryRequestWrapper的轉換,這就是實現了具體的流程!
request.getSession().setAttribute(name, value)
的實作: 追蹤程式碼,可以到達下邊內容
##可以看到有Redis相關的操作!至此,我們應該清楚了,Spring Session的工作原理了!雖然下邊的過程沒有再去介紹,但已經很清楚的理解了。
相關學習推薦:
以上是學習Spring Session和Redis解決分散式Session跨域共享問題的詳細內容。更多資訊請關注PHP中文網其他相關文章!