SpringSession集群与单节点间的切换
- 最近项目需要上分布式环境,首先第一步需要解决Session在多个服务器之间的共享问题,这里我选择了SpringSession,Spring在EE中目前还是主流框架,Spring既然对我的需求有所支持,那选SpringSession,必然是顺理成章。我在这里只记录遇到的集群和单节点切换问题,配置什么的就不在多叙述了,相信csdn上有很多大家需要的教程
基本配置
- SpringSession 有很多支持,比如redis、mongodb、jdbc 等等,这里我使用的是redis
Maven依赖
<properties>
<spring-session.version>1.2.1.RELEASE</spring-session.version>
<lettuce.version>3.5.0.Final</lettuce.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.session</groupId>
<artifactId>spring-session-data-redis</artifactId>
<version>${spring-session.version}</version>
<type>pom</type>
</dependency>
<dependency>
<groupId>biz.paluch.redis</groupId>
<artifactId>lettuce</artifactId>
<version>${lettuce.version}</version>
</dependency>
</dependencies>
目录及配置文件
- 我对于集群和单节点环境分别新建了两个配置文件 - distributed与single 在 resources/env 包下
- spring-session.xml中配置如下
- session-redis.properties 的配置文件如下
- resources/env/distributed/spring/env.properties 内容
- resources/env/single/spring/env.properties 内容
对于上述配置,我解释一下,我需要用Maven在打war包时指定环境,单节点环境或者是集群环境,集群环境需要配置redis,并且添加SpringSession的Filter至web.xml中(后面介绍), 上面的env.properties 是为后面切换环境做的配置。
我在env 包下的distributed 与 single 包下都创建了spring文件夹,是因为后面使用maven配置环境的时候,把这些文件都最后都输出都resources/spring文件夹下,因为我web.xml中读取spring文件的配置是这样的
这样spring-session文件最后就会输出到spring文件夹下,spring在初始化时才可以读到
添加SpringSession 的Filter
- 这里注意:在网上看到很多教程,是在web.xml中添加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>
<dispatcher>REQUEST</dispatcher>
<dispatcher>ERROR</dispatcher>
</filter-mapping>
-
但是这样添加filter,需要切换到单节点环境的时候,你没办法在web.xml中控制加不加在这个filter。原先我想使用Servlet3.0的新特性—— 模块化,即web-fragment将此filter打成jar包再通过maven的profile 通过不同环境判断是否加载这个jar包,但是SpringSession的这个Filter 比较难搞的一点就在于它需要在Filter 执行链的第一位,一般在web.xml中filter的执行顺序是由filter声明靠前靠后来控制的,现在通过fragment引进来之后,没办法控制SpringSession的Filter在第一个了,除非我将项目中其他所有的filter 弄出去整一个jar包,引两个fragment进来,指定fragment的执行顺序,但是一个大的项目,很显然filter中的代码可能关联很多其他的地方,不好都弄出来整一个jar包,所以这个方案行不通。
而后,又看到Servlet3.0中可以动态addFilter ,经过三翻四次的采坑后,终于得以落地实现 -
Environment 类
-
@Value("${env.open.distributed}") 是读取上面 resources/env/(distributed或single)/spring/env.properties 中配置的内容,前提是需要在spring配置文件中配置properties位置
注意:如果做了如下配置。则spring-session中加载properties那一段需要注释掉!
-
写个监听器,动态添加Filter , 注意SpringSession 的Filter必须第一个添加;我这里是判断哪个环境下的配置文件,从而判断是否需要动态添加SpringSession的Filter 代码如下
Maven 多环境配置
- 上述我们创建了两个环境—— distributed 及 single 环境,maven中配置如下
<profiles>
<!-- 集群环境 -->
<profile>
<id>distributed</id>
<properties>
<env.active>distributed</env.active>
</properties>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
</profile>
<!-- 单节点环境 -->
<profile>
<id>single</id>
<properties>
<env.active>single</env.active>
</properties>
</profile>
</profiles>
<build>
<finalName>Distributed-Branch</finalName>
<resources>
<resource>
<!-- 资源根目录排除各环境的配置 -->
<directory>src/main/resources</directory>
<excludes>
<exclude>**/env/**</exclude>
</excludes>
</resource>
<resource>
<directory>src/main/resources/env/${env.active}</directory>
</resource>
</resources>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.5.1</version>
<configuration>
<source>1.7</source>
<target>1.7</target>
</configuration>
</plugin>
</plugins>
</build>
- 这样我们就可以通过修改
\<activation>\<activeByDefault>true\</activeByDefault>\</activation>
来修改环境了,不同的环境加载不同的配置文件,实现了集群和节点切换控制SpringSession是否加载,以及是否加载Spring-Redis配置文件 !