第八章 中间件:SpringBoot 集成 Redis


  (如果没有了解可以去我主页看看 第一至七章的内容来学习)通过前面七章的学习,我们已经掌握了SpringBoot的基础知识,数据访问层技术:JPA、MyBAtis、MyBAtis-Plus,表示层技术:控制器开发、视图(JSP)开发、过滤器和拦截器开发以及Thymeleaf模板技术,可以说基于SpringBoot开发常规的Web应用我们已经有了全面的掌握。

8.1 Redis简介

  Redis 是一个开源的、基于内存的、键值对存储系统,它可以用作数据库、缓存和消息中间件。Redis 支持多种类型的数据结构,如字符串(strings)、哈希(hashes)、列表(lists)、集合(sets)、有序集合(sorted sets)等。由于它存储在内存中,Redis 的性能非常高,但同时也意味着它的数据是易失的,不过 Redis 提供了持久化机制(如 RDB 快照和 AOF 日志)来防止数据丢失。

以下是一个简单的 Java 示例,展示了如何使用 Jedis(一个流行的 Redis Java 客户端)来连接 Redis 并执行一些基本操作。

首先,确保你已经在你的机器上安装了 Redis 服务器,并且它正在运行。此外,你还需要在你的 Java 项目中添加 Jedis 依赖。如果你使用 Maven,可以在你的 pom.xml 文件中添加以下依赖:

<dependency>  
    <groupId>redis.clients</groupId>  
    <artifactId>jedis</artifactId>  
    <version>最新版本号</version> <!-- 请替换为最新版本号 -->  
</dependency>

然后,你可以使用以下 Java 代码连接到 Redis 并执行一些操作:

import redis.clients.jedis.Jedis;  
  
public class RedisExample {  
    public static void main(String[] args) {  
        // 连接到 Redis 服务器  
        // 这里的 "localhost" 是 Redis 服务器地址,6379 是 Redis 服务的默认端口  
        // 如果你的 Redis 设置了密码,可以使用 Jedis(String host, int port, int timeout, String password) 构造函数  
        try (Jedis jedis = new Jedis("localhost", 6379)) {  
            System.out.println("连接成功");  
  
            // 设置键值对  
            String result = jedis.set("mykey", "hello");  
            System.out.println("SET mykey hello: " + result);  
  
            // 获取键对应的值  
            String value = jedis.get("mykey");  
            System.out.println("GET mykey: " + value);  
  
            // 列表操作  
            jedis.lpush("mylist", "one");  
            jedis.lpush("mylist", "two");  
            jedis.lpush("mylist", "three");  
  
            // 获取列表中的所有元素  
            List<String> list = jedis.lrange("mylist", 0, -1);  
            System.out.println("LRANGE mylist 0 -1: " + list);  
  
            // 哈希操作  
            jedis.hset("myhash", "field1", "value1");  
            jedis.hset("myhash", "field2", "value2");  
  
            // 获取哈希表中字段的值  
            String field1Value = jedis.hget("myhash", "field1");  
            System.out.println("HGET myhash field1: " + field1Value);  
  
            // 遍历哈希表中的所有字段和值  
            Map<String, String> hashMap = jedis.hgetAll("myhash");  
            for (Map.Entry<String, String> entry : hashMap.entrySet()) {  
                System.out.println("HGETALL myhash: " + entry.getKey() + "=" + entry.getValue());  
            }  
  
            // 其他操作...  
  
        } catch (Exception e) {  
            e.printStackTrace();  
        }  
    }  
}

请注意:为了简化示例,我们没有包含异常处理的详细代码,但在实际应用中,你应该总是适当地处理或记录异常。

此外,try-with-resources 语句确保了 Jedis 连接在 try 代码块执行完毕后会被自动关闭,这是一种良好的资源管理实践。

请确保 Redis 服务器正在运行,并且你的 Java 应用程序能够访问它(包括网络权限和端口配置)。如果你在本机运行 Redis 并且没有修改任何默认设置,上面的代码应该可以正常工作。

8.1.1 数据类型

  Redis数据类型不仅与关系数据库管理系统(RDBMS)不同,也不同于任何简单的NoSQL键-值数据存储。Redis数据类型似于编程语言的基础数据类型,因此开发人员感觉很自然,每个数据类型都支持用于其类型的操作,受支持的数据类型包括:

  • String (字符串)
    字符串是 Redis 中最基本的数据类型,它可以包含任何形式的数据,如文本、数字等。
import redis.clients.jedis.Jedis;  
  
public class RedisStringExample {  
    public static void main(String[] args) {  
        try (Jedis jedis = new Jedis("localhost", 6379)) {  
            // 设置字符串  
            String response = jedis.set("myString", "Hello, Redis!");  
            System.out.println("SET myString Hello, Redis!: " + response);  
  
            // 获取字符串  
            String value = jedis.get("myString");  
            System.out.println("GET myString: " + value);  
        }  
    }  
}
  • Hash (哈希)
    在Redis中,哈希(Hash)类型允许你将多个字段(field)和值(value)对存储在一个键(key)下,这非常类似于Java中的Map<String, String>或HashMap<String, String>数据结构。在Java中,使用Redis客户端(如Jedis)操作Hash类型的数据时,你可以通过相应的API来实现字段的添加、删除、更新和获取等操作。

以下是一个使用Jedis操作Redis Hash类型的Java代码示例:

import redis.clients.jedis.Jedis;  
  
public class RedisHashExample {  
    public static void main(String[] args) {  
        try (Jedis jedis = new Jedis("localhost", 6379)) {  
            // 向Hash中添加字段和值  
            jedis.hset("myHash", "field1", "value1");  
            jedis.hset("myHash", "field2", "value2");  
  
            // 获取Hash中指定字段的值  
            String value1 = jedis.hget("myHash", "field1");  
            System.out.println("HGET myHash field1: " + value1);  
  
            // 获取Hash中所有字段和值  
            Map<String, String> allEntries = jedis.hgetAll("myHash");  
            System.out.println("HGETALL myHash: " + allEntries);  
  
            // 删除Hash中的指定字段  
            jedis.hdel("myHash", "field1");  
  
            // 再次获取Hash中所有字段和值,查看删除效果  
            allEntries = jedis.hgetAll("myHash");  
            System.out.println("HGETALL myHash after deleting field1: " + allEntries);  
  
            // 判断Hash中是否存在指定字段  
            Boolean exists = jedis.hexists("myHash", "field2");  
            System.out.println("HEXISTS myHash field2: " + exists);  
  
            // 获取Hash中字段的数量  
            Long size = jedis.hlen("myHash");  
            System.out.println("HLEN myHash: " + size);  
  
            // 为Hash中的字段设置值(如果字段不存在则创建)  
            jedis.hsetnx("myHash", "field3", "value3");  
  
            // 再次获取Hash中所有字段和值,查看新增效果  
            allEntries = jedis.hgetAll("myHash");  
            System.out.println("HGETALL myHash after setting field3: " + allEntries);  
  
            // 为Hash中的字段增加整数值(适用于整数字段)  
            jedis.hincrBy("myHash", "field3", 1); // 假设field3的值是整数  
  
            // 获取更新后的值  
            String value3 = jedis.hget("myHash", "field3");  
            System.out.println("HGET myHash field3 after increment: " + value3);  
        }  
    }  
}  
  
// 注意:上述代码中的Map<String, String>需要自行导入java.util.Map包

请注意:由于我直接在示例中使用了Map<String, String>而没有显示导入,你可能需要在你的Java文件中添加相应的导入语句:
import java.util.Map;

此外,上述代码示例中使用了try-with-resources语句来自动关闭Jedis连接,这是一种处理资源(如数据库连接、文件流等)的好方法,可以确保即使在发生异常时也能正确关闭资源。如果你的Jedis版本不支持自动关闭连接(尽管较新版本的Jedis通常支持),则需要在finally块中手动关闭连接。

  • List (列表)
    列表是简单的字符串列表,按照插入顺序排序。你可以向列表两端添加或从列表两端移除元素。
import redis.clients.jedis.Jedis;  
  
