SpringBoot整合Redis的实践

 更新时间:2026年03月02日 14:25:58   作者:一恍过去  
Redis是一个高性能的内存数据库,支持多种数据结构和持久化机制,广泛应用于缓存、会话存储、排行榜等场景,SpringDataRedis是SpringFramework生态系统中用于简化Redis开发的模块,提供了对象映射、高级查询、事务支持、Pub/Sub消息订阅等功能

前言

Redis(Remote Dictionary Server)是一个开源的内存数据库(In-Memory Database),也被称为数据结构服务器,它支持存储键值对,并提供多种数据结构的操作。

Redis具有高性能、丰富的数据结构和灵活的持久化机制,因此在缓存、会话存储、排行榜、计数器、消息队列等场景中得到广泛的应用。

Redis主要有以下特点:

  • 内存数据库: Redis的所有数据都存储在内存中,这使得它具有非常高的读写速度。虽然数据存储在内存中,但Redis也支持将数据持久化到磁盘上,以确保数据的安全性和可恢复性。
  • 键值存储: Redis以键值对(Key-Value)的形式存储数据,其中键是唯一的,而值可以是字符串、列表、哈希表、集合、有序集合等多种数据结构。
  • 丰富的数据结构: Redis支持多种数据结构的操作,如字符串(String)、列表(List)、哈希表(Hash)、集合(Set)、有序集合(Sorted Set)等。这些数据结构可以方便地满足不同应用场景的需求。
  • 高性能: Redis是一个单线程的服务器,它采用异步I/O和事件驱动的方式,使得它能够在单个线程中处理大量的并发请求,从而获得较高的性能。
  • 持久化: Redis提供了两种方式的数据持久化:RDB快照和AOF日志。RDB快照可以将当前内存中的数据以二进制形式写入磁盘,而AOF日志则记录了所有写命令,用于在服务重启后重放这些命令以还原数据。
  • 分布式: Redis支持通过主从复制(Master-Slave Replication)实现数据的读写分离和高可用性。此外,Redis还提供了集群(Cluster)模式,可以将数据分布在多个节点上,从而实现数据的横向扩展。
  • 支持多种编程语言: Redis提供了多种编程语言的客户端库,可以方便地在各种不同的编程语言中使用Redis。

Spring Data Redis是Spring Framework生态系统中的一个模块,用于简化使用Redis的开发。它提供了对Redis的集成和操作的抽象层,使得在Spring应用程序中使用Redis变得更加方便和高效。

通过使用Spring Data Redis,开发人员可以更加便捷地操作Redis数据库,减少了与Redis交互的复杂性和重复性工作。同时,它与Spring Framework的其他模块和特性无缝集成,提供了更强大的功能和灵活性。

Spring Data Redis主要提供以下功能和特性:

  • 对象映射: Spring Data Redis允许开发人员使用注解或XML配置将Java对象与Redis数据存储之间进行映射。通过这种方式,可以将复杂的Java对象直接存储到Redis中,并通过简单的API进行读取和更新。
  • 高级查询: Spring Data Redis支持通过注解或方法命名约定进行高级查询,例如按条件查询、排序、分页等操作。这样可以方便地使用查询语言来检索和操作Redis中的数据。
  • 事务支持: Spring Data Redis提供了对Redis事务的支持,可以在一系列Redis操作中开启、提交或回滚事务,确保数据的一致性和完整性。
  • Pub/Sub消息订阅/发布: Spring Data Redis支持Redis的Pub/Sub功能,使应用程序能够通过订阅和发布消息来实现解耦和异步通信。
  • 缓存支持: Spring Data Redis与Spring缓存抽象集成,使得可以轻松地使用Redis作为缓存提供器,提高应用程序的性能和响应速度。
  • 连接池管理: Spring Data Redis提供了连接池管理功能,通过连接池可以有效地管理和复用Redis连接,减少连接的创建和销毁开销,提高性能和资源利用率。

1、引入pom

		<dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
        </dependency>
        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-pool2</artifactId>
        </dependency>

2、配置RedisTemplate

import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.cache.CacheManager;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.cache.RedisCacheConfiguration;
import org.springframework.data.redis.cache.RedisCacheManager;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.RedisSerializationContext;
import org.springframework.data.redis.serializer.StringRedisSerializer;

import java.time.Duration;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

