Redis是一个高性能的开源的、C语言写的Nosql(非关系型数据库)。Redis通常用于数据缓存(Cache),作用是减少服务器业务代码对数据库的访问频率。简单的理解,就是将数据库查询的结果缓存到Redis中,等下次查询的时候,直接从Redis中获取数据,而不再查询数据了。因为Redis的内存存储比MySQL的硬盘存储要快的多。
如何安装Redis请查看:Windows安装Redis-优快云博客
首先,我们使用IDEA创建一个“SpringBootRedisDemo”的Maven工程。
然后我们修改编码格式以及Maven仓库地址,我们省略这个过程了。
接下来,我们修改 “pom.xml” 文件,添加SpringBoot和SpringBootRedis依赖,如下所示
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.demo</groupId>
<artifactId>SpringBootRedisDemo</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
</properties>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.6.13</version>
<relativePath/>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>2.7.18</version>
</plugin>
</plugins>
</build>
</project>
接下来,我们创建 Appliaction 入口类文件
package com.demo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
接下来,我们要创建 application.properties 中配置Redis
spring.redis.host=127.0.0.1
spring.redis.port=6379
#spring.redis.password=123456
spring.redis.database=1
如果有连接密码的话,就设置上,没有就不用写了。注意,我们使用Redis中第1个数据库哦。
Redis的Java客户端常见的有jedis, redission,lettuce等等,所以我们在集成的时候,我们可以选择直接集成这些原生客户端。默认情况下,spring-boot-starter-data-redis 使用的就是lettuce这个客户端。
重点来了,spring-data-redis 为我们提供的 RedisTemplate 类来读写Redis缓存数据。
Redis中 string, list, hash,set, zset五种数据格式,都在RedisTemplate这个类中进行了封装。
RedisTemplate常用方法如下:
redisTemplate.opsForValue(); // 操作字符串
redisTemplate.opsForList(); // 操作list
redisTemplate.opsForHash(); // 操作hash
redisTemplate.opsForSet(); // 操作set
redisTemplate.opsForZSet(); // 操作有序set
redisTemplate.delete() // 根据key删除
接下来,我们写入一个字符串类型
redisTemplate.opsForValue().set(key, value);
然后,我们创建一个 TestCache.java 类来测试一下
package com.demo.cache;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
@Component
public class TestCache {
@Autowired
private RedisTemplate redisTemplate;
public void testSetStr(String key, String val){
redisTemplate.opsForValue().set(key, val);
}
public String testGetStr(String key){
return redisTemplate.opsForValue().get(key).toString();
}
}
Redis中的数据以 key-value 形式保存在内存中,其value就是Redis中string, list, hash,set, zset五种数据格式。接下来,我们创建“TestController.java”控制器来调用上面的TestCache
package com.demo.controller;
import com.demo.cache.TestCache;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import java.util.Map;
@Controller
public class TestController {
@Autowired
private TestCache testCache;
private final String key = "message";
@RequestMapping("/testset")
public String testset(String val, Map<String, Object> map){
testCache.testSetStr(key, val);
map.put("message", "");
return "test";
}
@RequestMapping("/testget")
public String testget(Map<String, Object> map){
String msg = testCache.testGetStr(key);
map.put("message", msg);
return "test";
}
}
接下来,我们创建 “resources\static\index.html” 和 “resources\templates\test.html” 视图文件
<!doctype html>
<html lang="zh-CN">
<head>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>index</title>
</head>
<body>
<a href="/testset?val=hello">testset?val=hello</a>
<br />
<a href="/testget">testget</a>
</body>
</html>
<!doctype html>
<html lang="zh-CN" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>test</title>
</head>
<body>
<div th:text="${message}"></div>
</body>
</html>
我们整体工程的结构如下
我们运行一下,查看结果
此时已经将“message=hello”放入Redis中了。
可以查询到了,我们重复刷新页面的话,这个“hello”会一直存在的,直到我们删除或者Redis过期删除掉。我们可以通过 “RedisDesktopManager” 查看一下
对于缓存的数据,我们还可以删除它们,以及给他们设置缓存时间,如下所示:
public void testDelStr(String key){
redisTemplate.delete(key);
}
public void testSetStrExpire(String key, String val, long timeout){
redisTemplate.opsForValue().set(key, val, timeout, TimeUnit.SECONDS);
}
删除方法不用介绍了,设置缓存时间的话,我们可以指定时间数值和时间单位。
接下来,我们在“TestController.java”控制器中调用一下
@RequestMapping("/testset")
public String testset(String val, Map<String, Object> map){
//testCache.testSetStr(key, val);
testCache.testSetStrExpire(key, val, 300);
map.put("message", "");
return "test";
}
@RequestMapping("/testdel")
public String testdel(Map<String, Object> map){
testCache.testDelStr(key);
map.put("message", "");
return "test";
}
接下来,我们在修改“index.html”文件
<a href="/testset?val=hello">testset?val=hello</a>
<br />
<a href="/testget">testget</a>
<br />
<a href="/testdel">testdel</a>
我们重新运行,测试一下
此时,缓存数据已经被我们删除了。我们直接查看“testget”请求页面
报错了,我们查看控制台日志
原因是,空指针异常,也就是我们的缓存数据不存在了。
public String testGetStr(String key){
if(redisTemplate.hasKey(key)){
return redisTemplate.opsForValue().get(key).toString();
}else{
return "null";
}
}
我们做一个是否存在的操作即可。
接下来,我们重新缓存这个数据,也就是重新请求 “testset?val=hello” 页面,对数据缓存5分钟。
我们等待5分钟之后,刷新这个页面。
接下来,我们存储一个Java对象进去试试。
package com.demo.data;
import java.io.Serializable;
public class UserInfo implements Serializable {
private int id;
private String name;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
我们定义了一个数据对象UserInfo类,它继承了 Serializable 序列化接口(必须的)。
public void testSetObj(String key, UserInfo data){
redisTemplate.opsForValue().set(key, data);
}
public UserInfo testGetObj(String key){
return (UserInfo)redisTemplate.opsForValue().get(key);
}
我们在 “testCache.java” 中增加缓存 UserInfo 类的方法。
@RequestMapping("/testsetobj")
public String testsetobj(Map<String, Object> map){
UserInfo data = new UserInfo();
data.setId(1);
data.setName("张三");
testCache.testSetObj(key, data);
map.put("message", data.getName());
return "test";
}
@RequestMapping("/testgetobj")
public String testgetobj(Map<String, Object> map){
UserInfo data = testCache.testGetObj(key);
map.put("message", data.getName());
return "test";
}
我们在“testController.java”中调用上面的方法
<a href="/testset?val=hello">testset?val=hello</a>
<br />
<a href="/testget">testget</a>
<br />
<a href="/testdel">testdel</a>
<br />
<a href="/testsetobj">testsetobj</a>
<br />
<a href="/testgetobj">testgetobj</a>
添加入口连接之后,我们重新运行,测试一下
此时Java对象已经被缓存到Redis中了。
我们请求“testgetobj”页面也能看到了。
我们通过“RedisDesktopManager”去查看一下
默认是16进制显示,我们可以改成纯文本形式
大概也能看明白。
我们注意到 redisTemplate.opsForValue().set(key, data); 方法的data参数是一个泛型,它不仅支持字符串,也支持写入Object对象的。那么这个对象采取什么方式存入内存中就是它的序列化方式。spring-boot-starter-data-redis中使用JdkSerializationRedisSerializerl来实现序列化。这种序列化最大的问题就是存入对象后,我们很难直观看到存储的内容,很不方便我们排查问题。因此,我们需要修改一个RedisTemplate的序列化方式。目前比较流行的序列化方式,是将数据转成json格式进行缓存。因为json格式的字符串和Java对象可以进行相互转化。
首先,我们需要引入json库文件,这里我们使用阿里巴巴的fastjson库,它是阿里开源的一个高性能的JSON框架,FastJson支持序列化(把JavaBean对象转化成Json格式的字符串)和反序列化(把JSON格式的字符串转化为Java Bean对象)。
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.83</version>
</dependency>
接下来,我们增加一个配置类来修改Redis的默认序列化
package com.demo.config;
import com.alibaba.fastjson.support.spring.FastJsonRedisSerializer;
import org.springframework.boot.autoconfigure.security.SecurityProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
@Configuration
public class RedisConfiguration {
@Bean
public RedisTemplate redisTemplate(RedisConnectionFactory redisConnectionFactory) {
RedisTemplate redisTemplate = new RedisTemplate();
redisTemplate.setConnectionFactory(redisConnectionFactory);
FastJsonRedisSerializer fastJsonRedisSerializer = new FastJsonRedisSerializer(SecurityProperties.User.class);
redisTemplate.setDefaultSerializer(fastJsonRedisSerializer);
return redisTemplate;
}
}
接下来,我们重新测试一下
缓存普通的字符串
缓存Java对象
现在,我们可以直观的看到缓存内容了。
完整 “SpringBootRedisDemo” 工程文件下载: https://download.youkuaiyun.com/download/richieandndsc/89904311