public class RedisListExample {  
    public static void main(String[] args) {  
        try (Jedis jedis = new Jedis("localhost", 6379)) {  
            // 向列表左侧添加元素  
            jedis.lpush("myList", "one", "two", "three");  
  
            // 获取列表中的所有元素  
            List<String> list = jedis.lrange("myList", 0, -1);  
            System.out.println("LRANGE myList 0 -1: " + list);  
  
            // 向列表右侧添加元素  
            jedis.rpush("myList", "four");  
  
            // 再次获取列表中的所有元素  
            list = jedis.lrange("myList", 0, -1);  
            System.out.println("LRANGE myList 0 -1 after rpush: " + list);  
        }  
    }  
}
  • Set (集合)
    集合是一个无序的字符串集合,集合中的元素是唯一的。
import redis.clients.jedis.Jedis;  
  
public class RedisSetExample {  
    public static void main(String[] args) {  
        try (Jedis jedis = new Jedis("localhost", 6379)) {  
            // 向集合中添加元素  
            jedis.sadd("mySet", "one", "two", "three");  
  
            // 获取集合中的所有元素  
            Set<String> set = jedis.smembers("mySet");  
            System.out.println("SMEMBERS mySet: " + set);  
  
            // 向集合中添加已存在的元素,不会增加集合大小  
            jedis.sadd("mySet", "two");  
  
            // 再次获取集合中的所有元素  
            set = jedis.smembers("mySet");  
            System.out.println("SMEMBERS mySet after adding duplicate: " + set);  
        }  
    }  
}

请注意:由于 Java 8 引入了 java.util.Set 接口,但 Jedis 返回的可能是一个实现了 Set 接口但并非 java.util.Set 的对象(例如,它可能是 Jedis 内部的一个集合实现),因此这里我使用了 Set 而不是具体的实现类(如 HashSet)。然而,在实际使用中,你通常可以像使用普通的 Java 集合那样使用它。

  • Sorted Set (有序集合)
    有序集合是字符串集合,每个元素都会关联一个双精度浮点数分数(score)。这使得集合中的元素能够按照分数进行排序。
import redis.clients.jedis.Jedis;  
import redis.clients.jedis.Tuple;  
import redis.clients.jedis.params.ZAddParams;  
  
import java.util.Set;  
  
public class RedisSortedSetExample {  
    public static void main(String[] args) {  
        try (Jedis jedis = new Jedis("localhost", 6379)) {  
            // 向有序集合中添加元素及其分数  
            jedis.zadd(new ZAddParams().nx(), "mySortedSet", 1.0, "one", 2.0, "two", 3.0, "three");  
  
            // 获取有序集合中的所有元素(按分数排序)  
            Set<Tuple> tuples = jedis.zrangeWithScores("mySortedSet", 0, -1);  
            for (Tuple tuple : tuples) {  
                System.out.println(tuple.getElement() + ": " + tuple.getScore());  
            }  
  
            // 更新元素的分数  
            jedis.zincrby("mySortedSet", 1.0, "two");  
  
            // 再次获取有序集合中的所有元素  
            tuples = jedis.zrangeWithScores("mySortedSet", 0, -1);  
            for (Tuple tuple : tuples) {  
                System.out.println(tuple.getElement() + ": " + tuple.getScore());  
            }  
        }  
    }  
}

请注意:由于篇幅限制,这里只提供了每种数据类型的基本操作示例。Jedis 提供了丰富的 API 来支持 Redis 的各种复杂操作,包括但不限于事务、管道、发布/订阅等。你可以查阅 Jedis 的官方文档来了解更多信息。

8.1.2 关键优势

  Redis是一个开源的、基于内存的键值对存储系统,它可以用作数据库、缓存和消息中间件。Redis 的关键优势包括高性能、丰富的数据结构支持(如字符串、列表、集合、哈希表、有序集合等)、持久化选项、以及支持多种语言的客户端库。

在Java中使用Redis,通常会用到Jedis或Lettuce这样的客户端库。这里我将提供一个简单的示例,展示如何使用Jedis库在Java代码中连接到Redis服务器,并执行一些基本操作,以体现Redis的关键优势。

首先,确保你已经将Jedis库添加到你的项目中。如果你使用Maven,可以在pom.xml中添加以下依赖:

<dependency>  
    <groupId>redis.clients</groupId>  
    <artifactId>jedis</artifactId>  
    <version>最新版本</version> <!-- 请替换为最新版本 -->  
</dependency>

接下来是一个简单的Java示例,展示如何连接到Redis并执行一些基本操作:

import redis.clients.jedis.Jedis;  
  
public class RedisExample {  
  
    public static void main(String[] args) {  
        // 连接到 Redis 服务器  
        // 假设 Redis 服务器运行在本地,默认端口 6379  
        Jedis jedis = new Jedis("localhost", 6379);  
  
        System.out.println("连接成功");  
  
        // 设置数据  
        jedis.set("foo", "bar");  
        System.out.println("存储的字符串为: " + jedis.get("foo"));  
  
        // 列表操作  
        jedis.lpush("mylist", "world");  
        jedis.lpush("mylist", "hello");  
        System.out.println(jedis.lrange("mylist", 0, -1));  
  
        // 哈希表操作  
        jedis.hset("myhash", "field1", "value1");  
        System.out.println(jedis.hget("myhash", "field1"));  
  
        // 关闭连接  
        jedis.close();  
    }  
}

  这个示例中,我们首先连接到Redis服务器(假设它运行在本地的默认端口6379)。然后,我们演示了如何使用Redis来存储和检索字符串、操作列表(使用LPUSH向列表左侧添加元素,LRANGE获取列表中的元素),以及操作哈希表(使用HSET添加哈希表的字段和值,HGET获取哈希表中字段的值)。

  这些操作展示了Redis作为内存数据存储的高性能特性,以及它支持的多种数据结构如何使得开发者能够灵活地存储和检索数据。此外,由于Redis是基于内存的,所以它的读写操作通常比传统的基于磁盘的数据库要快得多,这是Redis的另一个关键优势。

8.2 Redis 基本使用

8.2.1 Windows安装

在Windows系统上安装Redis主要包括下载、解压、配置(可选)和启动几个步骤。以下是一个详细的安装指南:

