Spring Boot之集成Redis(二):集成Redis

前言

来啦老铁!

笔者学习Spring Boot有一段时间了,附上Spring Boot系列学习文章,欢迎取阅、赐教:

  1. 5分钟入手Spring Boot;
  2. Spring Boot数据库交互之Spring Data JPA;
  3. Spring Boot数据库交互之Mybatis;
  4. Spring Boot视图技术;
  5. Spring Boot之整合Swagger;
  6. Spring Boot之junit单元测试踩坑;
  7. 如何在Spring Boot中使用TestNG;
  8. Spring Boot之整合logback日志;
  9. Spring Boot之整合Spring Batch:批处理与任务调度;
  10. Spring Boot之整合Spring Security: 访问认证;
  11. Spring Boot之整合Spring Security: 授权管理;
  12. Spring Boot之多数据库源:极简方案;
  13. Spring Boot之使用MongoDB数据库源;
  14. Spring Boot之多线程、异步:@Async;
  15. Spring Boot之前后端分离(一):Vue前端;
  16. Spring Boot之前后端分离(二):后端、前后端集成;
  17. Spring Boot之前后端分离(三):登录、登出、页面认证;
  18. Spring Boot之面向切面编程:Spring AOP;
  19. Spring Boot之集成Redis(一):Redis初入门;

在上一篇文章Spring Boot之集成Redis(一):Redis初入门中,我们初步入门了Redis,熟悉了Redis的安装、配置、本数据类型以及基本操作。今天,我们一起来尝试在Spring Boot项目中集成Redis,一起在Spring Boot完成一些Redis基本操作吧!

项目代码已上传Git Hub仓库,欢迎取阅:

基本步骤

  1. 安装Redis依赖;
  2. 配置application.properties;
  3. 使用StringRedisTemplate操作Redis;

1. 安装Redis依赖;

在项目的pom.xml文件内的dependencies节点内添加redis依赖:

<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
记得安装一下依赖:
mvn install -Dmaven.test.skip=true -Dmaven.wagon.http.ssl.insecure=true -Dmaven.wagon.http.ssl.allowall=true

2. 配置application.properties;

这里作用主要是配置Redis服务端的连接,配置如下:

#Redis服务端的host和port
spring.redis.host=127.0.0.1
spring.redis.port=6379
#Redis服务端的密码
spring.redis.password=Redis!123
#Redis最大连接数
spring.redis.pool.max-active=8
#Redis连接超时时间,单位 ms(毫秒)
spring.redis.timeout=5000

其中spring.redis.pool.max-active指定了Spring Boot应用的最大连接数,若设置为0,则表示无限制。

3. 使用StringRedisTemplate操作Redis;

我的思路是创建一个API,在该API内使用Redis的基本命令,进而演示在Spring Boot项目中与Redis的交互过程。

(我们先来演示Redis数据类型为String的)

1). 创建controller包,并在包内创建RedisStringController类;
2). 创建domain包,并创建实体类RedisStringCache,用于声明Redis String缓存对象格式;

代码如下:

package com.github.dylanz666.domain;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.stereotype.Component;

import java.io.Serializable;

/**
 * @author : dylanz
 * @since : 10/28/2020
 */
@NoArgsConstructor
@AllArgsConstructor
@Data
@Component
public class RedisStringCache implements Serializable {
    private static final long serialVersionUID = 1L;

    private String key;
    private String value;

    @Override
    public String toString() {
        return "{" +
                "\"key\":\"" + key + "\"," +
                "\"value\":" + value + "" +
                "}";
    }
}
3). 在RedisStringController类内添加演示用的API,代码如下:
package com.github.dylanz666.controller;

import com.github.dylanz666.domain.RedisStringCache;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.web.bind.annotation.*;

/**
 * @author : dylanz
 * @since : 10/28/2020
 */
@RestController
@RequestMapping("/api/cache")
public class RedisStringController {
    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    @PostMapping("/string")
    public @ResponseBody RedisStringCache redisStringCache(@RequestBody RedisStringCache redisStringCache) {
        String key = redisStringCache.getKey();
        String value = redisStringCache.getValue();

        stringRedisTemplate.opsForValue().set(key, value);
        String cachedValue = stringRedisTemplate.opsForValue().get(key);

        RedisStringCache cached = new RedisStringCache();
        cached.setKey(key);
        cached.setValue(cachedValue);
        return cached;
    }
}

项目整体结构:

项目整体结构

上述步骤完成后,我们开始来做演示:

(1). 启动Redis服务端;
启动Redis服务端
(2). 启动Spring Boot应用;
启动Spring Boot应用
(3). 调用API进行Redis交互演示;

请求API:http://127.0.0.1:8080/api/cache/string

