0

0

Spring Boot集成RedisTemplate进行数据存储教程

聖光之護

聖光之護

发布时间:2025-12-08 20:29:42

|

559人浏览过

|

来源于php中文网

原创

spring boot集成redistemplate进行数据存储教程

本教程旨在指导如何在Spring Boot应用中有效集成和使用RedisTemplate,实现数据(如用户令牌)的存储。文章将涵盖Spring Boot的自动配置机制、手动配置Redis连接工厂与RedisTemplate的细节,重点讲解不同序列化器的选择及其对数据存储的影响,并提供避免常见错误(如NoSuchMethodError)的实践建议。

Spring Boot集成RedisTemplate进行数据存储

在Spring Boot应用中利用Redis进行数据缓存或存储是常见的需求,尤其是在处理用户会话或令牌等场景。Spring Data Redis提供了强大的抽象,其中RedisTemplate是与Redis进行交互的核心组件。本文将详细介绍如何在Spring Boot项目中配置和使用RedisTemplate,并解决可能遇到的常见问题

1. 快速配置:利用Spring Boot自动配置

Spring Boot为Redis提供了便捷的自动配置功能,这是推荐的集成方式。通过简单的配置,Spring Boot会自动创建JedisConnectionFactory或LettuceConnectionFactory(取决于你引入的依赖)以及一个默认的RedisTemplate实例。

你只需在application.yml或application.properties文件中添加Redis连接信息:

spring:
  redis:
    host: localhost
    port: 6379
    # password: your_redis_password # 如果Redis有密码
    # database: 0 # 选择Redis数据库,默认为0

完成上述配置后,Spring Boot会自动配置好Redis连接,你就可以直接在Service层或Repository层注入RedisTemplate或StringRedisTemplate进行使用了。

import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

@Service
public class TokenService {

    private final RedisTemplate redisTemplate;

    // 推荐使用构造器注入
    public TokenService(RedisTemplate redisTemplate) {
        this.redisTemplate = redisTemplate;
    }

    public void storeToken(String userId, String token) {
        // 使用opsForValue()存储简单的键值对
        redisTemplate.opsForValue().set("user:token:" + userId, token);
    }

    public String getToken(String userId) {
        // 获取令牌
        return (String) redisTemplate.opsForValue().get("user:token:" + userId);
    }
}

注意事项:

  • 默认情况下,Spring Boot的RedisTemplate会使用JdkSerializationRedisSerializer进行值的序列化。这意味着存储到Redis的数据是Java对象序列化后的二进制形式。
  • 如果需要存储纯字符串或JSON数据,推荐使用StringRedisTemplate,它默认使用StringRedisSerializer,或者对RedisTemplate进行定制。

2. 手动配置RedisTemplate与序列化器

在某些特定场景下,例如需要更细粒度的控制、使用不同的连接池配置、或者自定义序列化策略时,你可能需要手动配置RedisConnectionFactory和RedisTemplate。

以下是一个手动配置RedisTemplate的示例,旨在解决常见的序列化问题并优化配置

若冰企业商务平台.net
若冰企业商务平台.net

集企业自助建站、网络营销、商品推广于一体的系统 功能说明: 1、系统采用Microsoft SQL Server大型数据库支持,查询数据库用的全是存储过程,速度和性能极好。开发环境是vs.net,采用4层结构,具有很好的可维护性和可扩冲性。 2、用户注册和登陆 未注册用户只具备浏览商品、新闻和留言功能;要采购商品,需接受服务协议并填写相关注册信息成为正式用户后方可进行,以尽可能减少和避免无效

下载
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisStandaloneConfiguration;
import org.springframework.data.redis.connection.jedis.JedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;

@Configuration
public class RedisConfig {

