首页 > Java > java教程 > 正文

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

聖光之護
发布: 2025-12-08 20:29:42
原创
541人浏览过

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<String, Object> redisTemplate;

    // 推荐使用构造器注入
    public TokenService(RedisTemplate<String, Object> 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的示例,旨在解决常见的序列化问题并优化配置

Android开发中使用SQLite数据库的教程 chm版
Android开发中使用SQLite数据库的教程 chm版

Android使用SQLite数据库进行开发的教程,chm格式,SQLite 是一款非常流行的嵌入式数据库,它支持 SQL 查询,并且只用很少的内存。Android 在运行时集成了 SQLite,所以每个 Android 应用程序都可以使用 SQLite 数据库。对数熟悉 SQL 的开发人员来时,使用 SQLite 相当简单。可以,由于 JDBC 不适合手机这种内存受限设备,所以 Android 开发人员需要学习新的 API 来使用 SQLite。本文主要讲解 SQLite 在 Android 环境中的基

Android开发中使用SQLite数据库的教程 chm版 0
查看详情 Android开发中使用SQLite数据库的教程 chm版
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<String, Object> redisTemplate() {
        RedisTemplate<String, Object> 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<String, Object> redisTemplate;

    public AuthenticationService(RedisTemplate<String, Object> 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的默认版本。
      <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-data-redis</artifactId>
      </dependency>
      <!-- 如果需要JSON序列化,添加Jackson依赖 -->
      <dependency>
      <groupId>com.fasterxml.jackson.core</groupId>
      <artifactId>jackson-databind</artifactId>
      </dependency>
      登录后复制
  • 检查依赖树:使用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数据存储解决方案。

以上就是Spring Boot集成RedisTemplate进行数据存储教程的详细内容,更多请关注php中文网其它相关文章!

最佳 Windows 性能的顶级免费优化软件
最佳 Windows 性能的顶级免费优化软件

每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。

下载
来源:php中文网
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn
最新问题
开源免费商场系统广告
热门教程
更多>
最新下载
更多>
网站特效
网站源码
网站素材
前端模板
关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新 English
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送
PHP中文网APP
随时随地碎片化学习

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