请求API
(4). 通过redis-cli方式,再次验证是否缓存成功;
再次验证是否缓存成功

可见,我们已在Spring Boot项目中与Redis服务端交互成功啦!

stringRedisTemplate.opsForValue().set(key, value);

上面这一行代码,相当于redis-cli连接Redis服务端方式的 set key value 操作;

stringRedisTemplate.opsForValue().get(key);

上面这一行代码,相当于redis-cli连接Redis服务端方式的 get key 操作;

接下来,我们一起来尝试在Spring Boot项目中做更多的Redis基本操作!

(演示Redis数据类型为hash的)

1). domain包内创建RedisHashCache实体类,用于声明Redis hash缓存对象格式;
package com.github.dylanz666.domain;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.stereotype.Component;

import java.io.Serializable;

/**
 * @author : dylanz
 * @since : 10/28/2020
 */
@NoArgsConstructor
@AllArgsConstructor
@Data
@Component
public class RedisHashCache implements Serializable {
    private static final long serialVersionUID = 1L;

    private String key;
    private String field;
    private String value;

    @Override
    public String toString() {
        return "{" +
                "\"key\":\"" + key + "\"," +
                "\"field\":\"" + field + "\"," +
                "\"value\":" + value + "" +
                "}";
    }
}
2). RedisStringController内编写演示API:
@PostMapping("/hash")
public @ResponseBody RedisHashCache redisHashCache(@RequestBody RedisHashCache redisHashCache) {
    String key = redisHashCache.getKey();
    String field = redisHashCache.getField();
    String value = redisHashCache.getValue();

    stringRedisTemplate.opsForHash().put(key, field, value);
    String cachedValue = Objects.requireNonNull(stringRedisTemplate.opsForHash().get(key, field)).toString();

    RedisHashCache cached = new RedisHashCache();
    cached.setKey(key);
    cached.setField(field);
    cached.setValue(cachedValue);
    return cached;
}
stringRedisTemplate.opsForHash().put(key, field, value);

上面这行代码等同于redis-cli中使用命令:hset key field value;

stringRedisTemplate.opsForHash().get(key, field);

上面这行代码等同于redis-cli中使用命令:hget key field;

(3). 调用API进行Redis交互演示;

请求API:http://127.0.0.1:8080/api/cache/hash

请求API

(演示Redis数据类型为list的)

1). domain包内创建RedisListCache实体类,用于声明Redis list缓存对象格式;
package com.github.dylanz666.domain;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.stereotype.Component;

import java.io.Serializable;
import java.util.List;

/**
 * @author : dylanz
 * @since : 10/28/2020
 */
@NoArgsConstructor
@AllArgsConstructor
@Data
@Component
public class RedisListCache implements Serializable {
    private static final long serialVersionUID = 1L;

    private String key;
    private List<String> list;

    @Override
    public String toString() {
        return "{" +
                "\"key\":\"" + key + "\"," +
                "\"list\":" + list + "" +
                "}";
    }
}
2). RedisStringController内编写演示API:
@PostMapping("/list")
public @ResponseBody RedisListCache redisListCache(@RequestBody RedisListCache redisListCache) {
    String key = redisListCache.getKey();
    List<String> list = redisListCache.getList();

    stringRedisTemplate.opsForList().leftPushAll(key, list);
    List<String> cachedList = stringRedisTemplate.opsForList().range(key, 0, -1);

    RedisListCache cached = new RedisListCache();
    cached.setKey(key);
    cached.setList(cachedList);
    return cached;
}
stringRedisTemplate.opsForList().leftPushAll(key, list);

上面这行代码等同于redis-cli中使用命令:lpush key value...;

stringRedisTemplate.opsForList().range(key, 0, -1);

上面这行代码等同于redis-cli中使用命令:lrange key 0 -1;

(3). 调用API进行Redis交互演示;

请求API:http://127.0.0.1:8080/api/cache/list

请求API

(演示Redis数据类型为set的)

1). domain包内创建RedisSetCache实体类,用于声明Redis set缓存对象格式;
package com.github.dylanz666.domain;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.stereotype.Component;

import java.io.Serializable;
import java.util.Arrays;

/**
 * @author : dylanz
 * @since : 10/28/2020
 */
@NoArgsConstructor
@AllArgsConstructor
@Data
@Component
public class RedisSetCache implements Serializable {
    private static final long serialVersionUID = 1L;

    private String key;
    private String[] sets;

