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:* 的问题

猜你喜欢

转载自www.cnblogs.com/wowblog/p/9367291.html