@Configuration
public class RedisTemplateConfig {
    @Bean("redisTemplate")
    public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory connectionFactory) {
        RedisTemplate<String, Object> template = new RedisTemplate<>();

        // 设置连接工厂
        template.setConnectionFactory(connectionFactory);

        // 设置序列化方式
        StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();
        // key序列化
        template.setKeySerializer(stringRedisSerializer);
        // value序列化
        template.setValueSerializer(getJackson2JsonRedisSerializer());
        // Hash key序列化
        template.setHashKeySerializer(stringRedisSerializer);
        // Hash value序列化
        template.setHashValueSerializer(getJackson2JsonRedisSerializer());

        template.afterPropertiesSet();

        return template;
    }


    /**
     * 缓存管理器
     *
     * @param redisConnectionFactory
     * @return
     */
    @Bean
    public CacheManager cacheManager(RedisConnectionFactory redisConnectionFactory) {
        RedisCacheConfiguration defaultCacheConfig = RedisCacheConfiguration.defaultCacheConfig();

        // 设置缓存管理器管理
        defaultCacheConfig = defaultCacheConfig
                // 缓存的默认过期时间:
                .entryTtl(Duration.ofSeconds(36000))
                // 设置 key为string序列化
                .serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(new StringRedisSerializer()))
                // 设置value为json序列化
                .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(getJackson2JsonRedisSerializer()))
                // 不缓存空值
                .disableCachingNullValues();
        Set<String> cacheNames = new HashSet<>();

        // 对每个缓存空间应用不同的配置
        Map<String, RedisCacheConfiguration> configMap = new HashMap<>();

        return RedisCacheManager.builder(redisConnectionFactory)
                .cacheDefaults(defaultCacheConfig)
                .initialCacheNames(cacheNames)
                .withInitialCacheConfigurations(configMap)
                .build();
    }

    /**
     * 获取Jackson2JsonRedisSerializer序列化对象
     *
     * @return o
     */
    private Jackson2JsonRedisSerializer<Object> getJackson2JsonRedisSerializer() {

        /* 明文存取 */
        Jackson2JsonRedisSerializer<Object> jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer<>(Object.class);
        ObjectMapper om = new ObjectMapper();
        //指定要序列化的域,field,get和set,以及修饰符范围,ANY是都有包括private和public
        om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
        jackson2JsonRedisSerializer.setObjectMapper(om);

        return jackson2JsonRedisSerializer;
    }

}

3、配置yml

3.1、单机配置

spring:  
  redis:
    # Redis数据库索引(默认为0)
    database: 0
    # 连接地址
    host: 127.0.0.1
    #端口号
    port: 6379
    ##连接超时时间
    timeout: 3600ms
    #密码
    password:
    lettuce:
      pool:
        # 连接池最大连接数(使用负值表示没有限制)
        max-active: 8
        # 连接池最大阻塞等待时间(使用负值表示没有限制)
        max-wait: -1ms
        # 连接池中的最大空闲连接
        max-idle: 8
        # 连接池中的最小空闲连接
        min-idle: 1
      #关闭超时
      shutdown-timeout: 500ms

3.2、集群配置

spring:  
  redis:
    cluster:
      nodes:
        - 127.0.0.1:7001
        - 127.0.0.1:7002
        - 127.0.0.1:7003
        - 127.0.0.1:7004
        - 127.0.0.1:7005
        - 127.0.0.1:7006
    #连接超时时间
    timeout: 3600ms
    #密码
    password:
    lettuce:
      pool:
        # 连接池最大连接数(使用负值表示没有限制)
        max-active: 8
        # 连接池最大阻塞等待时间(使用负值表示没有限制)
        max-wait: -1ms
        # 连接池中的最大空闲连接
        max-idle: 8
        # 连接池中的最小空闲连接
        min-idle: 1
      #关闭超时
      shutdown-timeout: 500ms

4、集成使用

@RestController
public class Controller {

    @Resource
    private RedisTemplate redisTemplate;

    @RequestMapping("redis")
    public String redis() {
        // 测试redis
        String key = "uid";
        String value = "测试用户";
        // 设置值
        redisTemplate.boundValueOps(key).set(value);
        // 取出值
        Object obj = redisTemplate.opsForValue().get(key);
        System.out.println("取出值为:" + obj);
        return "操作成功";
    }
}

5、工具类封装及使用

实际开发中,使用redis的场景会比较多,可以将reidsTemplate的操作封装为工具类,代码如下:

5.1、工具封装

import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;

import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;


@Component
public class RedisUtils {

    private static RedisTemplate redisTemplate = null;

    public RedisUtils(RedisTemplate redisTemplate) {
        RedisUtils.redisTemplate = redisTemplate;
    }

