频道栏目
首页 > 数据库 > 其他综合 > 正文
项目增加spring-session模块所遇到的问题及解决办法
2018-03-14 10:39:18         来源:Welcome!  
收藏   我要投稿

使用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文件中配置如下sample-session.xml

<?xml version="1.0" encoding="UTF-8"?><!-- spring session redis连接配置文件 --> 

<beans xmlns="https://www.springframework.org/schema/beans" 

xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance" 

xsi:schemaLocation="https://www.springframework.org/schema/beans https://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访问错误。 

https://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 

点击复制链接 与好友分享!回本站首页
上一篇:LeetCode编程:Intersection of Two Linked Lists
下一篇:mongodb数据库增删改查、备份与回复及运算符使用讲解
相关文章
图文推荐
点击排行

关于我们 | 联系我们 | 广告服务 | 投资合作 | 版权申明 | 在线帮助 | 网站地图 | 作品发布 | Vip技术培训 | 举报中心

版权所有: 红黑联盟--致力于做实用的IT技术学习网站