使用session共享,原有项目加上spring-session开源模块 使用redis进行共享session的存储,redis服务端是sentinel集群
使用的spring版本 <properties> <spring-version>3.1.2.RELEASE</spring-version> </properties> 使用的spring- data -redis版本 <dependency> <groupId>org.springframework.data</groupId> <artifactId>spring-data-redis</artifactId> <version>1.4.2.RELEASE</version> </dependency>
<?xml version="1.0" encoding="UTF-8"?><!-- spring session redis连接配置文件 --> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <bean id="jedisPoolConfig" class="redis.clients.jedis.JedisPoolConfig"> <!-- jedis连接池参数 --> <property name="maxTotal" value="300" /><!-- 设置最大连接数 --> <property name="maxIdle" value="10" /><!-- 设置最多空闲连接 --> <property name="testOnBorrow" value="true"/><!-- 启动检查是否存在 --> <property name="maxWaitMillis" value="2000" /><!-- 设置最大阻塞时间,记住是毫秒数milliseconds --> </bean> <!-- 哨兵集群连接配置 start--> <property name="master"> <bean class="org.springframework.data.redis.connection.RedisNode"> <property name="name" value="CAREERS_c42581_1"/> </bean> </property> <property name="sentinels"> <set> <bean class="org.springframework.data.redis.connection.RedisNode"> <constructor-arg name="host" value="10.27.18.225"/> <constructor-arg name="port" value="26379"/> </bean> <bean class="org.springframework.data.redis.connection.RedisNode"> <constructor-arg name="host" value="10.27.18.227"/> <constructor-arg name="port" value="26379"/> </bean> <bean class="org.springframework.data.redis.connection.RedisNode"> <constructor-arg name="host" value="10.27.18.228"/> <constructor-arg name="port" value="26379"/> </bean> </set> </property> </bean> <!-- 哨兵集群连接配置 end--> <!-- redis连接池配置 --> <constructor-arg index="0" ref="sentinelConfig"/> <constructor-arg index="1" ref="jedisPoolConfig"/> </bean> <bean id="redisHttpSessionConfiguration" class="org.springframework.session.data.redis.config.annotation.web.http.RedisHttpSessionConfiguration"> <!-- 配置spring-session --> <property name="maxInactiveIntervalInSeconds" value="6000"></property> <!-- 过期时间100分钟 --> </bean> </beans>
三月 05, 2018 3:20:40 下午 org.apache.catalina.core.StandardContext listenerStart SEVERE: Exception sending context initialized event to listener instance of class org.springframework.web.context.ContextLoaderListener org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'sentinelConfig' defined in class path resource [conf/spring/sample-session.xml]: Error setting property values; nested exception is org.springframework.beans.NotWritablePropertyException: Invalid property 'sentinels' of bean class [org.springframework.data.redis.connection.RedisSentinelConfiguration]: Bean property 'sentinels' is not writable or has an invalid setter method. Does the parameter type of the setter match the return type of the getter? at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyPropertyValues(AbstractAutowireCapableBeanFactory.java:1396) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1118) .... Caused by: org.springframework.beans.NotWritablePropertyException: Invalid property 'sentinels' of bean class [org.springframework.data.redis.connection.RedisSentinelConfiguration]: Bean property 'sentinels' is not writable or has an invalid setter method. Does the parameter type of the setter match the return type of the getter? at org.springframework.beans.BeanWrapperImpl.setPropertyValue(BeanWrapperImpl.java:1064) ... 23 more
无法把sentinels属性设置进sentinelConfig对象,因为sentinels属性是不可写的或没有一个有效的set方法。又或者set方法和get方法的参数类型是否一致?
在sentinelConfig对象(org.springframework.data.redis.connection.RedisSentinelConfiguration)中, 属性sentinels的set方法及get方法如下 public class RedisSentinelConfiguration { … … private Set<RedisNode> sentinels; public void setSentinels(Iterable<RedisNode> sentinels) { Assert.notNull(sentinels, "Cannot set sentinels to 'null'."); this.sentinels.clear(); for (RedisNode sentinel : sentinels) { addSentinel(sentinel); } } public Set<RedisNode> getSentinels() { return Collections.unmodifiableSet(sentinels); } … … } 发现sentinels属性的set方法的参数类型与sentinels属性不一致 查看源码发现 Set extends Collection Collection extends Iterable 属性sentinels类型虽然是Set,但是Iterable是其父类的父类,应该可以直接转换
一, 升级spring版本,升级至spring-beans模块支持将Set类型属性调用其Iterable类型的set方法,实测当spring版本升级至3.2.5+时,可以排除错误。但是原有项目因为升级spring,引发了其它问题,如SpringMVC模块的406访问错误。 http://blog.csdn.net/linhenk/article/details/54611449 二, 继承RedisSentinelConfiguration类,重载其中sentinels的set方法 public class RpsRedisSentinelConfiguration extends RedisSentinelConfiguration { … … public void setSentinels(Set<RedisNode> sentinels) { Assert.notNull(sentinels, "Cannot set sentinels to 'null'."); this.sentinels.clear(); for (RedisNode sentinel : sentinels) { addSentinel(sentinel); } } … … } 并修改sample-session.xml文件,修改spring容器初始化的具体实现类为自定义 <bean id="sentinelConfig" class="org.springframework.data.redis.connection.RedisSentinelConfiguration" class="com.***.***.RpsRedisSentinelConfiguration"> … … </bean