    public static RedisTemplate getRedisTemplate() {
        return redisTemplate;
    }

    /**
     * 指定缓存失效时间
     *
     * @param key  键
     * @param time 时间(秒)
     * @return
     */
    public static boolean expire(String key, long time, TimeUnit unit) {
        try {
            if (time > 0) {
                redisTemplate.expire(key, time, unit);
            }
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    /**
     * 根据key 获取过期时间
     *
     * @param key 键 不能为null
     * @return 时间(秒) 返回0代表为永久有效
     */
    public static long getExpire(String key) {
        return redisTemplate.getExpire(key, TimeUnit.SECONDS);
    }

    /**
     * 根据key 获取过期时间
     *
     * @param key 键 不能为null
     * @return TimeUnit
     */
    public static long getExpire(String key, TimeUnit timeUnit) {
        return redisTemplate.getExpire(key, timeUnit);
    }

    /**
     * 判断key是否存在
     *
     * @param key 键
     * @return true 存在 false不存在
     */
    public static boolean hasKey(String key) {
        try {
            return redisTemplate.hasKey(key);
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    /**
     * 删除缓存
     *
     * @param key 可以传一个值 或多个
     */
    public static void del(String... key) {
        if (key != null && key.length > 0) {
            if (key.length == 1) {
                redisTemplate.delete(key[0]);
            } else {
                redisTemplate.delete(CollectionUtils.arrayToList(key));
            }
        }
    }

    /**
     * 普通缓存获取
     *
     * @param key 键
     * @return 值
     */
    public static Object get(String key) {
        return key == null ? null : redisTemplate.opsForValue().get(key);
    }

    /**
     * 普通缓存放入
     *
     * @param key   键
     * @param value 值
     * @return true成功 false失败
     */
    public static boolean set(String key, Object value) {
        try {
            redisTemplate.boundValueOps(key).set(value);
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    /**
     * 将值 value 关联到 key ,并将 key 的过期时间设为 timeout
     *
     * @param key
     * @param value
     * @param timeout 过期时间
     * @param unit    时间单位, 天:TimeUnit.DAYS 小时:TimeUnit.HOURS 分钟:TimeUnit.MINUTES
     *                秒:TimeUnit.SECONDS 毫秒:TimeUnit.MILLISECONDS
     */
    public static boolean setEx(String key, Object value, long timeout, TimeUnit unit) {
        try {
            set(key, value);
            if (timeout > 0) {
                expire(key, timeout, unit);
            }
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    /**
     * 向一张hash表中放入数据,如果不存在将创建
     *
     * @param key   键
     * @param item  项
     * @param value 值
     * @return true 成功 false失败
     */
    public static boolean hset(String key, String item, Object value) {
        try {
            redisTemplate.boundHashOps(key).put(item, value);
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    public static boolean hset(String key, Map<String, String> map) {
        try {
            redisTemplate.boundHashOps(key).putAll(map);
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    /**
     * 将值 value 关联到 key ,并将 key 的过期时间设为 timeout
     *
     * @param key
     * @param value
     * @param timeout 过期时间
     * @param unit    时间单位, 天:TimeUnit.DAYS 小时:TimeUnit.HOURS 分钟:TimeUnit.MINUTES
     *                秒:TimeUnit.SECONDS 毫秒:TimeUnit.MILLISECONDS
     */
    public static boolean hSetEx(String key, String item, Object value, long timeout, TimeUnit unit) {
        try {
            hset(key, item, value);
            if (timeout > 0) {
                expire(key, timeout, unit);
            }
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    /**
     * 获取所有给定字段的值
     *
     * @param key
     * @return
     */
    public static Map<Object, Object> hGetAll(String key) {
        return redisTemplate.boundHashOps(key).entries();
    }

    /**
     * 获取所有哈希表中的字段
     *
     * @param key
     * @return
     */
    public static Set<Object> hKeys(String key) {
        return redisTemplate.boundHashOps(key).keys();
    }

    /**
     * 获取哈希表中字段的数量
     *
     * @param key
     * @return
     */
    public static Long hSize(String key) {
        return redisTemplate.boundHashOps(key).size();
    }

    /**
     * 获取哈希表中所有值
     *
     * @param key
     * @return
     */
    public static List<Object> hValues(String key) {
        return redisTemplate.boundHashOps(key).values();
    }

    /**
     * 向一张hash表中读取数据
     */
    public static Object hget(String key, String item) {
        try {
            return redisTemplate.boundHashOps(key).get(item);
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }


    /**
     * 删除hash表中的值
     *
     * @param key  键 不能为null
     * @param item 项 可以使多个 不能为null
     */
    public static void hdel(String key, Object... item) {
        redisTemplate.boundHashOps(key).delete(item);
    }

    /**
     * 判断hash表中是否有该项的值
     *
     * @param key  键 不能为null
     * @param item 项 不能为null
     * @return true 存在 false不存在
     */
    public static boolean hHasKey(String key, String item) {
        return redisTemplate.boundHashOps(key).hasKey(item);
    }

    /**
     * 递增
     *
     * @param key 键
     *            //     * @param by 要增加几(大于0)
     * @return
     */
    public static long incr(String key, long increment) {
        if (increment < 0) {
            throw new RuntimeException("递增因子必须大于0");
        }
        return redisTemplate.boundValueOps(key).increment(increment);
    }

    /**
     * 为哈希表 key 中的指定字段的整数值加上增量 increment
     *
     * @param key
     * @param field
     * @param increment
     * @return
     */
    public static long hIncrBy(String key, Object field, long increment) {
        if (increment < 0) {
            throw new RuntimeException("递增因子必须大于0");
        }
        return redisTemplate.boundHashOps(key).increment(field, increment);
    }
}

5.2、封装使用

通过工具类直接操作Redis

@RestController
public class Controller {
    @RequestMapping("redis")
    public String redis() {
        // 测试redis
        String key = "uid";
        String value = "测试用户";
        // 设置值
        RedisUtils.set(key, value);
        // 取出值
        Object obj = RedisUtils.get(key);
        System.out.println("取出值为:" + obj);
        return "操作成功";
    }
}

总结

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

相关文章

  • 在Spring Boot中加载初始化数据的实现

    在Spring Boot中加载初始化数据的实现

    这篇文章主要介绍了在Spring Boot中加载初始化数据的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-02-02
  • 详细讲解Java输入语句的写法

    详细讲解Java输入语句的写法

    作为初步进入java开发学习的小白来说,学习java语言一开始的时候得一步步的学习,比如说java输入语句应该这么去实现呢,这篇文章主要给大家介绍了关于Java输入语句的相关资料,需要的朋友可以参考下
    2024-03-03
  • Spring缓存机制实例代码

    Spring缓存机制实例代码

    这篇文章主要介绍了Spring缓存机制实例代码,分享了相关代码示例,小编觉得还是挺不错的,具有一定借鉴价值,需要的朋友可以参考下
    2018-02-02
  • springboot 注册服务注册中心(zk)的两种方式详解

    springboot 注册服务注册中心(zk)的两种方式详解

    本文通过一个demo讲述一下这两种注册方式,使用的是传统的向zk注册的方案。对springboot 注册zk的相关知识感兴趣的朋友一起看看吧
    2018-01-01
  • Java中使用Socket发送Java对象实例

    Java中使用Socket发送Java对象实例

    这篇文章主要介绍了Java中使用Socket发送Java对象实例,本文使用对象流直接发送对象,本文同时给出代码实例,需要的朋友可以参考下
    2015-05-05
  • java中使用zxing批量生成二维码立牌

    java中使用zxing批量生成二维码立牌

    本篇文章主要介绍了java中使用zxing批量生成二维码立牌,非常具有实用价值,需要的朋友可以参考下。
    2016-12-12
  • Spring interceptor拦截器配置及用法解析

    Spring interceptor拦截器配置及用法解析

    这篇文章主要介绍了Spring interceptor拦截器配置及用法解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-10-10
  • package打包一个springcloud项目的某个微服务报错问题

    package打包一个springcloud项目的某个微服务报错问题

    这篇文章主要介绍了package打包一个springcloud项目的某个微服务报错问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2024-07-07
  • Java8如何构建一个Stream示例详解

    Java8如何构建一个Stream示例详解

    Java 8 是迄今为止在语义上改动上最大的一个平台。下面这篇文章主要给大家介绍了关于Java8如何构建一个Stream的相关资料,文中通过示例代码介绍的非常详细,需要的朋友可以参考借鉴,下面随着小编来一起学习学习吧。
    2018-04-04
  • springboot在filter中如何用threadlocal存放用户身份信息

    springboot在filter中如何用threadlocal存放用户身份信息

    这篇文章主要介绍了springboot中在filter中如何用threadlocal存放用户身份信息,本文章主要描述通过springboot的filter类,在过滤器中设置jwt信息进行身份信息保存的方法,需要的朋友可以参考下
    2024-07-07

最新评论