当前位置: 代码网 > it编程>编程语言>Java > SpringBoot集成Redis使用Lettuce详解

SpringBoot集成Redis使用Lettuce详解

2026年05月09日 Java 我要评论
redis是最常用的kv数据库,spring 通过模板方式(redistemplate)提供了对redis的数据查询和操作功能。本文主要介绍基于redistemplate + lettuce方式对re

redis是最常用的kv数据库,spring 通过模板方式(redistemplate)提供了对redis的数据查询和操作功能。

本文主要介绍基于redistemplate + lettuce方式对redis进行查询和操作的案例。

一、redis基础数据类型

首先对redis来说,所有的key(键)都是字符串。我们在谈基础数据结构时,讨论的是存储值的数据类型,主要包括常见的5种数据类型,分别是:string、list、set、zset、hash。

结构类型

结构存储的值

结构的读写能力

string字符串

可以是字符串、整数或浮点数

对整个字符串或字符串的一部分进行操作;对整数或浮点数进行自增或自减操作;

list列表

一个链表,链表上的每个节点都包含一个字符串

对链表的两端进行push和pop操作,读取单个或多个元素;根据值查找或删除元素;

set集合

包含字符串的无序集合

字符串的集合,包含基础的方法有看是否存在添加、获取、删除;还包含计算交集、并集、差集等

hash散列

包含键值对的无序散列表

包含方法有添加、获取、删除单个元素

zset有序集合

和散列一样,用于存储键值对

字符串成员与浮点数分数之间的有序映射;元素的排列顺序由分数的大小决定;包含方法有添加、获取、删除单个元素以及根据分值范围或成员来获取元素

二、redis常用连接池

  • jedis:是redis的java实现客户端,提供了比较全面的redis命令的支持。
  • redisson:实现了分布式和可扩展的java数据结构。
  • lettuce:高级redis客户端,用于线程安全同步,异步和响应使用,支持集群,sentinel,管道和编码器。

三、springboot集成redis案例

1、yml配置常量:

redis:
  # 地址
  host: 192.168.1.66
  # 端口,默认为6379
  port: 6379
  # 数据库索引
  database: 0
  # 密码(如没有密码请注释掉)
  password: 123456
  # 连接超时时间
  timeout: 3000
  # 是否开启ssl
  ssl: false
  lettuce:
    pool:
      max-active: 1000  # 连接池最大连接数(使用负值表示没有限制)
      max-wait: -1   # 连接池最大阻塞等待时间(使用负值表示没有限制)
      max-idle: 10      # 连接池中的最大空闲连接
      min-idle: 5       # 连接池中的最小空闲连接

2、pom.xml引入依赖:

<!--redis依赖-->
<dependency>
    <groupid>org.springframework.boot</groupid>
    <artifactid>spring-boot-starter-data-redis</artifactid>
    <version>2.4.0</version>
</dependency>
<!--连接池依赖-->
<dependency>
    <groupid>org.apache.commons</groupid>
    <artifactid>commons-pool2</artifactid>
    <version>2.8.0</version>
</dependency>

3、redisconfig配置类:

package com.cn.common.conf;

import com.alibaba.fastjson.parser.parserconfig;
import com.alibaba.fastjson.support.config.fastjsonconfig;
import com.alibaba.fastjson.support.spring.fastjsonredisserializer;
import org.apache.commons.pool2.impl.genericobjectpoolconfig;
import org.springframework.beans.factory.annotation.value;
import org.springframework.cache.annotation.enablecaching;
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.lettuce.lettuceconnectionfactory;
import org.springframework.data.redis.connection.lettuce.lettucepoolingclientconfiguration;
import org.springframework.data.redis.core.redistemplate;
import org.springframework.data.redis.serializer.redisserializer;
import org.springframework.data.redis.serializer.stringredisserializer;

import java.nio.charset.standardcharsets;
import java.time.duration;


/**
 * redis配置类
 *
 * @author zq
 */

@configuration
@enablecaching
public class redisconfig {

    // 倘若 spring.redis.host 不存在,则会默认为127.0.0.1.
    @value("${spring.redis.host:#{'127.0.0.1'}}")
    private string hostname;

    @value("${spring.redis.port:#{6379}}")
    private int port;

