传统的session是维护在内存中的,如果部署多个服务,通过ngix转发,用户登录完成后的请求可能转发到另外一个服务上去,内存中就没有用户的session,就会判定为用户没有登录,spring-session项目可以把session维护到redis等数据库中,这样多个服务可以共用session,就可以解决上面遇到的问题。下面就用redis保存session示例。

需要添加的依赖

<dependency>
<groupId>org.springframework.session</groupId>
<artifactId>spring-session-core</artifactId>
<version>2.0.2.RELEASE</version>
</dependency>
<!-- 缓存 -->
<dependency>
<groupId>org.redisson</groupId>
<artifactId>redisson</artifactId>
<version>${redisson.version}</version>
</dependency>
<dependency>
<groupId>com.esotericsoftware</groupId>
<artifactId>kryo</artifactId>
<version>4.0.2</version>
</dependency>

配置连接redis

文件名为applicationContext-cache-single.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:redisson="http://redisson.org/schema/redisson"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://redisson.org/schema/redisson http://redisson.org/schema/redisson/redisson.xsd">

<!--使用kryo序列化方式-->
<bean id="kryoCodec" class="org.redisson.codec.KryoCodec"/>

<redisson:client id="redissonClient" codec-ref="kryoCodec">
<redisson:single-server address="redis://127.0.0.1:6379"/>
</redisson:client>
</beans>

配置相关bean

<import resource="classpath:applicationContext-cache-single.xml"/>

<!-- session交给redis管理 -->
<bean id="redissonHttpSessionConfiguration"
class="org.redisson.spring.session.config.RedissonHttpSessionConfiguration">
<property name="maxInactiveIntervalInSeconds" value="1800"/>
</bean>
<!--这个是设置cookie保存的位置,需要不同服务指定成一样的,不然无法公用cookie-->
<bean id="defaultCookieSerializer" class="org.springframework.session.web.http.DefaultCookieSerializer">
<property name="cookieName" value="GARDPAY_SESSION_ID"/>
<property name="cookiePath" value="/"/>
</bean>

这里只是初始化了一些相关配置,真正能够把session,从请求中找出,保存到数据库中需要通过过滤器实现

过滤器配置

<!-- spring-session过滤器 -->
<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>

这里的DelegatingFilterProxy是一个代理过滤器,真正的过滤器是springSessionRepositoryFilter,这个过滤器是我们创建redissonHttpSessionConfiguration这个bean的时候这个bean内部生产的。

测试

@GetMapping("/put.pub")
public Map<String, String> put(HttpServletRequest request) {
request.getSession().setAttribute("aaa", "占旭鹏");
Map<String, String> map = new HashMap<>();
map.put("success", "成功");
return map;
}

@GetMapping("/get.pub")
public Map<String, Object> get(HttpServletRequest request) {
Object result = request.getSession().getAttribute("aaa");
Map<String, Object> map = new HashMap<>();
map.put("aaa", result);
return map;
}

把项目放在两个端口下跑起来,一个端口put数据,两个端口下都可以取到,说明已经session共享成功了