欢迎讨论:NoSuchMethodError: org.springxxx.RedisOperations.delete(Ljava/lang/Object;)!

-发帖者:
-参与讨论....
【主题】:NoSuchMethodError: org.springxxx.RedisOperations.delete(Ljava/lang/Object;)

前言

在使用springboot2.0.6版本的配置spring session同步,共享管理的功能时,出现了以下问题

java.lang.NoSuchMethodError: org.springframework.data.redis.core.RedisOperations.delete(Ljava/lang/Object;)V

我现在使用的是版本是:springboot2.0.6,添加的依赖如下:对应的默认版本分别是:

  • spring-boot-starter-data-redis   2.0.7.RELEASE
  • spring-data-redis  2.0.11.RELEASE
  • spring-session-data-redis  2.0.7.RELEASE
  • jedis   2.9.0
<!-- 2020.08.14 miki redis starter依赖 ############################################# -->
	<dependency>
       <groupId>org.springframework.boot</groupId>
       <artifactId>spring-boot-starter-data-redis</artifactId>
       <exclusions>
           <exclusion>
               <groupId>redis.clients</groupId>
               <artifactId>jedis</artifactId>
           </exclusion>
           <exclusion>
               <groupId>io.lettuce</groupId>
               <artifactId>lettuce-core</artifactId>
           </exclusion>
       </exclusions>
   </dependency>
   <dependency>
       <groupId>org.apache.commons</groupId>
       <artifactId>commons-pool2</artifactId>
   </dependency>

   <dependency>
       <groupId>com.fasterxml.jackson.core</groupId>
       <artifactId>jackson-core</artifactId>
   </dependency>
   <dependency>
       <groupId>com.fasterxml.jackson.core</groupId>
       <artifactId>jackson-databind</artifactId>
   </dependency>
   <dependency>
       <groupId>com.fasterxml.jackson.core</groupId>
       <artifactId>jackson-annotations</artifactId>
   </dependency>
	 <dependency>
	    <groupId>org.springframework.session</groupId>
	    <artifactId>spring-session-core</artifactId>
	  </dependency>
	<dependency>
		<groupId>org.springframework.session</groupId>
		<artifactId>spring-session-data-redis</artifactId>
	</dependency>
   
 <!-- 2020.08.14 miki redis starter依赖 ############################################# -->

配置redisConfig如下:

package com.sharehoo.config;

/**
 * @author a small asshole
 * @version 1.0
 * @description redis配置类
 * @date in 17:14 2020/3/13
 * @since 1.0
 */
@EnableCaching
@EnableRedisHttpSession(maxInactiveIntervalInSeconds = 3600)//session过期时间(秒)
@Configuration
public class RedisConfig {
    @Value("${spring.redis.host}")
    private String host;
    @Value("${spring.redis.database}")
    private Integer database;
    @Value("${spring.redis.password}")
    private String password;
    @Value("${spring.redis.port}")
    private Integer port;
    @Value("${spring.redis.timeout}")
    private Integer timeout;
    
    @Bean
    @ConditionalOnMissingBean(name = "redisTemplate")
    public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
        RedisTemplate<Object, Object> redisTemplate = new RedisTemplate<>();
        redisTemplate.setConnectionFactory(redisConnectionFactory);
        Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
        ObjectMapper objectMapper = new ObjectMapper();
        objectMapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
        objectMapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
        jackson2JsonRedisSerializer.setObjectMapper(objectMapper);
        // 设置value的序列化规则和 key的序列化规则
        redisTemplate.setValueSerializer(jackson2JsonRedisSerializer);
        redisTemplate.setKeySerializer(new StringRedisSerializer());
        redisTemplate.afterPropertiesSet();
        return redisTemplate;
    }


    @Bean
    @ConditionalOnMissingBean(name = "stringRedisTemplate")
    public StringRedisTemplate stringRedisTemplate(RedisConnectionFactory redisConnectionFactory) {
        StringRedisTemplate stringRedisTemplate = new StringRedisTemplate();
        stringRedisTemplate.setConnectionFactory(redisConnectionFactory);
        Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(
                Object.class);
        ObjectMapper objectMapper = new ObjectMapper();
        objectMapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
        objectMapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
        jackson2JsonRedisSerializer.setObjectMapper(objectMapper);
        // 设置value的序列化规则和 key的序列化规则
        stringRedisTemplate.setValueSerializer(jackson2JsonRedisSerializer);
        stringRedisTemplate.setKeySerializer(new StringRedisSerializer());
        stringRedisTemplate.afterPropertiesSet();
        return stringRedisTemplate;
    }
    
    @Bean(name = "jedisPool")
    @ConfigurationProperties(prefix = "spring.redis.jedis.pool")
    public JedisPoolConfig jedisPoolConfig() {
        return new JedisPoolConfig();
    }

    @Bean
    @Primary
    public RedisConnectionFactory redisConnectionFactory(@Qualifier("jedisPool") JedisPoolConfig jedisPoolConfig) {
        //单机模式 没情趣不想理你 小气鬼 我中国银行和支付宝解绑了 为啥不回家搞不想回家
    	   	
        RedisStandaloneConfiguration redisStandaloneConfiguration =
                new RedisStandaloneConfiguration();
        redisStandaloneConfiguration.setHostName(host);
        redisStandaloneConfiguration.setDatabase(database);
        //密码解密
        redisStandaloneConfiguration.setPassword(RedisPassword.of(password));
        redisStandaloneConfiguration.setPort(port);
        //坑壁,竟然是个内部类,pool配置
        JedisClientConfiguration.DefaultJedisClientConfigurationBuilder clientConfigBuilder =
                (JedisClientConfiguration.DefaultJedisClientConfigurationBuilder) JedisClientConfiguration.builder();
        clientConfigBuilder.readTimeout(Duration.ofSeconds(50l)).connectTimeout(Duration.ofSeconds(50l));
        JedisClientConfiguration clientConfiguration = clientConfigBuilder.usePooling().poolConfig(jedisPoolConfig).build();
        
        JedisConnectionFactory factory = new JedisConnectionFactory(redisStandaloneConfiguration, clientConfiguration);
        factory.afterPropertiesSet();
        return factory;
    }


    @Bean
    public CacheManager cacheManagerBuilder(RedisConnectionFactory connectionFactory) {
        // 设置缓存有效期20天
        RedisCacheConfiguration redisCacheConfiguration = RedisCacheConfiguration.defaultCacheConfig()
                .entryTtl(Duration.ofDays(20));
        return RedisCacheManager
                .builder(RedisCacheWriter.nonLockingRedisCacheWriter(connectionFactory))
                .cacheDefaults(redisCacheConfiguration).build();
    }    
}