    @value("${spring.redis.password:#{123456}}")
    private string password;

    @value("${spring.redis.timeout:#{3000}}")
    private int timeout;

    @value("${spring.redis.lettuce.pool.max-idle:#{16}}")
    private int maxidle;

    @value("${spring.redis.lettuce.pool.min-idle:#{1}}")
    private int minidle;

    @value("${spring.redis.lettuce.pool.max-wait:#{16}}")
    private long maxwaitmillis;

    @value("${spring.redis.lettuce.pool.max-active:#{16}}")
    private int maxactive;

    @value("${spring.redis.database:#{0}}")
    private int databaseid;

    @bean
    public lettuceconnectionfactory lettuceconnectionfactory() {

        redisconfiguration redisconfiguration = new redisstandaloneconfiguration(
            hostname, port
        );

        // 设置选用的数据库号码
        ((redisstandaloneconfiguration) redisconfiguration).setdatabase(databaseid);

        // 设置 redis 数据库密码
        ((redisstandaloneconfiguration) redisconfiguration).setpassword(password);

        // 连接池配置
        genericobjectpoolconfig<object> poolconfig = new genericobjectpoolconfig<>();
        poolconfig.setmaxidle(maxidle);
        poolconfig.setminidle(minidle);
        poolconfig.setmaxtotal(maxactive);
        poolconfig.setmaxwaitmillis(maxwaitmillis);

        lettucepoolingclientconfiguration.lettucepoolingclientconfigurationbuilder builder
            = lettucepoolingclientconfiguration.builder()
            .commandtimeout(duration.ofmillis(timeout));

        lettucepoolingclientconfiguration lettucepoolingclientconfiguration = builder.build();

        builder.poolconfig(poolconfig);

        // 根据配置和客户端配置创建连接
        lettuceconnectionfactory factory = new lettuceconnectionfactory(redisconfiguration, lettucepoolingclientconfiguration);
        return factory;
    }

    /**
     * springboot2.x 使用lettuceconnectionfactory 代替 redisconnectionfactory
     * application.yml配置基本信息后,springboot2.x  redisautoconfiguration能够自动装配
     * lettuceconnectionfactory 和 redisconnectionfactory 及其 redistemplate
     *
     * @param
     * @return
     */
    @bean(name = "redistemplate")
    public redistemplate<string, object> redistemplate(
        lettuceconnectionfactory lettuceconnectionfactory
    ) {

        redistemplate<string, object> redistemplate = new redistemplate<>();
        redistemplate.setconnectionfactory(lettuceconnectionfactory);

        // 使用 fastjsonredisserializer 来序列化和反序列化redis 的 value的值
        fastjsonredisserializer<object> serializer = new fastjsonredisserializer<>(object.class);
        parserconfig.getglobalinstance().addaccept("com.muzz");
        fastjsonconfig fastjsonconfig = new fastjsonconfig();
        fastjsonconfig.setcharset(standardcharsets.utf_8);
        serializer.setfastjsonconfig(fastjsonconfig);

        // key 的 string 序列化采用 stringredisserializer
        stringredisserializer stringredisserializer = new stringredisserializer();
        redistemplate.setkeyserializer(stringredisserializer);
        redistemplate.sethashkeyserializer(stringredisserializer);

        // value 的值序列化采用 fastjsonredisserializer
        redistemplate.setvalueserializer(serializer);
        redistemplate.sethashvalueserializer(serializer);

        redistemplate.afterpropertiesset();

        system.out.println(redistemplate.getdefaultserializer());

        return redistemplate;
    }

    @bean
    public redisserializer<object> springsessiondefaultredisserializer() {

        // 使用 fastjsonredisserializer 来序列化和反序列化redis 的 value的值
        fastjsonredisserializer<object> serializer = new fastjsonredisserializer<>(object.class);
        parserconfig.getglobalinstance().addaccept("com.muzz");
        fastjsonconfig fastjsonconfig = new fastjsonconfig();
        fastjsonconfig.setcharset(standardcharsets.utf_8);
        serializer.setfastjsonconfig(fastjsonconfig);
        return serializer;
    }


}

4、redisutil工具类:

package com.cn.util;

