前阵子在公司负责一个云部署项目,因项目之前是个单体服务,所以在集群部署后,pod节点均衡发布,导致系统登录会话在跳转到另一个pod节点时失去session会话。此时,整合spring-session-data-redis可以很好的处理此问题,并且修改代码量少。
一、前期准备
(1)需要依赖(spring版本为4.1.7)
<dependency> <groupId>org.springframework.data</groupId> <artifactId>spring-data-redis</artifactId> <version>1.6.0.RELEASE</version> </dependency> <dependency> <groupId>redis.clients</groupId> <artifactId>jedis</artifactId> <version>2.9.0</version> </dependency> <dependency> <groupId>org.springframework.session</groupId> <artifactId>spring-session</artifactId> <version>1.3.0.RELEASE</version> </dependency> <dependency> <groupId>org.springframework.session</groupId> <artifactId>spring-session-data-redis</artifactId> <version>1.2.0.RELEASE</version> </dependency> |
(2)在web.xml文件中配置spring 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> |
二、spring-redis.xml
在项目的resources文件夹下添加spring-redis.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:context="http://www.springframework.org/schema/context" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.1.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.1.xsd"> <context:property-placeholder location="classpath:/redis.properties" ignore-unresolvable="true"/> <bean class="org.springframework.session.data.redis.config.annotation.web.http.RedisHttpSessionConfiguration"> </bean> <bean id="jedisConnectionFactory" class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory"> <constructor-arg name="sentinelConfig" ref="redisConnectionFactory"/> </bean> <!-- 配置Redis连接池 --> <bean id="jedisPoolConfig" class="redis.clients.jedis.JedisPoolConfig"> <property name="maxTotal" value="100" /> <property name="maxIdle" value="50" /> <property name="minIdle" value="10" /> <property name="testOnBorrow" value="true" /> <property name="testOnReturn" value="true" /> <property name="testWhileIdle" value="true" /> <property name="minEvictableIdleTimeMillis" value="1800000" /> <property name="softMinEvictableIdleTimeMillis" value="10000" /> <property name="timeBetweenEvictionRunsMillis" value="30000" /> <property name="numTestsPerEvictionRun" value="10" /> <property name="blockWhenExhausted" value="true" /> </bean> <!-- 配置Redis哨兵集群连接工厂 --> <bean id="redisConnectionFactory" class="org.springframework.data.redis.connection.RedisSentinelConfiguration"> <property name="master"> <bean class="org.springframework.data.redis.connection.RedisNode"> <property name="name" value="mymaster"></property> </bean> </property> <property name="sentinels"> <set> <bean class="org.springframework.data.redis.connection.RedisNode"> <constructor-arg value="ip" /> <constructor-arg value="26379" /> </bean> <bean class="org.springframework.data.redis.connection.RedisNode"> <constructor-arg value="ip" /> <constructor-arg value="26380" /> </bean> <bean class="org.springframework.data.redis.connection.RedisNode"> <constructor-arg value="ip" /> <constructor-arg value="26381" /> </bean> </set> </property> </bean> </beans> |
注:ip字段填写redis的ip地址
至此,关于ssm框架结合redis哨兵模式已完成,启动项目后,可以查看redis中存储的数据(spring-session-data-redis 存储的key 一般以 spring:session开头)。
三、可能出错问题
一般公司的Redis,运维人员都会将一些关键词禁用,例如 flush db 、config、keys * 等,所以项目启动会报错
Caused by: redis.clients.jedis.exceptions.JedisDataException: ERR unknown command 'CONFIG' |
解决办法(代码不深究):
package com.ylink.corp.report.util; import com.alibaba.fastjson2.support.spring.data.redis.FastJsonRedisSerializer; import com.alibaba.fastjson2.support.spring.data.redis.GenericFastJsonRedisSerializer; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.data.redis.connection.jedis.JedisConnectionFactory; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.data.redis.serializer.RedisSerializer; import org.springframework.data.redis.serializer.StringRedisSerializer; import org.springframework.session.data.redis.config.ConfigureRedisAction; import org.springframework.session.data.redis.config.annotation.web.http.EnableRedisHttpSession; import org.springframework.session.data.redis.config.annotation.web.http.RedisHttpSessionConfiguration; import javax.annotation.PostConstruct; /** * 禁用Redis的config命令后: * 注入空值ConfigureRedisAction.NO_OP解决该问题 * * @author test * @version 1.0v * @date 2021/12/29 15:44 */ @Configuration @EnableRedisHttpSession public class HttpSessionConfig { @Autowired JedisConnectionFactory jedisConnectionFactory; //解决Caused by: redis.clients.jedis.exceptions.JedisDataException: ERR unknown command 'CONFIG'这个错误 @Bean public static ConfigureRedisAction configureRedisAction() throws NoSuchMethodException { return ConfigureRedisAction.NO_OP; } @Autowired private RedisHttpSessionConfiguration redisHttpSessionConfiguration; @PostConstruct public void init() { //设置会话最大活动时间 redisHttpSessionConfiguration.setMaxInactiveIntervalInSeconds(60); //设置redis存储前缀名 redisHttpSessionConfiguration.setRedisNamespace("***"); //设置序列号 redisHttpSessionConfiguration.setDefaultRedisSerializer(new GenericFastJsonRedisSerializer()); } @Bean public RedisTemplate<Object, Object> redisTemplate() { RedisTemplate<Object, Object> redisTemplate = new RedisTemplate<>(); StringRedisSerializer stringRedisSerializer = new StringRedisSerializer(); redisTemplate.setConnectionFactory(jedisConnectionFactory); //Key序列化 redisTemplate.setKeySerializer(stringRedisSerializer); //value序列化 redisTemplate.setHashValueSerializer(stringRedisSerializer); //value hashmap序列化 redisTemplate.setHashKeySerializer(new FastJsonRedisSerializer<>(Object.class)); //key hashmap序列化 redisTemplate.setHashValueSerializer(new FastJsonRedisSerializer<>(Object.class)); return redisTemplate; } } |