配置sessionConfig如下:

@EnableCaching
@EnableRedisHttpSession(maxInactiveIntervalInSeconds = 3600)//session过期时间(秒)
@Configuration
public class SessionConfig {
	
	    @Bean
	    public static ConfigureRedisAction configureRedisAction(){
	        //让springSession不再执行config命令
	        return ConfigureRedisAction.NO_OP;
	    }

}

然后配置yml文件:

redis: 
        host: 127.0.0.1
        password:
        port: 6379   
        timeout: 50000
        database: 0
        jedis:
          pool:
            max-active: 8
            max-idle: 8  
            min-idle: 0
            max-wait: -1
        lettuce:
          pool:
            max-active: 8
            max-wait:  -1
            max-idle: 8
            min-idle: 0
    session:
      store-type: redis

一切就绪,启动项目,redis已经可以存储session了,但是过一段时候之后,发现spring在定时清理过期的session的时候报错如下:

spring-session的核心类RedisSessionExpirationPolicy在执行清理过期session时,报错:源码如下:

Set<Object> sessionsToExpire = redis.boundSetOps(expirationKey).members();执行此行代码抛出异常:

public void cleanExpiredSessions() {
		long now = System.currentTimeMillis();
		long prevMin = roundDownMinute(now);

		if(logger.isDebugEnabled()) {
			logger.debug("Cleaning up sessions expiring at "+ new Date(prevMin));
		}

		String expirationKey = getExpirationKey(prevMin);
		Set<Object> sessionsToExpire = redis.boundSetOps(expirationKey).members();
		redis.delete(expirationKey);
		for(Object session : sessionsToExpire) {
			String sessionKey = getSessionKey((String) session);
			touch(sessionKey);
		}
	}

网上找了很多原因,大多数是说版本不兼容问题,但是我试着更新了好几个版本的包,依然是报如上的错误。后来我试着搭建了一个springboot2.1.15版本的脚手架重复以上的操作,然后问题得到了解决,最终定位到没有该问题的版本如下:

问题得到解决,真的是坑,springboot2.0.6版本默认版本的redis,session都不行,必须要升级到2.1.15版本以上适配的包才行,也是醉了。目前只有想到了该方法,仅以此记录下来。

<!-- https://mvnrepository.com/artifact/redis.clients/jedis -->
	<dependency>
	    <groupId>redis.clients</groupId>
	    <artifactId>jedis</artifactId>
	</dependency>
	<!-- 2020.08.14 miki redis starter依赖 ############################################# -->
	<dependency>
       <groupId>org.springframework.boot</groupId>
       <artifactId>spring-boot-starter-data-redis</artifactId>
       <version>2.1.15.RELEASE</version>
       <exclusions>
           <exclusion>
               <groupId>redis.clients</groupId>
               <artifactId>jedis</artifactId>
           </exclusion>
           <exclusion>
               <groupId>io.lettuce</groupId>
               <artifactId>lettuce-core</artifactId>
           </exclusion>
           <!-- 排除低版本的spring-data-redis,解决低版本下报错 【
           		java.lang.NoSuchMethodError: org.springframework.data.redis.core.RedisOperations.delete(Ljava/lang/Object;)V】
           	2020.08.15 Miki -->
           <exclusion>
           	<groupId>org.springframework.data</groupId>
           	<artifactId>spring-data-redis</artifactId>
           </exclusion>
       </exclusions>
   </dependency>
   <!-- 依赖高版本的spring-data-redis,解决低版本下报错 【
           		java.lang.NoSuchMethodError: org.springframework.data.redis.core.RedisOperations.delete(Ljava/lang/Object;)V】
           	2020.08.15 Miki -->
   <dependency>
      <groupId>org.springframework.data</groupId>
      <artifactId>spring-data-redis</artifactId>
      <version>2.1.18.RELEASE</version>
      <scope>compile</scope>
      <exclusions>
        <exclusion>
          <artifactId>jcl-over-slf4j</artifactId>
          <groupId>org.slf4j</groupId>
        </exclusion>
      </exclusions>
    </dependency>

 

 发表评论     发表时间:『2020-08-15 23:03:22』


扫描二维码关注网站最新动态