import lombok.requiredargsconstructor;
import org.springframework.beans.factory.annotation.autowired;
import org.springframework.data.redis.core.redistemplate;
import org.springframework.data.redis.core.stringredistemplate;
import org.springframework.data.redis.serializer.redisserializer;
import org.springframework.data.redis.serializer.stringredisserializer;
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;

/**
 * @ description: 基于spring和redis的redistemplate工具类
 * 针对所有的hash 都是以h开头的方法
 * 针对所有的set 都是以s开头的方法                    不含通用方法
 * 针对所有的list 都是以l开头的方法
 * @ modified by:
 */
@component
@requiredargsconstructor
public class redisutils {


    private redistemplate redistemplate;


    private final stringredistemplate stringredistemplate;

    @autowired(required = false)
    public void setredistemplate(redistemplate redistemplate) {
        redisserializer stringserializer = new stringredisserializer();
        redistemplate.setkeyserializer(stringserializer);
        redistemplate.sethashkeyserializer(stringserializer);
        this.redistemplate = redistemplate;
    }

    /**
     * 获取key
     * @param patten
     * @return
     */
    public set keys(string patten){
        return stringredistemplate.keys(patten);
    }

    /**
     * 指定缓存失效时间
     *
     * @param key  键
     * @param time 时间(秒)
     *
     */
    public boolean expire(string key, long time) {
        try {
            if (time > 0) {
                redistemplate.expire(key, time, timeunit.seconds);
            }
            return true;
        } catch (exception e) {
            e.printstacktrace();
            return false;
        }
    }

    /**
     * 根据key 获取过期时间
     *
     * @param key 键 不能为null
     * @return 时间(秒) 返回0代表为永久有效
     */
    public long getexpire(string key) {
        return redistemplate.getexpire(key, timeunit.seconds);
    }

    /**
     * 判断key是否存在
     *
     * @param key 键
     * @return true 存在 false不存在
     */
    public boolean haskey(string key) {
        try {
            return redistemplate.haskey(key);
        } catch (exception e) {
            e.printstacktrace();
            return false;
        }
    }

    /**
     * 删除缓存
     *
     * @param key 可以传一个值 或多个
     */
    @suppresswarnings("unchecked")
    public void del(string... key) {
        if (key != null && key.length > 0) {
            if (key.length == 1) {
                redistemplate.delete(key[0]);
            } else {
                redistemplate.delete(collectionutils.arraytolist(key));
            }
        }
    }

    //============================string=============================

    /**
     * 普通缓存获取
     *
     * @param key 键
     * @return 值
     */
    public object get(string key) {
        return key == null ? null : redistemplate.opsforvalue().get(key);
    }

    /**
     * 普通缓存放入
     *
     * @param key   键
     * @param value 值
     * @return true成功 false失败
     */
    public boolean set(string key, object value) {
        try {
            redistemplate.opsforvalue().set(key, value);
            return true;
        } catch (exception e) {
            e.printstacktrace();
            return false;
        }

    }

    /**
     * 普通缓存放入并设置时间
     *
     * @param key   键
     * @param value 值
     * @param time  时间(秒) time要大于0 如果time小于等于0 将设置无限期
     * @return true成功 false 失败
     */
    public boolean set(string key, object value, long time) {
        try {
            if (time > 0) {
                redistemplate.opsforvalue().set(key, value, time, timeunit.seconds);
            } else {
                set(key, value);
            }
            return true;
        } catch (exception e) {
            e.printstacktrace();
            return false;
        }
    }

    /**
     * 递增
     *
     * @param key   键
     * @param delta 要增加几(大于0)
     * @return
     */
    public long incr(string key, long delta) {
        if (delta < 0) {
            throw new runtimeexception("递增因子必须大于0");
        }
        return redistemplate.opsforvalue().increment(key, delta);
    }

    /**
     * 递减
     *
     * @param key   键
     * @param delta 要减少几(小于0)
     * @return
     */
    public long decr(string key, long delta) {
        if (delta < 0) {
            throw new runtimeexception("递减因子必须大于0");
        }
        return redistemplate.opsforvalue().increment(key, -delta);
    }

    //================================map=================================

    /**
     * hashget
     *
     * @param key  键 不能为null
     * @param item 项 不能为null
     * @return 值
     */
    public object hget(string key, string item) {
        return redistemplate.opsforhash().get(key, item);
    }