一、下载Redis

  1. 访问Redis官方网站:首先,你需要访问Redis的官方网站(https://redis.io/download)来下载Redis的Windows版本。然而,需要注意的是,Redis的官方GitHub仓库可能不包含直接用于Windows的安装包,但你可以找到指向其他资源的链接。
  2. 选择下载源:由于Redis官方可能不直接提供Windows的安装包,你可以选择从Microsoft Archive for Redis on Windows项目或其他可靠的源下载。这些资源通常会提供.zip压缩包或.msi安装包。例如,你可以从GitHub的MicrosoftArchive/redis仓库下载Redis的Windows版本。
  3. 下载Redis安装包:根据你的需求,选择下载.zip压缩包或.msi安装包。.msi安装包提供了图形界面的安装向导,而.zip压缩包则需要手动解压并配置。

二、解压Redis

  • 解压文件:如果你下载的是.zip压缩包,你需要将其解压到你希望安装Redis的文件夹中。例如,你可以将其解压到C:\Redis目录下。

三、配置Redis(可选)

  1. 编辑配置文件:Redis的配置主要通过编辑其配置文件(通常是redis.windows.conf或redis.conf)来完成。你可以使用文本编辑器打开该文件,并根据需要进行修改。

    • 设置密码:找到requirepass配置项,取消注释并设置你的密码。例如:requirepass yourpassword。
    • 修改绑定地址:如果需要Redis服务允许远程访问,可以将bind配置项从127.0.0.1改为0.0.0.0,但请注意这会增加安全风险。
    • 其他配置:根据需要调整端口号、内存限制、持久化策略等。
  2. 配置环境变量(可选):为了方便在命令行中直接使用Redis命令,你可以将Redis的安装目录添加到系统的PATH环境变量中。

四、启动Redis

  1. 临时启动: 在命令行中,进入Redis的安装目录,运行以下命令启动Redis服务器:
redis-server.exe redis.windows.conf

或者,如果不使用配置文件,直接运行:

redis-server.exe

但此时需要保持命令行窗口开启。

  1. 作为服务启动: 如果你希望Redis在Windows启动时自动运行,你可以将其注册为Windows服务。这可以通过在Redis安装目录下运行以下命令来完成:
redis-server --service-install redis.windows.conf --loglevel verbose

安装服务后,你可以通过服务管理器(services.msc)来启动、停止或重启Redis服务。

五、验证安装
启动Redis服务器后,你可以在另一个命令行窗口中运行Redis客户端来测试Redis是否正常运行。使用以下命令连接到Redis服务器:

redis-cli.exe -h 127.0.0.1 -p 6379 -a yourpassword

如果Redis服务器正常运行,你将能够连接到它并执行Redis命令,如PING,它应该返回PONG作为响应。

通过以上步骤,你可以在Windows系统上成功安装并配置Redis。Redis的强大功能和灵活性使其成为许多应用程序不可或缺的一部分。

8.2.2 配置

Redis在Windows系统安装后的配置主要涉及编辑配置文件、配置环境变量(可选)、以及启动Redis服务等步骤。以下是详细的配置指南:

一、编辑配置文件
Redis的配置主要通过编辑其配置文件(如redis.windows.conf或redis.conf)来完成。你可以使用任何文本编辑器打开该文件,并根据需要进行修改。以下是一些常见的配置项:

  1. 设置密码:
    • 找到requirepass配置项,取消注释并设置你的密码。例如:requirepass yourpassword。这样,在连接Redis服务器时就需要提供密码。
  2. 修改绑定地址:
    • 如果需要Redis服务允许远程访问,可以将bind配置项从127.0.0.1(只允许本机访问)改为0.0.0.0。但请注意,这样做会增加安全风险,因为任何能够访问到Redis服务器所在端口的设备都可以尝试连接。
  3. 其他配置:
    • 根据需要调整端口号(默认是6379)、内存限制、持久化策略(如RDB快照或AOF追加文件)等。

二、配置环境变量(可选)
为了方便在命令行中直接使用Redis命令,你可以将Redis的安装目录添加到系统的PATH环境变量中。这样,无论在哪个目录下打开命令行窗口,都可以直接运行Redis命令。

  • 打开“系统属性”对话框(可以通过“控制面板”->“系统和安全”->“系统”->“高级系统设置”进入),点击“环境变量”按钮。
  • 在“系统变量”区域找到名为“Path”的变量,点击“编辑”按钮。
  • 在弹出的对话框中,点击“新建”按钮,并添加Redis的安装目录(如C:\Redis)。
  • 点击“确定”保存更改。

三、启动Redis服务
Redis支持两种启动方式:临时启动和作为服务启动。

  1. 临时启动:
    • 在命令行中,进入Redis的安装目录。
    • 运行redis-server.exe redis.windows.conf(或你的配置文件名称)来启动Redis服务器。此时,需要保持命令行窗口开启,Redis服务器才会继续运行。
  2. 作为服务启动:
    • 将Redis注册为Windows服务,以便在系统启动时自动运行。在Redis安装目录下运行以下命令:
    redis-server --service-install redis.windows.conf --loglevel verbose
    
    • 安装服务后,你可以通过服务管理器(services.msc)来启动、停止或重启Redis服务。

四、验证配置
启动Redis服务器后,你可以在另一个命令行窗口中运行Redis客户端来测试Redis是否正常运行。使用以下命令连接到Redis服务器:

redis-cli.exe -h 127.0.0.1 -p 6379 -a yourpassword(如果设置了密码)

如果Redis服务器正常运行,你将能够连接到它并执行Redis命令,如PING,它应该返回PONG作为响应。

通过以上步骤,你可以完成Redis在Windows系统安装后的配置工作,并根据自己的需求进行定制化设置。

8.2.3 启动

Redis在Windows安装后的配置及启动主要包括以下几个步骤:

一、配置Redis
Redis的配置主要通过编辑其配置文件(如redis.windows.conf)来完成。可以使用文本编辑器打开该文件,并根据需要进行修改。以下是一些常见的配置项:

  1. 设置密码:
    • 找到requirepass配置项,取消注释并设置密码。例如:requirepass yourpassword。设置密码后,连接Redis时需要提供此密码。
  2. 修改绑定地址:
    • 如果需要Redis服务允许远程访问,可以将bind配置项从127.0.0.1(只允许本机访问)改为0.0.0.0。但请注意,这样做会增加安全风险,建议仅在安全的环境下使用。
  3. 端口配置:
    • 确认或修改Redis服务的监听端口。默认端口是6379,但可以根据需要修改为其他端口。
  4. 持久化策略:
    • 根据需要配置Redis的持久化策略,包括RDB快照和AOF追加文件。这有助于在Redis服务重启后恢复数据。
  5. 其他配置:
    • 根据实际使用情况调整内存限制、连接数限制等其他配置项。

二、启动Redis服务
Redis支持多种启动方式,在Windows上常用的有两种:临时启动和作为服务启动。

  1. 临时启动:

    • 打开命令行工具(如CMD或PowerShell)。
    • 切换到Redis的安装目录。
    • 执行redis-server.exe redis.windows.conf(或你的配置文件名称)来启动Redis服务器。此时,Redis服务器将在当前命令行窗口中运行,并且当命令行窗口关闭时,Redis服务器也会停止。
  2. 作为服务启动:

    • 首先,将Redis注册为Windows服务。在Redis安装目录下,以管理员身份打开命令行工具,并执行以下命令:
    redis-server --service-install redis.windows.conf --loglevel verbose
    

    这条命令会将Redis注册为Windows服务,并设置日志级别为verbose(详细)。

    • 安装服务后,可以通过Windows的服务管理器(services.msc)来管理Redis服务。在服务列表中找到Redis服务,右键点击并选择“启动”来启动Redis服务器。
    • 也可以使用命令行工具来启动、停止或重启Redis服务。例如,使用以下命令启动Redis服务:
    redis-server --service-start
    

    停止服务则使用:

    redis-server --service-stop
    

三、验证Redis服务是否启动成功
启动Redis服务后,可以通过Redis客户端来验证服务是否启动成功。

  1. 打开另一个命令行窗口。
  2. 输入redis-cli.exe(如果设置了密码,则需要使用-a参数提供密码,如redis-cli.exe -a yourpassword)来连接到Redis服务器。
  3. 如果连接成功,可以尝试执行一些Redis命令,如PING,如果返回PONG,则说明Redis服务已经成功启动并可以正常工作。

通过以上步骤,可以完成Redis在Windows安装后的配置及启动工作。

8.2.4 连接

Redis的连接可以通过多种方式实现,主要包括使用Redis客户端库、命令行工具redis-cli、配置文件redis.conf以及连接池等。以下是对这些连接方式的详细解释:

1. 使用Redis客户端库
Redis客户端库是用于连接和与Redis服务器进行通信的软件库。这些库提供了丰富的接口和功能,使得开发者可以在不同的编程语言中方便地操作Redis。常见的Redis客户端库包括:

  • Jedis(Java)
  • redis-py(Python)
  • hiredis(C/C++)
  • StackExchange.Redis(C#)
  • node_redis(Node.js)

使用这些客户端库时,通常需要提供Redis服务器的IP地址、端口号和密码(如果设置了密码)。连接成功后,就可以使用相应的客户端库来执行Redis命令和操作Redis数据。

2. 使用命令行工具redis-cli
redis-cli是Redis官方提供的命令行工具,可以直接在终端中连接Redis服务器,并执行Redis命令。通过运行redis-cli命令,可以指定连接Redis服务器的IP地址和端口号。例如:

redis-cli -h 127.0.0.1 -p 6379

如果Redis服务器设置了密码,还需要在连接后使用AUTH命令进行身份验证。

3. 使用配置文件redis.conf
Redis的配置文件redis.conf中包含了连接Redis服务器的设置。通过编辑redis.conf文件中的bind、port和requirepass等参数,可以指定连接Redis服务器的IP地址、端口号和密码。然后,在启动Redis服务器时,它会根据配置文件中的设置来进行连接。

4. 使用连接池
连接池是一种管理和维护多个Redis连接的机制。通过创建和使用连接池,可以避免频繁地创建和销毁Redis连接,提高连接的复用性和效率。常见的连接池实现包括Jedis的JedisPool(Java)、redis-py的ConnectionPool(Python)、StackExchange.Redis的ConnectionMultiplexer(C#)等。

使用连接池时,首先需要创建连接池实例,并配置Redis服务器的连接信息。然后,从连接池中获取连接并执行Redis命令。使用完毕后,连接会自动归还给连接池,供后续请求使用。

注意事项

  • 在连接Redis时,需要确保Redis服务器已经启动并正在监听指定的IP地址和端口。
  • 如果Redis服务器设置了密码,连接时需要提供正确的密码进行身份验证。
  • 在高并发场景下,建议使用连接池来管理Redis连接,以提高系统性能和稳定性。
  • 定期检查连接池中的连接状态,及时替换不可用的连接,以保证系统的健壮性。

综上所述,Redis的连接方式多种多样,开发者可以根据具体需求和场景选择合适的方式进行连接和操作。

8.2.5基本操作

Redis是一个高性能的key-value数据库,它支持多种类型的数据结构,并提供了丰富的操作命令。以下是Redis的一些基本操作:

  1. 连接Redis

    • 使用redis-cli命令行工具连接Redis服务器。例如,redis-cli -h 127.0.0.1 -p 6379用于连接本地Redis服务器(默认端口为6379)。
    • 如果Redis服务器设置了密码,连接后需要使用AUTH [密码]命令进行身份验证。
  2. 数据类型与操作

    • Redis支持五种基本的数据类型,每种类型都有其特定的操作命令。

字符串(String)

  • 设置值:使用SET key value命令设置字符串类型的值。
  • 获取值:使用GET key命令获取字符串类型的值。
  • 自增/自减:使用INCR key和DECR key命令对字符串类型的值进行原子性的自增和自减操作。

列表(List)

  • 添加元素:使用LPUSH key value [value …]命令在列表头部插入一个或多个元素,使用RPUSH key value [value …]命令在列表尾部插入一个或多个元素。
  • 获取元素:使用LRANGE key start stop命令获取列表指定范围内的元素。
  • 移除元素:使用LPOP key和RPOP key命令分别从列表的头部和尾部移除元素。

集合(Set)

  • 添加元素:使用SADD key member [member …]命令向集合中添加一个或多个元素。
  • 获取元素:使用SMEMBERS key命令获取集合中的所有元素。
  • 集合运算:支持并集(SUNION)、交集(SINTER)和差集(SDIFF)运算。’

有序集合(Sorted Set)

  • 添加元素:使用ZADD key score member [score member …]命令向有序集合中添加一个或多个元素,并关联一个分数(score)。
  • 获取元素:使用ZRANGE key start stop [WITHSCORES]命令按分数从低到高获取有序集合中的元素及其分数。
  • 排名操作:支持根据分数进行排名和范围查询。

散列(Hash)

  • 设置字段值:使用HSET key field value命令设置散列字段的值。
  • 获取字段值:使用HGET key field命令获取散列字段的值。
  • 批量操作:支持HMSET和HMGET等批量设置和获取字段值的操作。
  1. 通用操作
  • 查看所有键:使用KEYS pattern命令查找符合特定模式的键(注意:在生产环境中慎用,因为可能会阻塞服务器)。
  • 查看键是否存在:使用EXISTS key命令检查键是否存在。
  • 删除键:使用DEL key [key …]命令删除一个或多个键。
  • 查看键的类型:使用TYPE key命令获取键的类型。
  1. 事务与持久化
  • 事务:Redis支持事务操作,使用MULTI、EXEC、DISCARD等命令来执行一组命令,确保这些命令的原子性。
  • 持久化:Redis提供了RDB和AOF两种持久化方式,可以将内存中的数据保存到磁盘上,以防止数据丢失。
  1. 监控与性能调优
  • 监控:使用INFO命令查看Redis服务器的状态信息,包括内存使用情况、连接数、命令执行统计等。
  • 性能调优:通过调整配置文件中的参数(如内存限制、持久化策略等)来优化Redis的性能。

以上是对Redis基本操作的一个简要概述。在实际应用中,根据具体需求选择合适的数据类型和操作命令是非常重要的。

8.3 Jedis操作Redis

  Jedis是Redis官方推荐的java连接开发工具。要在java开发中使用好Redis中间件,必须对Jedis熟悉才能写出漂亮的代码。

8.3.1 常用方法API

Jedis是Java环境下广泛使用的一个Redis客户端库,它提供了丰富的API来操作Redis数据库。以下是一些Jedis操作Redis的常用方法及其Java代码示例:

1. 连接Redis
首先,需要创建一个Jedis实例来连接Redis服务器。

import redis.clients.jedis.Jedis;  
  
public class RedisExample {  
    public static void main(String[] args) {  
        // 连接到Redis服务器  
        Jedis jedis = new Jedis("localhost", 6379);  
        // 如果Redis服务器设置了密码,则需要通过auth方法进行认证  
        // jedis.auth("yourpassword");  
  
        // 以下为其他操作...  
  
        // 操作完成后,关闭连接  
        jedis.close();  
    }  
}

2. 字符串操作

// 设置字符串  
jedis.set("key", "value");  
  
// 获取字符串  
String value = jedis.get("key");  
System.out.println(value);  
  
// 自增操作  
long newvalue = jedis.incr("counter");  
System.out.println(newvalue);  
  
// 自减操作  
newvalue = jedis.decr("counter");  
System.out.println(newvalue);

3. 列表操作

// 向列表头部插入元素  
jedis.lpush("mylist", "value1");  
jedis.lpush("mylist", "value2");  
  
// 向列表尾部插入元素  
jedis.rpush("mylist", "value3");  
  
// 获取列表元素  
List<String> list = jedis.lrange("mylist", 0, -1);  
for (String element : list) {  
    System.out.println(element);  
}  
  
// 移除并获取列表的第一个元素  
String firstElement = jedis.lpop("mylist");  
System.out.println(firstElement);

4. 集合操作

// 向集合添加元素  
jedis.sadd("myset", "element1");  
jedis.sadd("myset", "element2");  
  
// 获取集合所有元素  
Set<String> set = jedis.smembers("myset");  
for (String element : set) {  
    System.out.println(element);  
}  
  
// 集合运算(交集)  
Set<String> intersection = jedis.sinter("myset", "anotherset");  
for (String element : intersection) {  
    System.out.println(element);  
}

5. 有序集合操作

// 向有序集合添加元素  
jedis.zadd("mysortedset", 1, "one");  
jedis.zadd("mysortedset", 2, "two");  
  
// 获取有序集合的元素(带分数)  
Set<Tuple> sortedSet = jedis.zrangeWithScores("mysortedset", 0, -1);  
for (Tuple tuple : sortedSet) {  
    System.out.println(tuple.getElement() + ":" + tuple.getScore());  
}  
  
// 获取有序集合的排名  
Long rank = jedis.zrank("mysortedset", "one");  
System.out.println("The rank of 'one' is: " + rank);

6. 散列操作

// 设置散列字段  
jedis.hset("myhash", "field1", "value1");  
  
// 获取散列字段  
String fieldValue = jedis.hget("myhash", "field1");  
System.out.println(fieldValue);  
  
// 获取散列所有字段和值  
Map<String, String> hashMap = jedis.hgetAll("myhash");  
for (Map.Entry<String, String> entry : hashMap.entrySet()) {  
    System.out.println(entry.getKey() + ":" + entry.getValue());  
}

注意:上述示例代码假设您已经成功将Jedis库添加到您的项目中,并且Redis服务器正在运行且可访问。此外,由于Redis版本和Jedis版本的更新,某些API的细节可能会有所不同,因此请参考您所使用的具体版本的文档。

8.3.2 基本操作

Jedis 是一个流行的 Java Redis 客户端库,它提供了丰富的 API 来执行 Redis 命令。以下是一些使用 Jedis 进行 Redis 基本操作的 Java 代码示例:

1. 连接到 Redis
首先,你需要创建一个 Jedis 实例来连接到 Redis 服务器。

import redis.clients.jedis.Jedis;  
  
public class RedisExample {  
    public static void main(String[] args) {  
        // 连接到 Redis 服务器  
        try (Jedis jedis = new Jedis("localhost", 6379)) {  
            // 如果 Redis 服务器设置了密码,则需要进行身份验证  
            // jedis.auth("yourpassword");  
  
            // 以下为其他操作...  
  
        } // Jedis 实例会在 try-with-resources 语句结束时自动关闭  
    }  
}

2. 字符串(String)操作

try (Jedis jedis = new Jedis("localhost", 6379)) {  
    // 设置字符串  
    jedis.set("key", "value");  
  
    // 获取字符串  
    String value = jedis.get("key");  
    System.out.println(value); // 输出: value  
  
    // 自增操作  
    long newvalue = jedis.incr("counter");  
    System.out.println(newvalue); // 假设 counter 之前不存在或值为 0,则输出: 1  
  
    // 自减操作  
    newvalue = jedis.decr("counter");  
    System.out.println(newvalue); // 输出: 0  
}

3. 列表(List)操作

try (Jedis jedis = new Jedis("localhost", 6379)) {  
    // 向列表头部插入元素  
    jedis.lpush("mylist", "value1", "value2");  
  
    // 向列表尾部插入元素  
    jedis.rpush("mylist", "value3");  
  
    // 获取列表元素  
    List<String> list = jedis.lrange("mylist", 0, -1);  
    for (String element : list) {  
        System.out.println(element); // 输出: value2, value1, value3  
    }  
  
    // 移除并获取列表的第一个元素  
    String firstElement = jedis.lpop("mylist");  
    System.out.println(firstElement); // 输出: value2  
}

4. 集合(Set)操作

try (Jedis jedis = new Jedis("localhost", 6379)) {  
    // 向集合添加元素  
    jedis.sadd("myset", "element1", "element2");  
  
    // 获取集合所有元素  
    Set<String> set = jedis.smembers("myset");  
    for (String element : set) {  
        System.out.println(element); // 输出: element1, element2(顺序可能不同)  
    }  
  
    // 集合运算(交集)  
    Set<String> intersection = jedis.sinter("myset", "anotherset"); // 假设anotherset已存在  
    for (String element : intersection) {  
        System.out.println(element); // 输出交集元素  
    }  
}

5. 有序集合(Sorted Set)操作

try (Jedis jedis = new Jedis("localhost", 6379)) {  
    // 向有序集合添加元素  
    jedis.zadd("mysortedset", 1, "one");  
    jedis.zadd("mysortedset", 2, "two");  
  
    // 获取有序集合的元素(带分数)  
    Set<Tuple> sortedSet = jedis.zrangeWithScores("mysortedset", 0, -1);  
    for (Tuple tuple : sortedSet) {  
        System.out.println(tuple.getElement() + ":" + tuple.getScore()); // 输出: one:1, two:2  
    }  
  
    // 获取有序集合的排名  
    Long rank = jedis.zrank("mysortedset", "one");  
    System.out.println("The rank of 'one' is: " + rank); // 输出: 0  
}

6. 散列(Hash)操作

try (Jedis jedis = new Jedis("localhost", 6379)) {  
    // 设置散列字段  
    jedis.hset("myhash", "field1", "value1");  
  
    // 获取散列字段  
    String fieldValue = jedis.hget("myhash", "field1");  
    System.out.println(fieldValue); // 输出: value1  
  
    // 获取散列所有字段和值  
    Map<String, String> hashMap = jedis.hgetAll("myhash");  
    for (Map.Entry<String, String> entry : hashMap.entrySet()) {  
        System.out.println(entry.getKey() + ":" + entry.getValue()); // 输出: field1:value1  
    }  
}

注意:在上面的示例中,我们使用了 try-with-resources 语句来自动关闭 Jedis 实例,这是一种良好的实践,可以确保资源得到及时释放。另外,如果 Redis 服务器设置了密码,你需要在连接后进行身份验证(如上例中的 jedis.auth(“yourpassword”);)。

8.3.3 连接池

Jedis 支持使用连接池来管理 Redis 连接,这可以提高应用程序的性能和资源利用率。以下是一个使用 Jedis 连接池的 Java 代码示例:

首先,你需要在你的项目中包含 Jedis 依赖。如果你使用 Maven,可以在 pom.xml 文件中添加以下依赖:

<dependency>  
    <groupId>redis.clients</groupId>  
    <artifactId>jedis</artifactId>  
    <version>最新版本</version> <!-- 请替换为最新版本 -->  
</dependency>

然后,你可以使用 JedisPool 或 JedisPoolConfig 来配置和获取连接池中的连接。

以下是一个完整的示例,展示了如何配置 Jedis 连接池并使用它来执行 Redis 命令:

import redis.clients.jedis.Jedis;  
import redis.clients.jedis.JedisPool;  
import redis.clients.jedis.JedisPoolConfig;  
  
public class JedisPoolExample {  
  
    // 私有静态 JedisPool 实例  
    private static JedisPool jedisPool = null;  
  
    // 静态代码块中初始化连接池  
    static {  
        // 创建一个 JedisPoolConfig 对象来设置连接池的配置  
        JedisPoolConfig poolConfig = new JedisPoolConfig();  
        poolConfig.setMaxTotal(100); // 最大活跃连接数  
        poolConfig.setMaxIdle(10);   // 最大空闲连接数  
        poolConfig.setMinIdle(2);    // 最小空闲连接数  
        poolConfig.setTestOnBorrow(true); // 在从池中取出连接前,检查连接是否有效  
  
        // 创建 JedisPool  
        jedisPool = new JedisPool(poolConfig, "localhost", 6379);  
  
        // 如果 Redis 服务器需要密码,可以这样设置  
        // jedisPool = new JedisPool(poolConfig, "localhost", 6379, 2000, "password");  
    }  
  
    // 获取 Jedis 连接的方法  
    public static Jedis getJedis() {  
        return jedisPool.getResource();  
    }  
  
    // 释放 Jedis 连接的方法  
    public static void releaseJedis(Jedis jedis) {  
        if (jedis != null) {  
            jedis.close();  
        }  
    }  
  
    public static void main(String[] args) {  
        // 从连接池中获取连接  
        Jedis jedis = getJedis();  
  
        try {  
            // 执行 Redis 命令  
            jedis.set("key", "value");  
            String value = jedis.get("key");  
            System.out.println(value); // 输出: value  
  
            // 其他的 Redis 操作...  
  
        } finally {  
            // 释放连接  
            releaseJedis(jedis);  
        }  
    }  
}

在这个示例中,我们使用了一个静态代码块来初始化 JedisPool 实例,并配置了连接池的一些基本参数,如最大活跃连接数、最大空闲连接数、最小空闲连接数等。getJedis() 方法用于从连接池中获取一个 Jedis 连接,而 releaseJedis() 方法则用于释放该连接。

在 main() 方法中,我们通过调用 getJedis() 方法来获取一个连接,并执行了一些 Redis 命令。最后,在 finally 块中,我们调用 releaseJedis() 方法来确保连接被正确释放回连接池。

注意:在实际应用中,你可能需要根据自己的需求调整连接池的配置参数。此外,如果你使用的是 Spring 框架或其他依赖注入容器,你也可以考虑将这些配置参数和连接池实例作为 Spring Bean 来管理。

8.4 SpringBoot操作Redis

在Spring Boot中操作Redis,通常会使用Spring Data Redis这个库,它提供了对Redis的高级抽象,使得在Spring应用中操作Redis变得非常简单。以下是一个基本的Spring Boot操作Redis的Java代码示例。

首先,你需要在你的pom.xml中添加Spring Data Redis和Jedis(或Lettuce,这是另一个Redis客户端)的依赖。这里以Jedis为例:

<dependencies>  
    <!-- Spring Boot Starter Data Redis -->  
    <dependency>  
        <groupId>org.springframework.boot</groupId>  
        <artifactId>spring-boot-starter-data-redis</artifactId>  
    </dependency>  
    <!-- Jedis 客户端 -->  
    <dependency>  
        <groupId>redis.clients</groupId>  
        <artifactId>jedis</artifactId>  
    </dependency>  
    <!-- 其他依赖... -->  
</dependencies>

注意:从Spring Boot 2.x开始,spring-boot-starter-data-redis已经包含了Jedis或Lettuce的依赖,所以你可能不需要显式地添加Jedis或Lettuce的依赖,除非你需要指定版本或进行其他配置。

接下来,在application.properties或application.yml中配置Redis服务器的连接信息:

<dependencies>  
    <!-- Spring Boot Starter Data Redis -->  
    <dependency>  
        <groupId>org.springframework.boot</groupId>  
        <artifactId>spring-boot-starter-data-redis</artifactId>  
    </dependency>  
    <!-- Jedis 客户端 -->  
    <dependency>  
        <groupId>redis.clients</groupId>  
        <artifactId>jedis</artifactId>  
    </dependency>  `# application.properties 示例  
spring.redis.host=localhost  
spring.redis.port=6379  
# 如果Redis服务器需要密码  
# spring.redis.password=yourpassword  
# 使用Jedis客户端(默认)  
# spring.redis.jedis.pool.max-active=10  
# spring.redis.jedis.pool.max-wait=-1ms  
# spring.redis.jedis.pool.max-idle=8  
# spring.redis.jedis.pool.min-idle=0  
  
# 或者使用Lettuce客户端  
# spring.redis.lettuce.pool.max-active=10  
# spring.redis.lettuce.pool.max-wait=-1ms  
# spring.redis.lettuce.pool.max-idle=8  
# spring.redis.lettuce.pool.min-idle=0
`
    <!-- 其他依赖... -->  
</dependencies>

然后,你可以使用StringRedisTemplate或RedisTemplate来操作Redis。StringRedisTemplate是RedisTemplate的一个特例,它默认使用String作为key和value的序列化方式。

以下是一个使用StringRedisTemplate的示例:

import org.springframework.beans.factory.annotation.Autowired;  
import org.springframework.data.redis.core.StringRedisTemplate;  
import org.springframework.stereotype.Service;  
  
@Service  
public class RedisService {  
  
    @Autowired  
    private StringRedisTemplate stringRedisTemplate;  
  
    public void setValue(String key, String value) {  
        stringRedisTemplate.opsForValue().set(key, value);  
    }  
  
    public String getValue(String key) {  
        return stringRedisTemplate.opsForValue().get(key);  
    }  
  
    // 其他Redis操作...  
}

在这个RedisService类中,我们注入了StringRedisTemplate,并使用它来设置和获取Redis中的字符串值。你可以根据需要添加更多的方法来执行其他Redis操作,如列表操作、集合操作、有序集合操作等。

最后,在你的Spring Boot应用中,你可以注入RedisService并使用它来与Redis进行交互。

注意:上述代码示例是基于Spring Boot 2.x版本的。如果你使用的是其他版本的Spring Boot,可能需要进行一些调整。此外,如果你需要自定义序列化方式或连接池配置,你可以在配置类中通过Java配置来实现。

8.4.1 sping-boot-starter-data-redis

在Spring Boot中,使用spring-boot-starter-data-redis来操作Redis是非常直接的。这个starter包含了所有必要的依赖和自动配置,使得你可以很容易地在你的Spring Boot应用中使用Redis。

以下是一个简单的Java代码示例,展示了如何在Spring Boot应用中使用spring-boot-starter-data-redis来操作Redis。

首先,确保你的pom.xml(如果你使用的是Maven)或build.gradle(如果你使用的是Gradle)中包含了spring-boot-starter-data-redis的依赖。但是,通常情况下,从Spring Boot 2.x开始,这个依赖是自动包含的,如果你已经添加了spring-boot-starter-web或其他starter,并且你的Spring Boot版本是2.x或更高。

然后,在你的Spring Boot应用中,你可以通过注入StringRedisTemplate或RedisTemplate来操作Redis。这里,我们将使用StringRedisTemplate,因为它默认使用String作为key和value的序列化方式,这在处理简单的键值对时非常方便。

以下是一个简单的服务类,它使用StringRedisTemplate来设置和获取Redis中的值:

import org.springframework.beans.factory.annotation.Autowired;  
import org.springframework.data.redis.core.StringRedisTemplate;  
import org.springframework.stereotype.Service;  
  
@Service  
public class RedisService {  
  
    @Autowired  
    private StringRedisTemplate stringRedisTemplate;  
  
    // 设置Redis中的值  
    public void setValue(String key, String value) {  
        stringRedisTemplate.opsForValue().set(key, value);  
    }  
  
    // 获取Redis中的值  
    public String getValue(String key) {  
        return stringRedisTemplate.opsForValue().get(key);  
    }  
  
    // 其他Redis操作...  
}

在你的控制器或其他服务中,你可以注入RedisService并使用它来与Redis进行交互:

import org.springframework.beans.factory.annotation.Autowired;  
import org.springframework.web.bind.annotation.GetMapping;  
import org.springframework.web.bind.annotation.PostMapping;  
import org.springframework.web.bind.annotation.RequestParam;  
import org.springframework.web.bind.annotation.RestController;  
  
@RestController  
public class RedisController {  
  
    @Autowired  
    private RedisService redisService;  
  
    @PostMapping("/set")  
    public String setValue(@RequestParam String key, @RequestParam String value) {  
        redisService.setValue(key, value);  
        return "Value set successfully";  
    }  
  
    @GetMapping("/get")  
    public String getValue(@RequestParam String key) {  
        return redisService.getValue(key);  
    }  
  
    // 其他REST API...  
}

在这个例子中,我们创建了一个RedisService类,它提供了两个方法:setValue用于设置Redis中的值,getValue用于获取Redis中的值。然后,我们在RedisController中注入了RedisService,并创建了两个REST API端点,一个用于设置值,另一个用于获取值。

注意:这个示例假设你的Redis服务器正在运行,并且Spring Boot应用已经配置了正确的Redis连接信息(这通常是通过application.properties或application.yml文件来完成的)。如果你没有配置Redis连接信息,Spring Boot将尝试使用默认的配置(例如,连接到localhost的6379端口),这可能会导致连接失败,除非你的Redis服务器确实在那里运行。

此外,如果你需要自定义Redis连接池的配置或序列化方式,你可以在你的Spring Boot配置类中通过Java配置来实现这一点。但是,对于大多数基本用例来说,默认的自动配置应该就足够了。

8.4.2 基本操作

在Spring Boot中操作Redis的基本操作包括设置键值对、获取键值对、删除键、以及使用事务等。下面是一个简单的Java代码示例,展示了如何在Spring Boot应用中通过StringRedisTemplate来进行这些基本操作。

首先,确保你的Spring Boot项目中已经包含了spring-boot-starter-data-redis依赖。

然后,你可以在你的服务类中注入StringRedisTemplate,并使用它来执行Redis命令。以下是一个示例服务类:

import org.springframework.beans.factory.annotation.Autowired;  
import org.springframework.data.redis.core.StringRedisTemplate;  
import org.springframework.data.redis.core.ValueOperations;  
import org.springframework.stereotype.Service;  
  
@Service  
public class RedisService {  
  
    @Autowired  
    private StringRedisTemplate stringRedisTemplate;  
  
    // 设置键值对  
    public void set(String key, String value) {  
        stringRedisTemplate.opsForValue().set(key, value);  
    }  
  
    // 获取键对应的值  
    public String get(String key) {  
        return stringRedisTemplate.opsForValue().get(key);  
    }  
  
    // 删除键  
    public Boolean delete(String key) {  
        return stringRedisTemplate.delete(key);  
    }  
  
    // 使用事务(简单示例:先设置再获取)  
    public String transactionalSetAndGet(String key, String value) {  
        // 开启事务  
        stringRedisTemplate.multi();  
        try {  
            // 执行命令  
            stringRedisTemplate.opsForValue().set(key, value);  
            String result = stringRedisTemplate.opsForValue().get(key);  
  
            // 提交事务  
            stringRedisTemplate.exec();  
  
            return result;  
        } catch (Exception e) {  
            // 发生异常时回滚事务  
            stringRedisTemplate.discard();  
            return null;  
        }  
    }  
  
    // 注意:上面的transactionalSetAndGet方法是一个简化的示例,  
    // 在实际使用中,你可能需要更复杂的错误处理和事务管理逻辑。  
    // 此外,Redis的事务支持并不像传统数据库那样强大,  
    // 它主要是用于确保一系列命令的原子性执行,而不是用于回滚到某个状态。  
  
    // 其他Redis操作...  
}

注意:StringRedisTemplate的multi(), exec(), 和 discard() 方法的使用方式在上述示例中可能并不完全正确,因为StringRedisTemplate本身并不直接暴露Redis的事务API(如MULTI, EXEC, DISCARD命令)的同步执行方式。上述示例中的事务处理更像是一个伪代码,用于说明概念。

在Spring Data Redis中,如果你需要执行Redis事务,你应该使用SessionCallback或RedisCallback接口,或者通过execute方法在RedisTemplate或StringRedisTemplate上执行。但是,对于简单的键值操作,你通常不需要显式地使用Redis的事务功能。

对于更复杂的场景,如果你确实需要Redis的事务支持,并且希望确保一系列命令的原子性执行,你可能需要查看Spring Data Redis的文档,了解如何使用SessionCallback或类似机制来显式地管理Redis会话和事务。

不过,对于大多数基本用途来说,上面的set, get, 和 delete 方法应该就足够了。

8.5 SpringBoot集成Redis使用Cache缓存

在Spring Boot中集成Redis并使用它作为缓存的一种常见方式是使用Spring的缓存抽象(@EnableCaching)结合spring-boot-starter-data-redis。这样,你可以通过简单的注解来控制缓存的创建、更新和失效,而不需要直接编写与Redis交互的代码。

以下是一个简单的示例,展示了如何在Spring Boot应用中集成Redis并使用它作为缓存。

首先,确保你的pom.xml(Maven)或build.gradle(Gradle)文件中包含了spring-boot-starter-data-redis和spring-boot-starter-cache的依赖。但是,请注意,从Spring Boot 2.x开始,spring-boot-starter-data-redis通常已经包含了spring-boot-starter-cache所需的依赖,因此你可能只需要添加spring-boot-starter-data-redis。

然后,在你的Spring Boot应用的主类或配置类上添加@EnableCaching注解来启用缓存支持。

接下来,配置Redis作为缓存管理器。Spring Boot会自动配置RedisCacheManager,但你也可以通过自定义配置来调整它。

最后,在你的服务层或数据访问层的方法上使用@Cacheable、@CachePut、@CacheEvict等注解来控制缓存行为。

以下是一个简单的示例:

pom.xml(如果你使用的是Maven)

<dependency>  
    <groupId>org.springframework.boot</groupId>  
    <artifactId>spring-boot-starter-data-redis</artifactId>  
</dependency>  
<!-- 注意:通常不需要显式添加spring-boot-starter-cache,因为它会被spring-boot-starter-data-redis隐式包含 -->

配置类(可选,如果你需要自定义Redis缓存管理器)

// 通常不需要,因为Spring Boot会自动配置  
// 但如果需要自定义,可以创建一个配置类来定义RedisCacheManager

主类或配置类

import org.springframework.boot.SpringApplication;  
import org.springframework.boot.autoconfigure.SpringBootApplication;  
import org.springframework.cache.annotation.EnableCaching;  
  
@SpringBootApplication  
@EnableCaching // 启用缓存支持  
public class MySpringBootApplication {  
  
    public static void main(String[] args) {  
        SpringApplication.run(MySpringBootApplication.class, args);  
    }  
}

服务层

import org.springframework.cache.annotation.Cacheable;  
import org.springframework.stereotype.Service;  
  
@Service  
public class MyService {  
  
    // 使用@Cacheable注解来缓存方法的返回值  
    // 当调用此方法时,Spring会先检查缓存中是否存在key为"someKey"的条目  
    // 如果存在,则直接返回缓存中的值;如果不存在,则执行方法体,并将返回值存入缓存中  
    @Cacheable(value = "myCache", key = "'someKey'")  
    public String getSomeData() {  
        // 模拟数据访问操作,例如从数据库或远程服务中获取数据  
        return "Data from database or remote service";  
    }  
  
    // 其他方法,可以使用@CachePut(更新缓存)、@CacheEvict(删除缓存)等注解  
}

在这个示例中,MyService类中的getSomeData方法被标记为可缓存的。当这个方法被调用时,Spring会检查名为myCache的缓存中是否存在一个键为"someKey"的条目。如果不存在,它会执行方法体,并将返回值存储在缓存中。如果已存在,它会直接从缓存中返回该值,从而避免了重复的数据访问操作。

注意:你需要有一个运行中的Redis服务器,并且你的Spring Boot应用需要配置为连接到该Redis服务器。这通常是通过application.properties或application.yml文件中的Redis连接属性来完成的。Spring Boot会自动检测这些属性并配置RedisTemplate和RedisCacheManager。

8.5.1 RedisConfig配置

在Spring Boot中集成Redis并使用它作为缓存时,通常不需要显式地编写一个完整的RedisConfig类来配置RedisCacheManager,因为Spring Boot的自动配置功能已经为你做了大部分工作。然而,如果你需要自定义缓存配置(比如更改默认的缓存过期时间、序列化方式等),你可以通过定义一个配置类来覆盖自动配置的默认值。

以下是一个自定义RedisConfig配置类的示例,展示了如何配置RedisCacheManager来自定义缓存行为:

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.cache.annotation.EnableCaching;  
import org.springframework.cache.interceptor.KeyGenerator;  
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.serializer.GenericJackson2JsonRedisSerializer;  
import org.springframework.data.redis.serializer.RedisSerializationContext;  
import org.springframework.data.redis.serializer.StringRedisSerializer;  
  
import java.time.Duration;  
  
@Configuration  
@EnableCaching  
public class RedisConfig {  
  
    private static final String CACHE_NAME = "defaultCache";  
  
    @Bean  
    public CacheManager cacheManager(RedisConnectionFactory redisConnectionFactory) {  
        // 自定义Jackson2JsonRedisSerializer来序列化缓存值  
        ObjectMapper om = new ObjectMapper();  
        om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);  
        om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);  
  
        RedisCacheConfiguration defaultCacheConfig = RedisCacheConfiguration.defaultCacheConfig()  
                .entryTtl(Duration.ofHours(1)) // 设置默认缓存过期时间为1小时  
                .serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(new StringRedisSerializer()))  
                .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(new GenericJackson2JsonRedisSerializer(om)));  
  
        return RedisCacheManager.builder(redisConnectionFactory)  
                .cacheDefaults(defaultCacheConfig)  
                .withInitialCacheConfigurations(  
                        // 可以为特定的缓存名称设置不同的配置  
                        CACHE_NAME + ":" + "someSpecificCache", RedisCacheConfiguration.defaultCacheConfig()  
                                .entryTtl(Duration.ofMinutes(30)) // 特定缓存的过期时间为30分钟  
                                .disableCachingNullValues() // 不缓存空值  
                )  
                .build();  
    }  
  
    // 如果需要自定义Key的生成策略,可以添加一个KeyGenerator的Bean  
    // @Bean  
    // public KeyGenerator customKeyGenerator() {  
    //     return (target, method, params) -> {  
    //         // 自定义Key生成逻辑  
    //         StringBuilder sb = new StringBuilder();  
    //         sb.append(target.getClass().getName());  
    //         sb.append(method.getName());  
    //         for (Object obj : params) {  
    //             sb.append(obj.toString());  
    //         }  
    //         return sb.toString();  
    //     };  
    // }  
}