    /**
     * 配置Jedis连接工厂。
     * 推荐使用LettuceConnectionFactory作为更现代的选择,但此处沿用JedisConnectionFactory以匹配原始问题背景。
     */
    @Bean
    public JedisConnectionFactory jedisConnectionFactory() {
        RedisStandaloneConfiguration redisStandaloneConfiguration = new RedisStandaloneConfiguration();
        redisStandaloneConfiguration.setHostName("localhost"); // 确保与application.yml一致或直接硬编码
        redisStandaloneConfiguration.setPort(6379);
        // redisStandaloneConfiguration.setPassword(RedisPassword.of("your_password")); // 如果有密码

        return new JedisConnectionFactory(redisStandaloneConfiguration);
    }

    /**
     * 配置RedisTemplate,指定键和值的序列化方式。
     * 对于存储字符串或JSON对象,推荐使用StringRedisSerializer和GenericJackson2JsonRedisSerializer。
     */
    @Bean
    public RedisTemplate redisTemplate() {
        RedisTemplate template = new RedisTemplate<>();
        template.setConnectionFactory(jedisConnectionFactory());

        // 使用StringRedisSerializer来序列化和反序列化Redis的key值
        StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();
        template.setKeySerializer(stringRedisSerializer);
        template.setHashKeySerializer(stringRedisSerializer); // Hash的key也使用String序列化

        // 使用GenericJackson2JsonRedisSerializer来序列化和反序列化Redis的value值(默认使用JDK序列化)
        // 这使得存储的对象以JSON字符串形式存储,易于阅读和跨语言互操作
        GenericJackson2JsonRedisSerializer jsonRedisSerializer = new GenericJackson2JsonRedisSerializer();
        template.setValueSerializer(jsonRedisSerializer);
        template.setHashValueSerializer(jsonRedisSerializer); // Hash的value也使用JSON序列化

        template.setEnableTransactionSupport(false); // 根据需要开启或关闭事务支持
        template.afterPropertiesSet();
        return template;
    }
}

在上述配置中,我们做了以下改进:

  • 连接工厂:jedisConnectionFactory()方法负责创建与Redis服务器的连接。
  • 序列化器选择
    • setKeySerializer(new StringRedisSerializer()):将所有Redis键(包括主键和Hash键)序列化为UTF-8字符串。
    • setValueSerializer(new GenericJackson2JsonRedisSerializer()):将所有Redis值(包括Hash值)序列化为JSON字符串。GenericJackson2JsonRedisSerializer比JdkSerializationRedisSerializer更通用,它将Java对象转换为人类可读的JSON格式,便于调试和跨语言互操作。如果你的值只是简单字符串,也可以直接使用StringRedisSerializer。
    • 避免重复配置:原始代码中setHashKeySerializer被调用了两次,后一次会覆盖前一次。这里我们明确指定了Hash键和值的序列化器。

3. 使用RedisTemplate进行数据操作

一旦RedisTemplate配置完成,你就可以在业务逻辑中注入并使用它来执行各种Redis操作。

import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import java.util.concurrent.TimeUnit;

@Service
public class AuthenticationService {

    private final RedisTemplate redisTemplate;

    public AuthenticationService(RedisTemplate redisTemplate) {
        this.redisTemplate = redisTemplate;
    }

    // 假设AuthenticationSuccessDto是一个包含accessToken等信息的DTO
    public static class AuthenticationSuccessDto {
        private String accessToken;
        private String refreshToken;
        private String tokenType;
        private Object user; // 示例,可以是User对象或其他
        private Long expiresIn;

        // 省略构造器、getter、setter、builder等
        public String getAccessToken() { return accessToken; }
        public String getRefreshToken() { return refreshToken; }
        public String getTokenType() { return tokenType; }
        public Object getUser() { return user; }
        public Long getExpiresIn() { return expiresIn; }
        public AuthenticationSuccessDto setAccessToken(String accessToken) { this.accessToken = accessToken; return this; }
        public AuthenticationSuccessDto setRefreshToken(String refreshToken) { this.refreshToken = refreshToken; return this; }
        public AuthenticationSuccessDto setTokenType(String tokenType) { this.tokenType = tokenType; return this; }
        public AuthenticationSuccessDto setUser(Object user) { this.user = user; return this; }
        public AuthenticationSuccessDto setExpiresIn(Long expiresIn) { this.expiresIn = expiresIn; return this; }
    }