    /**
     * 获取hashkey对应的所有键值
     *
     * @param key 键
     * @return 对应的多个键值
     */
    public map<object, object> hmget(string key) {
        return redistemplate.opsforhash().entries(key);
    }

    /**
     * hashset
     *
     * @param key 键
     * @param map 对应多个键值
     * @return true 成功 false 失败
     */
    public boolean hmset(string key, map<string, object> map) {
        try {
            redistemplate.opsforhash().putall(key, map);
            return true;
        } catch (exception e) {
            e.printstacktrace();
            return false;
        }
    }

    /**
     * hashset 并设置时间
     *
     * @param key  键
     * @param map  对应多个键值
     * @param time 时间(秒)
     * @return true成功 false失败
     */
    public boolean hmset(string key, map<string, object> map, long time) {
        try {
            redistemplate.opsforhash().putall(key, map);
            if (time > 0) {
                expire(key, time);
            }
            return true;
        } catch (exception e) {
            e.printstacktrace();
            return false;
        }
    }

    /**
     * 向一张hash表中放入数据,如果不存在将创建
     *
     * @param key   键
     * @param item  项
     * @param value 值
     * @return true 成功 false失败
     */
    public boolean hset(string key, string item, object value) {
        try {
            redistemplate.opsforhash().put(key, item, value);
            return true;
        } catch (exception e) {
            e.printstacktrace();
            return false;
        }
    }

    /**
     * 向一张hash表中放入数据,如果不存在将创建
     *
     * @param key   键
     * @param item  项
     * @param value 值
     * @param time  时间(秒)  注意:如果已存在的hash表有时间,这里将会替换原有的时间
     * @return true 成功 false失败
     */
    public boolean hset(string key, string item, object value, long time) {
        try {
            redistemplate.opsforhash().put(key, item, value);
            if (time > 0) {
                expire(key, time);
            }
            return true;
        } catch (exception e) {
            e.printstacktrace();
            return false;
        }
    }

    /**
     * 删除hash表中的值
     *
     * @param key  键 不能为null
     * @param item 项 可以使多个 不能为null
     */
    public void hdel(string key, object... item) {
        redistemplate.opsforhash().delete(key, item);
    }

    /**
     * 判断hash表中是否有该项的值
     *
     * @param key  键 不能为null
     * @param item 项 不能为null
     * @return true 存在 false不存在
     */
    public boolean hhaskey(string key, string item) {
        return redistemplate.opsforhash().haskey(key, item);
    }

    /**
     * hash递增 如果不存在,就会创建一个 并把新增后的值返回
     *
     * @param key  键
     * @param item 项
     * @param by   要增加几(大于0)
     * @return
     */
    public double hincr(string key, string item, double by) {
        return redistemplate.opsforhash().increment(key, item, by);
    }

    /**
     * hash递减
     *
     * @param key  键
     * @param item 项
     * @param by   要减少记(小于0)
     * @return
     */
    public double hdecr(string key, string item, double by) {
        return redistemplate.opsforhash().increment(key, item, -by);
    }

    //============================set=============================

    /**
     * 根据key获取set中的所有值
     *
     * @param key 键
     * @return
     */
    public set<object> sget(string key) {
        try {
            return redistemplate.opsforset().members(key);
        } catch (exception e) {
            e.printstacktrace();
            return null;
        }
    }

    /**
     * 根据value从一个set中查询,是否存在
     *
     * @param key   键
     * @param value 值
     * @return true 存在 false不存在
     */
    public boolean shaskey(string key, object value) {
        try {
            return redistemplate.opsforset().ismember(key, value);
        } catch (exception e) {
            e.printstacktrace();
            return false;
        }
    }

    /**
     * 将数据放入set缓存
     *
     * @param key    键
     * @param values 值 可以是多个
     * @return 成功个数
     */
    public long sset(string key, object... values) {
        try {
            return redistemplate.opsforset().add(key, values);
        } catch (exception e) {
            e.printstacktrace();
            return 0;
        }
    }