注意:上述代码中的@EnableCaching注解是可选的,因为如果你已经在主类或另一个配置类上添加了它,那么就不需要在这里再次添加。但是,如果你想要确保这个配置类被Spring Boot识别为缓存配置的一部分,并且没有其他地方启用了缓存,那么在这里添加@EnableCaching也是可以的。

在上面的配置中,我们创建了一个CacheManager的Bean,它使用RedisCacheManager来管理缓存。我们为默认缓存和特定名称的缓存设置了不同的配置,包括缓存的过期时间和序列化方式。这里,我们使用了GenericJackson2JsonRedisSerializer来序列化缓存值,它允许我们存储更复杂的Java对象,并且能够处理继承和多态性。

另外,如果你需要自定义缓存Key的生成策略,可以像注释掉的customKeyGenerator方法那样实现一个KeyGenerator的Bean,并在需要的地方通过@Cacheable(keyGenerator = “customKeyGenerator”)来指定它。但是,请注意,这通常是可选的,因为Spring已经为你提供了一个默认的Key生成策略。

8.5.2 Cache注解

在Spring Boot中集成Redis并使用它作为缓存时,你可以通过@Cacheable、@CachePut、@CacheEvict等注解来简化缓存的操作。这些注解允许你声明性地控制缓存的创建、更新和删除,而无需编写大量的缓存管理代码。