    private static final String USER_TOKENS_KEY_PREFIX = "user:tokens:";

    /**
     * 存储用户认证信息,使用Redis的Hash结构。
     *
     * @param userId 用户ID
     * @param authDto 认证成功DTO
     */
    public AuthenticationSuccessDto storeAuthenticationInfo(String userId, AuthenticationSuccessDto authDto) {
        String hashKey = USER_TOKENS_KEY_PREFIX + userId;

        try {
            // 使用opsForHash().putAll()存储整个DTO,或者opsForHash().put()存储单个字段
            // 这里为了演示,我们存储accessToken到Hash中
            redisTemplate.opsForHash().put(hashKey, "accessToken", authDto.getAccessToken());
            redisTemplate.opsForHash().put(hashKey, "refreshToken", authDto.getRefreshToken());
            redisTemplate.opsForHash().put(hashKey, "expiresIn", authDto.getExpiresIn());

            // 设置整个Hash的过期时间
            if (authDto.getExpiresIn() != null && authDto.getExpiresIn() > 0) {
                redisTemplate.expire(hashKey, authDto.getExpiresIn(), TimeUnit.SECONDS);
            }

        } catch (Exception e) {
            System.err.println("存储认证信息到Redis失败: " + e.getMessage());
            e.printStackTrace();
            // 根据业务需求抛出自定义异常
            throw new RuntimeException("Failed to store authentication info in Redis.", e);
        }
        return authDto;
    }

    /**
     * 从Redis获取用户的访问令牌。
     *
     * @param userId 用户ID
     * @return 访问令牌,如果不存在则返回null
     */
    public String getAccessToken(String userId) {
        String hashKey = USER_TOKENS_KEY_PREFIX + userId;
        return (String) redisTemplate.opsForHash().get(hashKey, "accessToken");
    }
}

在上述AuthenticationService示例中:

  • 我们定义了一个USER_TOKENS_KEY_PREFIX来构建Hash的主键。
  • storeAuthenticationInfo方法使用redisTemplate.opsForHash().put()将AuthenticationSuccessDto中的关键信息存储到Redis的Hash结构中。
  • redisTemplate.expire()用于为整个Hash设置过期时间,确保令牌的生命周期。
  • getAccessToken方法演示了如何从Hash中检索特定字段。

4. 解决java.lang.NoSuchMethodError问题

java.lang.NoSuchMethodError: 'long redis.clients.jedis.Jedis.hset(byte[], byte[], byte[])' 错误通常发生在以下情况:

  1. 版本不兼容:spring-data-redis库与底层Jedis客户端库的版本不兼容。Spring Data Redis会根据其内部实现调用Jedis客户端的特定方法。如果Jedis版本过旧或过新,不包含Spring Data Redis期望的方法签名,就会抛出此错误。
  2. 依赖冲突:项目中引入了多个版本的Jedis或相关的Redis客户端库,导致运行时加载了错误的版本。

解决方案:

  • 优先使用Spring Boot管理依赖:让Spring Boot Starter POMs (spring-boot-starter-data-redis) 来管理spring-data-redis和Jedis/Lettuce的版本。Spring Boot会选择一个已知兼容的版本组合。
    • 确保你的pom.xml中只引入了spring-boot-starter-data-redis,并且没有显式地引入Jedis或Lettuce的特定版本,除非你明确知道需要覆盖Spring Boot的默认版本。
      
      org.springframework.boot
      spring-boot-starter-data-redis
      
      
      
      com.fasterxml.jackson.core
      jackson-databind
      
  • 检查依赖树:使用Maven (mvn dependency:tree) 或 Gradle (gradle dependencies) 命令检查项目的实际依赖树,查找是否存在Jedis或Lettuce的冲突版本。如果发现冲突,可以通过标签排除不正确的版本。
  • 更新Spring Boot版本:如果你的Spring Boot版本较旧,尝试升级到最新稳定版本,这通常会带来最新的兼容依赖。

总结

在Spring Boot中集成RedisTemplate进行数据存储,最佳实践是首先利用Spring Boot的自动配置功能。当需要更高级的定制时,可以手动配置JedisConnectionFactory(或LettuceConnectionFactory)和RedisTemplate,并特别注意选择合适的序列化器。对于存储字符串或JSON对象,StringRedisSerializer和GenericJackson2JsonRedisSerializer是常用的选择。遇到NoSuchMethodError时,应重点检查spring-data-redis和底层Redis客户端库的版本兼容性及依赖冲突,通常通过Spring Boot Starter的依赖管理可以有效避免此类问题。通过以上步骤,你可以构建一个健壮且高效的Redis数据存储解决方案。

相关专题

更多
java
java

Java是一个通用术语,用于表示Java软件及其组件,包括“Java运行时环境 (JRE)”、“Java虚拟机 (JVM)”以及“插件”。php中文网还为大家带了Java相关下载资源、相关课程以及相关文章等内容,供大家免费下载使用。

841

2023.06.15

java正则表达式语法
java正则表达式语法

java正则表达式语法是一种模式匹配工具,它非常有用,可以在处理文本和字符串时快速地查找、替换、验证和提取特定的模式和数据。本专题提供java正则表达式语法的相关文章、下载和专题,供大家免费下载体验。

742

2023.07.05

java自学难吗
java自学难吗

Java自学并不难。Java语言相对于其他一些编程语言而言,有着较为简洁和易读的语法,本专题为大家提供java自学难吗相关的文章,大家可以免费体验。

737

2023.07.31

java配置jdk环境变量
java配置jdk环境变量

Java是一种广泛使用的高级编程语言,用于开发各种类型的应用程序。为了能够在计算机上正确运行和编译Java代码,需要正确配置Java Development Kit(JDK)环境变量。php中文网给大家带来了相关的教程以及文章,欢迎大家前来阅读学习。

397

2023.08.01

java保留两位小数
java保留两位小数

Java是一种广泛应用于编程领域的高级编程语言。在Java中,保留两位小数是指在进行数值计算或输出时,限制小数部分只有两位有效数字,并将多余的位数进行四舍五入或截取。php中文网给大家带来了相关的教程以及文章,欢迎大家前来阅读学习。

399

2023.08.02

java基本数据类型
java基本数据类型

java基本数据类型有:1、byte;2、short;3、int;4、long;5、float;6、double;7、char;8、boolean。本专题为大家提供java基本数据类型的相关的文章、下载、课程内容,供大家免费下载体验。

446

2023.08.02

java有什么用
java有什么用

java可以开发应用程序、移动应用、Web应用、企业级应用、嵌入式系统等方面。本专题为大家提供java有什么用的相关的文章、下载、课程内容,供大家免费下载体验。

430

2023.08.02

java在线网站
java在线网站

Java在线网站是指提供Java编程学习、实践和交流平台的网络服务。近年来,随着Java语言在软件开发领域的广泛应用,越来越多的人对Java编程感兴趣,并希望能够通过在线网站来学习和提高自己的Java编程技能。php中文网给大家带来了相关的视频、教程以及文章,欢迎大家前来学习阅读和下载。

16926

2023.08.03

Java JVM 原理与性能调优实战
Java JVM 原理与性能调优实战

本专题系统讲解 Java 虚拟机(JVM)的核心工作原理与性能调优方法,包括 JVM 内存结构、对象创建与回收流程、垃圾回收器(Serial、CMS、G1、ZGC)对比分析、常见内存泄漏与性能瓶颈排查,以及 JVM 参数调优与监控工具(jstat、jmap、jvisualvm)的实战使用。通过真实案例,帮助学习者掌握 Java 应用在生产环境中的性能分析与优化能力。

19

2026.01.20

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
Kotlin 教程
Kotlin 教程

共23课时 | 2.7万人学习

C# 教程
C# 教程

共94课时 | 7.1万人学习

Java 教程
Java 教程

共578课时 | 48.4万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号