Spring Session使用筆記


簡介

解決web服務集群session共享問題,原理不做介紹!

基本原理

  1. 過濾器(SessionRepositoryFilter),過濾請求。
  2. 繼承servlet接口,對request、response進行封裝擴展,重寫session相關方法。

使用

pom依賴

<dependency>
  <groupId>org.springframework.session</groupId>
  <artifactId>spring-session-data-redis</artifactId>
  <version>1.3.0.RELEASE</version>
  <type>pom</type>
  <exclusions>
      <exclusion>
          <groupId>org.springframework</groupId>
          <artifactId>*</artifactId>
      </exclusion>
  </exclusions>
</dependency>

jar版本適配問題個人解決。

spring-session.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:util="http://www.springframework.org/schema/util"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
						http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.1.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">

    <context:annotation-config/>

    <bean class="org.springframework.session.data.redis.config.annotation.web.http.RedisHttpSessionConfiguration">
        <!--session 有效期,時間單位:秒-->
        <property name="maxInactiveIntervalInSeconds" value="1800"/>
        <!--spring session key 命名前綴,用於項目區分-->
        <property name="redisNamespace" value="project"/>
    </bean>
    
    <bean id="jedisPoolConfig" class="redis.clients.jedis.JedisPoolConfig">
        <!--資源池中最大連接數-->
        <property name="maxTotal" value="20" />
        <!--資源池允許最大空閑的連接數-->
        <property name="maxIdle" value="20" />
        <!--資源池確保最少空閑的連接數-->
        <property name="minIdle" value="5"/>
        <!--當資源池用盡后,調用者是否要等待。只有當為true時,下面的maxWaitMillis才會生效-->
        <property name="blockWhenExhausted" value="true"/>
        <!--當資源池連接用盡后,調用者的最大等待時間(單位為毫秒)-->
        <property name="maxWaitMillis" value="1000"/>
        <!--向資源池借用連接時是否做連接有效性檢測(ping),無效連接會被移除-->
        <property name="testOnBorrow" value="false"/>
        <!--向資源池歸還連接時是否做連接有效性檢測(ping),無效連接會被移除-->
        <property name="testOnReturn" value="false"/>
        <!--是否開啟空閑資源監測-->
        <property name="testWhileIdle" value="true"/>
        <!--空閑資源的檢測周期(單位為毫秒)-->
        <property name="timeBetweenEvictionRunsMillis" value="30000"/>
        <!--資源池中資源最小空閑時間(單位為毫秒),達到此值后空閑資源將被移除-->
        <property name="minEvictableIdleTimeMillis" value="60000"/>
        <!--做空閑資源檢測時,每次的采樣數, -1:所有-->
        <property name="numTestsPerEvictionRun" value="-1"/>
    </bean>
    
    <!--redis connection配置-->
    <bean id="jedisConnectionFactory" class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory" destroy-method="destroy">
        <property name="hostName" value="#{config['redis.host']}"/>
        <property name="port" value="#{config['redis.port']}"/>
        <property name="database" value="#{config['redis.db.session']}"/>
        <property name="timeout" value="3000"/>
        <property name="usePool" value="true"/>
        <property name="poolConfig" ref="jedisPoolConfig"/>
    </bean>

    <!-- 讓Spring Session不再執行config命令 -->
    <util:constant static-field="org.springframework.session.data.redis.config.ConfigureRedisAction.NO_OP"/>
</beans>

web.xml配置

<filter>
    <filter-name>CharacterEncodingFilter</filter-name>
    <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
    <init-param>
        <param-name>encoding</param-name>
        <param-value>utf-8</param-value>
    </init-param>
</filter>
<filter-mapping>
    <filter-name>CharacterEncodingFilter</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>
<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>
   <dispatcher>REQUEST</dispatcher>
   <dispatcher>ERROR</dispatcher>
</filter-mapping>

<filter>
   <filter-name>requestContextFilter</filter-name>
   <filter-class>org.springframework.web.filter.RequestContextFilter</filter-class>
</filter>
<filter-mapping>
   <filter-name>requestContextFilter</filter-name>
   <url-pattern>/*</url-pattern>
</filter-mapping>

過濾器的順序問題:

  1. CharacterEncodingFilter,設置請求編碼。否則可能產生中文亂碼問題。
  2. springSessionRepositoryFilter,spring session 過濾器,攔截所有請求。
  3. requestContextFilter,如項目中存在直接注入 request的情況,需設置,否則 request 中獲取到的session不可用。

FindByIndexNameSessionRepository

使用 springsecurtiy 的項目,spring session 會保存用戶名下所有的會話ID。該key在用戶主動退出時會刪除,但自動過期的情況下沒有做清理,會導致冗余垃圾數據的產生。
解決方法:

redis-cli config set notify-keyspace-events Egx

開啟redis的keyspace事件。
或者定時掃描清理

注意事項

  1. session中存儲的對象需要可序列化。
  2. 過濾器順序問題
  3. spring:session:index:org.springframework.session.FindByIndexNameSessionRepository.PRINCIPAL_NAME_INDEX_NAME:* 的問題


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM