Spring Boot RedisTemplate存Token报错NoSuchMethodError,求解决
解决Redis存储Token时的
NoSuchMethodError异常 问题场景
计划在Redis中存储Token,编写了如下配置类和业务代码:
RedisConfig配置类
@Configuration @EnableCaching public class RedisConfig { @Bean public JedisConnectionFactory jedisConnectionFactory() { RedisStandaloneConfiguration redisStandaloneConfiguration = new RedisStandaloneConfiguration(); redisStandaloneConfiguration.setHostName("127.0.0.1"); redisStandaloneConfiguration.setPort(6379); JedisConnectionFactory jedisConnectionFactory = new JedisConnectionFactory(redisStandaloneConfiguration); return jedisConnectionFactory; } @Bean public RedisTemplate<String, String> redisTemplate() { RedisTemplate<String, String> redisTemplate = new RedisTemplate<>(); redisTemplate.setConnectionFactory(jedisConnectionFactory()); redisTemplate.setKeySerializer(new StringRedisSerializer()); redisTemplate.setHashKeySerializer(new StringRedisSerializer()); redisTemplate.setHashKeySerializer(new JdkSerializationRedisSerializer()); redisTemplate.setValueSerializer(new JdkSerializationRedisSerializer()); redisTemplate.setEnableTransactionSupport(true); redisTemplate.afterPropertiesSet(); return redisTemplate; } }
Service业务代码
final var st =AuthenticationSuccessDto .builder() .accessToken(jwtUtils.generateAccessToken(user)) .refreshToken(jwtUtils.generateRefreshToken(user)) .tokenType("Bearer") .user(user) .expiresIn(TimeUnit.SECONDS.toSeconds(60)).build(); try { redisTemplate.opsForHash().put(KEY,"1",st.getAccessToken()); } catch (Exception e) { e.printStackTrace(); throw new Exception(); } return st;
运行时抛出异常:
java.lang.NoSuchMethodError: 'long redis.clients.jedis.Jedis.hset(byte[], byte[], byte[])'
问题原因
- RedisTemplate序列化配置冲突:配置中重复设置
HashKeySerializer,先指定为StringRedisSerializer后又覆盖为JdkSerializationRedisSerializer,且泛型为<String,String>的RedisTemplate使用JDK序列化会导致逻辑混乱。 - 依赖版本不兼容:Spring Data Redis与Jedis版本不匹配,导致调用的
hset方法签名(返回值、参数)在当前Jedis版本中不存在。 - 该异常不需要手动将字符串转为字节,RedisTemplate的序列化器会自动处理类型转换。
解决方案
1. 修复RedisTemplate序列化配置
因存储的是字符串类型Token,统一使用StringRedisSerializer适配泛型,避免序列化冲突:
@Bean public RedisTemplate<String, String> redisTemplate() { RedisTemplate<String, String> redisTemplate = new RedisTemplate<>(); redisTemplate.setConnectionFactory(jedisConnectionFactory()); StringRedisSerializer stringSerializer = new StringRedisSerializer(); // 统一配置序列化器 redisTemplate.setKeySerializer(stringSerializer); redisTemplate.setValueSerializer(stringSerializer); redisTemplate.setHashKeySerializer(stringSerializer); redisTemplate.setHashValueSerializer(stringSerializer); redisTemplate.setEnableTransactionSupport(true); redisTemplate.afterPropertiesSet(); return redisTemplate; }
2. 对齐Spring Data Redis与Jedis版本
确保两者版本兼容,若使用Spring Boot,建议通过依赖管理统一版本:
- Maven示例:
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency> <dependency> <groupId>redis.clients</groupId> <artifactId>jedis</artifactId> <!-- Spring Boot自动匹配兼容版本,无需手动指定 --> </dependency>
手动管理版本时,参考Spring官方文档的版本兼容矩阵,保证Jedis版本与Spring Data Redis版本匹配。
3. 优化业务代码(可选)
- 给Token设置过期时间,避免Redis存储无效数据:
try { String hashKey = "1"; redisTemplate.opsForHash().put(KEY, hashKey, st.getAccessToken()); // 给整个KEY设置过期时间,与Token有效期保持一致 redisTemplate.expire(KEY, st.getExpiresIn(), TimeUnit.SECONDS); } catch (Exception e) { e.printStackTrace(); throw new RuntimeException("存储Token到Redis失败", e); }
- 避免直接抛出
Exception,改用更具体的自定义异常或RuntimeException,便于上层逻辑处理。
内容的提问来源于stack exchange,提问作者Borka192
相关产品推荐
相关产品推荐