    /**
     * 将set数据放入缓存
     *
     * @param key    键
     * @param time   时间(秒)
     * @param values 值 可以是多个
     * @return 成功个数
     */
    public long ssetandtime(string key, long time, object... values) {
        try {
            long count = redistemplate.opsforset().add(key, values);
            if (time > 0) expire(key, time);
            return count;
        } catch (exception e) {
            e.printstacktrace();
            return 0;
        }
    }

    /**
     * 获取set缓存的长度
     *
     * @param key 键
     * @return
     */
    public long sgetsetsize(string key) {
        try {
            return redistemplate.opsforset().size(key);
        } catch (exception e) {
            e.printstacktrace();
            return 0;
        }
    }

    /**
     * 移除值为value的
     *
     * @param key    键
     * @param values 值 可以是多个
     * @return 移除的个数
     */
    public long setremove(string key, object... values) {
        try {
            long count = redistemplate.opsforset().remove(key, values);
            return count;
        } catch (exception e) {
            e.printstacktrace();
            return 0;
        }
    }
    //===============================list=================================

    /**
     * 获取list缓存的内容
     *
     * @param key   键
     * @param start 开始
     * @param end   结束  0 到 -1代表所有值
     * @return
     */
    public list<object> lget(string key, long start, long end) {
        try {
            return redistemplate.opsforlist().range(key, start, end);
        } catch (exception e) {
            e.printstacktrace();
            return null;
        }
    }

    /**
     * 获取list缓存的长度
     *
     * @param key 键
     * @return
     */
    public long lgetlistsize(string key) {
        try {
            return redistemplate.opsforlist().size(key);
        } catch (exception e) {
            e.printstacktrace();
            return 0;
        }
    }

    /**
     * 通过索引 获取list中的值
     *
     * @param key   键
     * @param index 索引  index>=0时, 0 表头,1 第二个元素,依次类推;index<0时,-1,表尾,-2倒数第二个元素,依次类推
     * @return
     */
    public object lgetindex(string key, long index) {
        try {
            return redistemplate.opsforlist().index(key, index);
        } catch (exception e) {
            e.printstacktrace();
            return null;
        }
    }

    /**
     * 将list放入缓存
     *
     * @param key   键
     * @param value 值
     * @return
     */
    public boolean lset(string key, object value) {
        try {
            redistemplate.opsforlist().rightpush(key, value);
            return true;
        } catch (exception e) {
            e.printstacktrace();
            return false;
        }
    }

    /**
     * 将list放入缓存
     *
     * @param key   键
     * @param value 值
     * @param time  时间(秒)
     * @return
     */
    public boolean lset(string key, object value, long time) {
        try {
            redistemplate.opsforlist().rightpush(key, value);
            if (time > 0) expire(key, time);
            return true;
        } catch (exception e) {
            e.printstacktrace();
            return false;
        }
    }

    /**
     * 将list放入缓存
     *
     * @param key   键
     * @param value 值
     * @return
     */
    public boolean lset(string key, list<object> value) {
        try {
            redistemplate.opsforlist().rightpushall(key, value);
            return true;
        } catch (exception e) {
            e.printstacktrace();
            return false;
        }
    }

    /**
     * 将list放入缓存
     *
     * @param key   键
     * @param value 值
     * @param time  时间(秒)
     * @return
     */
    public boolean lset(string key, list<object> value, long time) {
        try {
            redistemplate.opsforlist().rightpushall(key, value);
            if (time > 0) expire(key, time);
            return true;
        } catch (exception e) {
            e.printstacktrace();
            return false;
        }
    }

    /**
     * 根据索引修改list中的某条数据
     *
     * @param key   键
     * @param index 索引
     * @param value 值
     * @return
     */
    public boolean lupdateindex(string key, long index, object value) {
        try {
            redistemplate.opsforlist().set(key, index, value);
            return true;
        } catch (exception e) {
            e.printstacktrace();
            return false;
        }
    }

    /**
     * 移除n个值为value
     *
     * @param key   键
     * @param count 移除多少个
     * @param value 值
     * @return 移除的个数
     */
    public long lremove(string key, long count, object value) {
        try {
            long remove = redistemplate.opsforlist().remove(key, count, value);
            return remove;
        } catch (exception e) {
            e.printstacktrace();
            return 0;
        }
    }
}

总结

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

(0)

相关文章:

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

发表评论

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