以下是一个简单的示例,展示了如何在Spring Boot应用程序中使用这些缓存注解:

首先,确保你的Spring Boot项目中已经包含了Redis和Spring Cache的依赖。例如,在pom.xml中添加如下依赖(如果你使用的是Maven):

<!-- Spring Boot Redis Starter -->  
<dependency>  
    <groupId>org.springframework.boot</groupId>  
    <artifactId>spring-boot-starter-data-redis</artifactId>  
</dependency>  
  
<!-- Spring Boot Cache Starter,通常已经包含在spring-boot-starter中 -->  
<!-- 如果你没有显式包含它,并且你的Spring Boot版本较新,那么它可能已经默认包含在内 -->  
<dependency>  
    <groupId>org.springframework.boot</groupId>  
    <artifactId>spring-boot-starter-cache</artifactId>  
</dependency>

然后,在你的配置类中(或者通过application.properties/application.yml),配置Redis连接信息。但是,对于大多数基本用途,Spring Boot的自动配置应该已经足够,除非你需要自定义序列化器、连接池等高级设置。

接下来,在你的服务层(Service Layer)中使用缓存注解。以下是一个简单的示例:

import org.springframework.cache.annotation.Cacheable;  
import org.springframework.stereotype.Service;  
  
@Service  
public class MyService {  
  
    // 假设这里有一个复杂的数据访问操作,比如从数据库查询  
  
    // 使用@Cacheable注解来缓存方法的结果  
    // cacheNames指定了缓存的名称,你可以根据需要在Redis中创建多个缓存  
    // key指定了缓存的键的生成策略,这里使用默认策略,但你也可以自定义  
    @Cacheable(cacheNames = "myCache", key = "#id")  
    public MyObject findById(Long id) {  
        // 模拟一个耗时的数据访问操作  
        // 这里应该是调用DAO层或Repository层来查询数据  
        // 但为了示例,我们直接返回一个模拟的对象  
        return new MyObject(id, "Some Data");  
    }  
  
    // 你可以使用@CachePut来更新缓存,而不是替换它  
    // 这在你想要更新缓存中的某个条目时非常有用  
    @CachePut(cacheNames = "myCache", key = "#myObject.id")  
    public MyObject updateMyObject(MyObject myObject) {  
        // 这里应该是更新数据库中的记录  
        // 但为了示例,我们直接返回传入的对象  
        return myObject;  
    }  
  
    // 使用@CacheEvict来从缓存中删除条目  
    // allEntries=true表示删除缓存中的所有条目,否则只删除与key匹配的条目  
    @CacheEvict(cacheNames = "myCache", key = "#id")  
    public void deleteById(Long id) {  
        // 这里应该是从数据库中删除记录  
        // 但为了示例,我们什么也不做  
    }  
  
