当前位置: 代码网 > it编程>编程语言>Java > SpringBoot整合Redis的实践

SpringBoot整合Redis的实践

2026年03月02日 Java 我要评论
前言redis(remote dictionary server)是一个开源的内存数据库(in-memory database),也被称为数据结构服务器,它支持存储键值对,并提供多种数据结构的操作。r

前言

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 "操作成功";
    }
}

总结

以上为个人经验,希望能给大家一个参考,也希望大家多多支持代码网。

(0)

相关文章:

版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。

发表评论

验证码:
Copyright © 2017-2026  代码网 保留所有权利. 粤ICP备2024248653号
站长QQ:2386932994 | 联系邮箱:2386932994@qq.com