    @Override
    public String toString() {
        return "{" +
                "\"key\":\"" + key + "\"," +
                "\"sets\":" + Arrays.toString(sets) + "" +
                "}";
    }
}
2). RedisStringController内编写演示API:
@PostMapping("/set")
public @ResponseBody RedisSetCache redisSetCache(@RequestBody RedisSetCache redisSetCache) {
    String key = redisSetCache.getKey();
    String[] sets = redisSetCache.getSets();

    stringRedisTemplate.opsForSet().add(key, sets);
    Set<String> cacheSets = stringRedisTemplate.opsForSet().members(key);

    RedisSetCache cached = new RedisSetCache();
    cached.setKey(key);
    assert cacheSets != null;
    cached.setSets(cacheSets.toArray(sets));
    return cached;
}
stringRedisTemplate.opsForSet().add(key, sets);

上面这行代码等同于redis-cli中使用命令:sadd key value...;

stringRedisTemplate.opsForSet().members(key);

上面这行代码等同于redis-cli中使用命令:smembers key;

(3). 调用API进行Redis交互演示;

请求API:http://127.0.0.1:8080/api/cache/set

请求API

(演示Redis数据类型为zset的)

1). domain包内创建RedisZsetCache实体类,用于声明Redis zset缓存对象格式;
package com.github.dylanz666.domain;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.stereotype.Component;

import java.io.Serializable;
import java.util.Set;

/**
 * @author : dylanz
 * @since : 10/28/2020
 */
@NoArgsConstructor
@AllArgsConstructor
@Data
@Component
public class RedisZsetCache implements Serializable {
    private static final long serialVersionUID = 1L;

    private String key;
    private String value;
    private double score;
    private Set<String> zset;


    @Override
    public String toString() {
        return "{" +
                "\"key\":\"" + key + "\"," +
                "\"value\":\"" + value + "\"," +
                "\"score\":\"" + score + "\"," +
                "\"zset\":" + zset + "" +
                "}";
    }
}
2). RedisStringController内编写演示API:
@PostMapping("/zset")
public @ResponseBody RedisZsetCache redisZsetCache(@RequestBody RedisZsetCache redisZsetCache) {
    String key = redisZsetCache.getKey();
    String value = redisZsetCache.getValue();
    double score = redisZsetCache.getScore();

    stringRedisTemplate.opsForZSet().add(key, value, score);

    Set<String> cachedZset = stringRedisTemplate.opsForZSet().rangeByScore(key, score, score);

    RedisZsetCache cached = new RedisZsetCache();
    cached.setKey(key);
    cached.setValue(value);
    cached.setScore(score);
    cached.setZset(cachedZset);
    return cached;
}
stringRedisTemplate.opsForZSet().add(key, value, score);

上面这行代码等同于redis-cli中使用命令:zadd key score value;

stringRedisTemplate.opsForZSet().rangeByScore(key, score, score);

上面这行代码等同于redis-cli中使用命令:zrangebyscore key min max;

(3). 调用API进行Redis交互演示;

请求API:http://127.0.0.1:8080/api/cache/zset

请求API

最后,来演示设置一个会过期的Redis缓存(演示缓存2分钟):

@PostMapping("/expire/string")
public @ResponseBody RedisStringCache redisStringCacheWithExpireTime(@RequestBody RedisStringCache redisStringCache) {
    String key = redisStringCache.getKey();
    String value = redisStringCache.getValue();

    stringRedisTemplate.opsForValue().set(key, value, Duration.ofMinutes(2));
    String cachedValue = stringRedisTemplate.opsForValue().get(key);

    RedisStringCache cached = new RedisStringCache();
    cached.setKey(key);
    cached.setValue(cachedValue);
    return cached;
}
缓存2分钟

通过这样的Redis操作,我们设置了一个2分钟后失效的String类型的Redis缓存,并且的确2分钟后缓存失效了!

更多操作和redis接口,可直接使用stringRedisTemplate,获取代码建议:
redis接口

以上是我们使用StringRedisTemplate来与Redis进行交互的过程,涉及存、取数据,读者可自行根据StringRedisTemplate提供的接口,对Redis进行增删改查。

实际使用场景中,通常是在第一次存到其他数据库时,会缓存到Redis,并设置一定的缓存过期时间,而后续的请求会先从Redis缓存中获取,减少数据库访问次数,降低数据库服务器的压力!

使用StringRedisTemplate来与Redis进行交互的过程是正确、灵活的,这一点毋庸置疑,但整体代码还是比较多的,略显臃肿,其实有更简约的方式来操作Redis,这里剧透一下:

下一篇文章我将介绍基于Spring Cache方式操作Redis,操作Redis缓存也能用注解的方式,敬请期待!

如果本文对您有帮助,麻烦点赞、关注!

谢谢!

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,372评论 6 498
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,368评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,415评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,157评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,171评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,125评论 1 297
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,028评论 3 417
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,887评论 0 274
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,310评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,533评论 2 332
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,690评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,411评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,004评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,659评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,812评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,693评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,577评论 2 353