    // 自定义key生成器的情况,你可能需要实现一个KeyGenerator  
    // 并在@Cacheable等注解中通过keyGenerator属性引用它  
    // 但对于大多数简单用例,默认的key生成策略应该就足够了  
}

注意:上面的MyObject是一个假设的类,代表你的业务对象。在实际应用中,你应该替换为你自己的类。

此外,@Cacheable、@CachePut和@CacheEvict注解都提供了许多其他属性,允许你进一步自定义缓存行为。例如,condition属性允许你基于某些条件来决定是否缓存结果或删除缓存条目,而unless属性则允许你在方法执行后基于结果来决定是否缓存或删除。

最后,请确保你的Spring Boot应用程序已经启用了缓存支持。这通常是通过在配置类上添加@EnableCaching注解来完成的,但如果你使用的是Spring Boot的自动配置,并且你的项目中包含了Spring Cache的依赖,那么它可能已经默认启用了缓存支持。

8.5.3 JSON注解

在Spring Boot中集成Redis并使用它作为缓存时,如果你想要缓存的数据是JSON格式的,你通常不需要特别指定JSON注解,因为Spring Cache抽象层并不直接关心缓存数据的格式。然而,当你使用Redis作为缓存存储时,你需要确保你的数据能够被正确地序列化和反序列化。

默认情况下,Spring Boot的Redis Starter使用JDK序列化来存储对象,但这通常不是存储JSON格式数据的最佳方式,因为它不是人类可读的,并且可能包含类元数据等额外信息。相反,你可以使用Jackson或Gson等库来将对象序列化为JSON字符串,并存储在Redis中。

以下是一个如何在Spring Boot中配置Redis以使用JSON格式存储缓存数据的示例:

  1. 添加依赖:确保你的项目中包含了Spring Boot Redis Starter和Jackson(或Gson)的依赖。
  2. 配置RedisTemplate:自定义RedisTemplate以使用JSON序列化器。
  3. 使用Spring Cache注解:在你的服务层使用@Cacheable、@CachePut和@CacheEvict注解。

下面是一个使用Jackson进行JSON序列化的配置示例:

import com.fasterxml.jackson.databind.ObjectMapper;  
import org.springframework.cache.CacheManager;  
import org.springframework.cache.annotation.EnableCaching;  
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.serializer.GenericJackson2JsonRedisSerializer;  
import org.springframework.data.redis.serializer.RedisSerializationContext;  
  
import java.time.Duration;  
  
@Configuration  
@EnableCaching  
public class RedisConfig {  
  
    @Bean  
    public CacheManager cacheManager(RedisConnectionFactory connectionFactory, ObjectMapper objectMapper) {  
        RedisCacheConfiguration defaultCacheConfig = RedisCacheConfiguration.defaultCacheConfig()  
                .entryTtl(Duration.ofHours(1)) // 设置默认缓存过期时间  
                .serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(new StringRedisSerializer()))  
                .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(new GenericJackson2JsonRedisSerializer(objectMapper)));  
  
        return RedisCacheManager.builder(connectionFactory)  
                .cacheDefaults(defaultCacheConfig)  
                .build();  
    }  
  
    // 其他配置...  
}

在这个配置中,我们创建了一个CacheManager,它使用RedisCacheManager来管理缓存。我们为缓存条目设置了默认的过期时间,并指定了键和值的序列化器。对于键,我们使用StringRedisSerializer来保持简单性(因为键通常是字符串)。对于值,我们使用GenericJackson2JsonRedisSerializer,它基于Jackson库将对象序列化为JSON字符串。

现在,当你使用@Cacheable、@CachePut或@CacheEvict注解时,Spring Cache将自动使用你配置的CacheManager,并且缓存的数据将以JSON格式存储在Redis中。

请注意,上面的配置假设你已经有一个配置好的RedisConnectionFactory bean在你的Spring Boot应用程序中。这通常是通过Spring Boot的自动配置完成的,但如果你需要自定义Redis连接,你可能需要提供一个自定义的RedisConnectionFactory bean。

此外,ObjectMapper是Jackson库中的一个类,用于配置和序列化Java对象为JSON字符串。在上面的配置中,我们直接注入了ObjectMapper的实例,但你也可以在配置类中创建一个新的实例,并根据需要进行配置。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值