文章目录
- 前言
- [一、redis 的封装](#一、redis 的封装)
-
- [1.1 为什么封装 redis?](#1.1 为什么封装 redis?)
- [1.2 在 common 工程下创建 common-redis 子工程](#1.2 在 common 工程下创建 common-redis 子工程)
- [1.3 添加依赖](#1.3 添加依赖)
- [1.4 创建包目录及 service 包和 config 包](#1.4 创建包目录及 service 包和 config 包)
- [1.5 在 service 包下创建 RedisService 类](#1.5 在 service 包下创建 RedisService 类)
- [1.6 在 service 包下创建 RedissonLockService 类](#1.6 在 service 包下创建 RedissonLockService 类)
- [1.7 对 redis 的默认的序列化器进行更改](#1.7 对 redis 的默认的序列化器进行更改)
-
- [1.7.1 在 config 目录下创建 RedisConfig](#1.7.1 在 config 目录下创建 RedisConfig)
- [1.8 在 resources 下创建自动配置](#1.8 在 resources 下创建自动配置)
- [二、配置 nacos](#二、配置 nacos)
- 三、验证
-
- [3.1 引入依赖](#3.1 引入依赖)
- END
鸡汤:
● 允许自己'电量不足',脆弱里藏着比完美更动人的生命力。
● 你不必做太阳,做一盏记得关掉的台灯就好。------ 累了就暗下来,真正的温柔是先对自己说:'今天,到此为止。
前言
进度:前面我们将基础通用包 common-core 、模板服务、网关服务、以及统一模版搞完了。
现在的项目都要引入一个两个的中间件,而我们作为一个''成熟''的脚手架项目也是要封装那么一两个中间件的!
一、redis 的封装
1.1 为什么封装 redis?
在高性能的应用场景下,Redis 展现出了卓越的性能。它能够轻松应对大量并发请求,为系统提供高效、稳定的缓存支持。这种出色的并发处理能力,使得 Redis 在应对高流量、高负载的复杂业务场景时游刃有余,极大地提升了整个系统的响应速度和处理能力,成为保障系统高性能运行的关键因素之一。
正是因为 Redis 具有这些显著的优势,它才会这么常用,在很多项目中才会使用它作为缓存实现方案,这也是我们在脚手架中封装 Redis 的原因。
1.2 在 common 工程下创建 common-redis 子工程
我们将 redis 单独创建一个工程出来,就是为了达到 ''可插拔''的效果,开发者如果需要就可以引入 common-redis 的依赖,而开发者如果无需要,只要不添加依赖就可以。

1.3 添加依赖
pom.xml:
xml
<?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>
<parent>
<groupId>com.my</groupId>
<artifactId>common</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>
<groupId>com.my</groupId>
<artifactId>common-redis</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-json</artifactId>
</dependency>
<!-- redisson -->
<dependency>
<groupId>org.redisson</groupId>
<artifactId>redisson-spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>com.my</groupId>
<artifactId>common-core</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
</dependencies>
</project>
1.4 创建包目录及 service 包和 config 包

1.5 在 service 包下创建 RedisService 类

封装 redis 提供的方法,思考方向 通用 -> String类型 -> List类型 -> Set类型 -> Zset类型 -> Hash类型
RedisService:
java
package com.my.commonredis.service;
import com.fasterxml.jackson.core.type.TypeReference;
import com.my.commoncore.utils.JsonUtil;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.HashOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import org.springframework.stereotype.Component;
import java.util.*;
import java.util.concurrent.TimeUnit;
@Component
public class RedisService {
@Autowired
private RedisTemplate redisTemplate;
//*********************** 基本操作 **************************
public Boolean expire(final String key, final long timeout) {
return redisTemplate.expire(key, timeout, TimeUnit.SECONDS);
}
//redis设置数据有效时间(可指定时间单位)
public Boolean expire(final String key, final long timeout, final TimeUnit timeUnit) {
return redisTemplate.expire(key, timeout, timeUnit);
}
/**
* 获取有效时间
*
* @param key Redis键
* @return 有效时间
*/
public long getExpire(final String key) {
return redisTemplate.getExpire(key);
}
/**
* 判断 key是否存在
*
* @param key 键
* @return true=存在;false=不存在
*/
public Boolean hasKey(String key) {
return redisTemplate.hasKey(key);
}
/**
* 根据提供的键模式查找 Redis 中匹配的键
*
* @param pattern 要查找的键的模式
* @return 键列表
*/
public Collection<String> keys(final String pattern) {
return redisTemplate.keys(pattern);
}
/**
* 重命名key
*
* @param oldKey 原来key
* @param newKey 新key
*/
public void renameKey(String oldKey, String newKey) {
redisTemplate.rename(oldKey, newKey);
}
/**
* 删除单个数据
*
* @param key 缓存的键值
* @return 是否成功 true=删除成功;false=删除失败
*/
public boolean deleteObject(final String key) {
return redisTemplate.delete(key);
}
/**
* 删除多个数据
*
* @param collection 多个数据对应的缓存的键值
* @return 是否删除了对象 true=删除成功;false=删除失败
*/
public boolean deleteObject(final Collection collection) {
return redisTemplate.delete(collection) > 0;
}
//************************* String类型操作 ****************************/
//修饰符 返回值类型 函数名 参数列表 函数体
// 缓存String数据 key value test aaa
//(将数据转为Json字符串存入)
/**
* 缓存String数据 (将数据转为Json字符串存入)
*
* @param key 缓存的键值
* @param value 缓存的值
* @param <T> 对象类型
*/
public <T> void setCacheObject(String key, T value) {
redisTemplate.opsForValue().set(key,value);
}
// 缓存String数据,并设置有效时间
// (将数据转为Json字符串存入)
/**
* 缓存String数据,并设置有效时间 (将数据转为Json字符串存入)
* @param key 缓存的键值
* @param value 缓存的值
* @param timeout 时间
* @param timeUnit 时间单位
* @param <T> 对象类型
*/
public <T> void setCacheObject(String key, T value, long timeout, TimeUnit timeUnit) {
redisTemplate.opsForValue().set(key,value,timeout,timeUnit);
}
// 缓存String数据,如果该键不存在则存储,若已存在则不存储。
/**
* 缓存String数据,如果该键不存在则存储,若已存在则不存储。
*
* @param key 缓存的键值
* @param value 缓存的值
* @param <T> 对象类型
* @return 是否缓存了对象 如果key已经存在,则返回false,否则返回true
*/
public <T> Boolean setCacheObjectIfAbsent(String key, T value) {
return redisTemplate.opsForValue().setIfAbsent(key,value);
}
/**
* 缓存String数据,如果该键不存在则存储,并设置数据有效时间,若已存在则不存储。
*
* @param key 缓存的键值
* @param value 缓存的值
* @param timeout 时间
* @param timeUnit 时间单位
* @param <T> 对象类型
* @return 是否缓存了对象 如果key已经存在,则返回false,否则返回true
*/
public <T> Boolean setCacheObjectIfAbsent(String key, T value, long timeout, TimeUnit timeUnit) {
return redisTemplate.opsForValue().setIfAbsent(key,value,timeout,timeUnit);
}
// 获得缓存的数据(将缓存的数据反序列化为指定类型返回)
//key : test value
/**
* 获得缓存的数据(将缓存的数据反序列化为指定类型返回)
* @param key 缓存键值
* @param clazz 对应数据的类
* @return 缓存键值对应的数据
* @param <T> 对应数据的类型
*/
public <T> T getCacheObject(String key, Class<T> clazz) {
Object o = redisTemplate.opsForValue().get(key);
if(o==null){
return null;
}
// o 不一定就是 String类型,不能强转
String json = JsonUtil.toJson(o);
return JsonUtil.fromJson(json,clazz);
}
/**
* 获得缓存的数据 (将缓存的数据反序列化为指定类型返回,支持复杂的泛型)
* @param key 缓存键值
* @param valueTypeRef 类型模板
* @return 缓存键值对应的数据
* @param <T> 对象类型
*/
public <T> T getCacheObject(String key, TypeReference<T> valueTypeRef) {
Object o = redisTemplate.opsForValue().get(key);
if(o==null){
return null;
}
// o 不一定就是 String类型,不能强转
String json = JsonUtil.toJson(o);
return JsonUtil.fromJson(json,valueTypeRef);
}
//************************* List类型操作 ****************************/
//修饰符 返回值类型 函数名 参数列表 函数体
//缓存List数据(插入整个list数据,并保持原顺序)
/**
* 缓存List数据
* @param key 缓存的键值
* @param dataList 待缓存的List数据
* @return 添加元素后 Redis 列表的长度
* @param <T> 对象类型
*/
public <T> Long setCacheList (String key, List<T> dataList) {
// redisTemplate.opsForList().leftPushAll()
//rightPushAll 的返回值指的是:添加之后,Redis中当前操作的这个list结构的长度
Long count = redisTemplate.opsForList().rightPushAll(key,dataList);
return count == null ? 0L : count;
}
/**
* 从List结构左侧插入数据(头插、入队)
* @param key key
* @param value 缓存的对象
* @param <T> 值类型
*/
public <T> void leftPushForList(String key,T value) {
redisTemplate.opsForList().leftPush(key,value);
}
/**
* 从List结构右侧插入数据(尾插、插入单个数据)
* @param key key
* @param value 缓存的对象
* @param <T> 值类型
*/
public <T> void rightPushForList(String key,T value) {
redisTemplate.opsForList().rightPush(key,value);
}
/**
* 删除左侧第一个数据 (头删)
* @param key key
*/
public <T> void leftPopForList(String key) {
redisTemplate.opsForList().leftPop(key);
}
/**
* 删除右侧第一个数据 (尾删)
* @param key key
*/
public <T> void rightPopForList(String key) {
redisTemplate.opsForList().rightPop(key);
}
/**
* 移除List第一个匹配的元素
*
* @param key key
* @param value 值
* @param <T> 值类型
*/
public <T> void removeForList(String key,T value) {
redisTemplate.opsForList().remove(key,-1,value);
//删除的方向: > 0 从左往右 <0 从右往左
//key : redis key
///count :删除的方向 & 删除个数(count绝对值的大小 1 -1 =》 1 2 -2 =》2) count > 0 从左往右删除 count < 0 从右往左删除
//count = 0 代表全部删除
}
/**
* 移除List中匹配的所有列表元素
*
* @param key key
* @param value 值
* @param <T> 值类型
*/
public <T> void removeAllForList(String key, T value) {
redisTemplate.opsForList().remove(key,0,value);
}
/**
* 移除指定列表中的所有元素
*
* @param key key
*/
public <T> void removeForAllList(String key) {
redisTemplate.opsForList().trim(key,0,-1);
}
/**
* 修改指定下标数据
* @param key key
* @param index 下标
* @param newValue 修改后新值
* @param <T> 值类型
*/
public <T> void setElementAtIndex(String key,T newValue,int index) {
redisTemplate.opsForList().set(key,index,newValue);
}
/**
* 获得缓存的list对象
* @param key key 缓存的键值
* @param clazz 对象的类
* @return 列表
* @param <T> 对象类型
*/
// Set data = redisTemplate.opsForZSet().range(key, 0, -1);
//range :获取指定范围的数据
//有序性
public <T> List<T> getCacheList(String key, Class<T> clazz) {
List list = redisTemplate.opsForList().range(key,-1,0);
return JsonUtil.fromJsonToList(JsonUtil.toJson(list),clazz);
//key : redis的key
//0 代表第一个元素 1 :第二个元素 2 第三个元素 依次类推 -1 最后一个元素 -2 倒数第二个元素 依次类推
//start : 起始索引(下标)
//end : 结束索引(下标)
}
/**
* 获得缓存的list对象 (支持复杂的泛型嵌套)
* @param key key信息
* @param typeReference 类型模板
* @return list对象
* @param <T> 对象类型
*/
public <T> List<T> getCacheList(String key, TypeReference<List<T>> typeReference) {
List list = redisTemplate.opsForList().range(key,0,-1);
return JsonUtil.fromJson(JsonUtil.toJson(list),typeReference);
}
/**
* 根据范围获取List
*
* @param key key
* @param start 开始位置
* @param end 结束位置
* @param clazz 类信息
* @return List列表
* @param <T> 类型
*/
public <T> List<T> getCacheListByRange(final String key, long start, long end, Class<T> clazz) {
List list = redisTemplate.opsForList().range(key,start,end);
return JsonUtil.fromJsonToList(JsonUtil.toJson(list),clazz);
}
/**
* 根据范围获取List(支持复杂的泛型嵌套 )
*
* @param key key
* @param start 开始
* @param end 结果
* @param typeReference 类型模板
* @return list列表
* @param <T> 类型信息
*/
public <T> List<T> getCacheListByRange(final String key, long start, long end, TypeReference<List<T>> typeReference) {
List list = redisTemplate.opsForList().range(key,start,end);
return JsonUtil.fromJson(JsonUtil.toJson(list),typeReference);
}
/**
* 获取指定列表长度
* @param key key信息
* @return 列表长度
*/
public Long getCacheListSize(String key) {
Long count = redisTemplate.opsForList().size(key);
return count == null ? 0 : count;
}
//************************ 操作Set类型 ***************************
/**
* set添加元素(批量添加或添加单个元素)
* @param key key
* @param member 元素信息
*/
public void addMember(final String key, Object... member) {
redisTemplate.opsForSet().add(key, member);
}
/**
* 删除元素
* @param key key
* @param member 元素信息
*/
public void deleteMember(final String key, Object... member) {
redisTemplate.opsForSet().remove(key, member);
}
/**
* 获取set数据(支持复杂的泛型嵌套)
* @param key key
* @param typeReference 类型模板
* @return set数据
* @param <T> 类型信息
*/
public <T> Set<T> getCacheSet(final String key, TypeReference<Set<T>> typeReference) {
Set data = redisTemplate.opsForSet().members(key);
return JsonUtil.fromJson(JsonUtil.toJson(data), typeReference);
}
//************************ 操作ZSet类型 ***************************
/**
* 添加元素
* @param key key
* @param value 值
* @param seqNo 分数
*/
public void addMemberZSet(String key, Object value, double seqNo) {
redisTemplate.opsForZSet().add(key, value, seqNo);
}
/**
* 删除元素
* @param key key
* @param value 值
*/
public void delMemberZSet(String key, Object value) {
redisTemplate.opsForZSet().remove(key, value);
}
/**
* 根据排序分值删除
*
* @param key key
* @param minScore 最小分
* @param maxScore 最大分
*/
public void removeZSetByScore(final String key, double minScore, double maxScore) {
redisTemplate.opsForZSet().removeRangeByScore(key, minScore, maxScore);
}
/**
* 获取有序集合数据(支持复杂的泛型嵌套)
*
* @param key key信息
* @param typeReference 类型模板
* @return 有序集合
* @param <T> 对象类型
*/
public <T> Set<T> getCacheZSet(final String key, TypeReference<LinkedHashSet<T>> typeReference) {
Set data = redisTemplate.opsForZSet().range(key, 0, -1);
return JsonUtil.fromJson(JsonUtil.toJson(data), typeReference);
}
/**
* 降序获取有序集合(支持复杂的泛型嵌套)
* @param key key信息
* @param typeReference 类型模板
* @return 降序的有序集合
* @param <T> 对象类型信息
*/
public <T> Set<T> getCacheZSetDesc(final String key, TypeReference<LinkedHashSet<T>> typeReference) {
Set data = redisTemplate.opsForZSet().reverseRange(key, 0, -1);
return JsonUtil.fromJson(JsonUtil.toJson(data), typeReference);
}
//************************ 操作Hash类型 ***************************
/**
* 缓存Map数据
* @param key key
* @param dataMap map
* @param <T> 对象类型
*/
public <T> void setCacheMap(final String key, final Map<String, T> dataMap) {
if (dataMap != null) {
redisTemplate.opsForHash().putAll(key, dataMap);
}
}
/**
* 往Hash中存入单个数据
* @param key Redis键
* @param hKey Hash键
* @param value 值
* @param <T> 对象类型
*/
public <T> void setCacheMapValue(final String key, final String hKey, final T value) {
redisTemplate.opsForHash().put(key, hKey, value);
}
/**
* 删除Hash中的某条数据
*
* @param key Redis键
* @param hKey Hash键
* @return 是否成功
*/
public boolean deleteCacheMapValue(final String key, final String hKey) {
return redisTemplate.opsForHash().delete(key, hKey) > 0;
}
/**
* 获取缓存的map数据(支持复杂的泛型嵌套)
* @param key key
* @param typeReference 类型模板
* @return hash对应的map
* @param <T> 对象类型
*/
public <T> Map<String, T> getCacheMap(final String key, TypeReference<Map<String, T>> typeReference) {
Map data= redisTemplate.opsForHash().entries(key);
return JsonUtil.fromJson(JsonUtil.toJson(data), typeReference);
}
/**
* 获取Hash中的单个数据
* @param key Redis键
* @param hKey Hash键
* @return Hash中的对象
* @param <T> 对象类型
*/
public <T> T getCacheMapValue(final String key, final String hKey) {
HashOperations<String, String, T> opsForHash = redisTemplate.opsForHash();
return opsForHash.get(key, hKey);
}
/**
* 获取Hash中的多个数据
*
* @param key Redis键
* @param hKeys Hash键集合
* @param typeReference 对象模板
* @return 获取的多个数据的集合
* @param <T> 对象类型
*/
public <T> List<T> getMultiCacheMapValue(final String key, final Collection<String> hKeys, TypeReference<List<T>> typeReference) {
List data = redisTemplate.opsForHash().multiGet(key, hKeys);
return JsonUtil.fromJson(JsonUtil.toJson(data), typeReference);
}
//******************************** LUA脚本 ***********************************
/**
* 删除指定值对应的 Redis 中的键值(compare and delete)
*
* @param key 缓存key
* @param value value
* @return 是否完成了比较并删除
*/
public boolean cad(String key, String value) {
if (key.contains(StringUtils.SPACE) || value.contains(StringUtils.SPACE)) {
return false;
}
String script = "if redis.call('get', KEYS[1]) == ARGV[1] then return redis.call('del', KEYS[1]) else return 0 end";
// 通过lua脚本原子验证令牌和删除令牌
Long result = (Long) redisTemplate.execute(new DefaultRedisScript<>(script, Long.class),
Collections.singletonList(key),
value);
return !Objects.equals(result, 0L);
}
}
1.6 在 service 包下创建 RedissonLockService 类

提供 Redisson 分布式锁的服务,因为是基于 redis 实现的所以就将它俩放在一起了。
RedissonLockService :
java
package com.my.commonredis.service;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import java.util.concurrent.TimeUnit;
/**
* 分布式锁
*/
@Slf4j
@RequiredArgsConstructor
public class RedissonLockService {
/**
* redis操作客户端
*/
private final RedissonClient redissonClient;
/**
* 获取锁
*
* @param lockKey 锁的key,唯一标识,建议模块名+唯一键
* @param expire 超时时间,单位毫秒,传入-1自动续期
* @return 获取到的RLock实例,为null则获取失败
*/
public RLock acquire(String lockKey, long expire) {
try {
final RLock lockInstance = redissonClient.getLock(lockKey);
// 注意:如果tryLock指定了leaseTime>0就不会续期。参考 RedissonLock类的tryAcquireAsync方法的实现
lockInstance.lock(expire, TimeUnit.MILLISECONDS);
return lockInstance;
} catch (Exception e) {
return null;
}
}
/**
* 释放锁。注意:必须和获取锁在一个线程中
*
* @param lockInstance 锁的实例,acquire返回的
* @return 释放成功返回true,否则返回false
*/
public boolean releaseLock(RLock lockInstance) {
if (lockInstance.isHeldByCurrentThread()) {
lockInstance.unlock();
return true;
}
return false;
}
}
1.7 对 redis 的默认的序列化器进行更改
redis 默认提供的 redisTemplate 的序列化器在序列化的时候会把数据存储为不可读的二进制的数据,随然可能对项目没什么影响,但是如果以后我们就是要看 redis 里的数据呢?
所以我们就要自己创建一个 redisTemplate,交给Spring 容器管理,修改序列化器
1.7.1 在 config 目录下创建 RedisConfig

这里的序列化器使用 GenericJackson2JsonRedisSerializer
RedisConfig:
java
package com.my.commonredis.config;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.MapperFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.databind.json.JsonMapper;
import com.fasterxml.jackson.databind.module.SimpleModule;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer;
import com.my.commondomain.constants.CommonConstants;
import org.springframework.boot.autoconfigure.AutoConfigureBefore;
import org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration;
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;
import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
@AutoConfigureBefore(RedisAutoConfiguration.class)
@Configuration
public class RedisConfig {
@Bean
public RedisTemplate<String, Object> redisTemplate (RedisConnectionFactory redisConnectionFactory) {
RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
redisTemplate.setConnectionFactory(redisConnectionFactory);
//Redis 中key的序列化设置
redisTemplate.setKeySerializer(new StringRedisSerializer());
redisTemplate.setHashKeySerializer(new StringRedisSerializer());
//Redis 中value的序列化设置
GenericJackson2JsonRedisSerializer jsonRedisSerializer = createJacksonSerializer();
redisTemplate.setValueSerializer(jsonRedisSerializer);
redisTemplate.setHashValueSerializer(jsonRedisSerializer);
redisTemplate.afterPropertiesSet();
return redisTemplate;
}
/**
* 创建序列化器
* @return redis序列化器
*/
private GenericJackson2JsonRedisSerializer createJacksonSerializer() {
ObjectMapper OBJECT_MAPPER = JsonMapper.builder()
//反序列化时,如果出现对应Java对象类没有定义的属性时,默认会抛出异常
.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)
//序列化时,将日期转化为时间戳,默认为 true
.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false)
//序列化时,如果序列化的类为 null,设为 true 会报错,false 不会报错,默认为 true
.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false)
.configure(DeserializationFeature.FAIL_ON_INVALID_SUBTYPE, false)
//不适用默认的dateTime进行序列化,使用JSR310的LocalDateTimeSerializer
.configure(SerializationFeature.WRITE_DATE_KEYS_AS_TIMESTAMPS, false)
//设置序列化类上的注解是否生效,默认为 true
.configure(MapperFeature.USE_ANNOTATIONS, false)
//重点,这是序列化LocalDateTIme和LocalDate的必要配置,由Jackson-data-JSR310实现
.addModule(new JavaTimeModule())
.addModule(new SimpleModule()
// 定义 LocalDateTime 序列化和反序列化的格式
.addSerializer(LocalDateTime.class, new LocalDateTimeSerializer(DateTimeFormatter.ofPattern(CommonConstants.STANDARD_FORMAT)))
.addDeserializer(LocalDateTime.class, new LocalDateTimeDeserializer(DateTimeFormatter.ofPattern(CommonConstants.STANDARD_FORMAT)))
)
//所有的日期格式都统一为以下的样式,即yyyy-MM-dd HH:mm:ss
.defaultDateFormat(new SimpleDateFormat(CommonConstants.STANDARD_FORMAT))
// 只针对非空的值进行序列化
.serializationInclusion(JsonInclude.Include.NON_NULL)
.build();
return new GenericJackson2JsonRedisSerializer(OBJECT_MAPPER);
}
}
注:
@AutoConfigureBefore(RedisAutoConfiguration.class) 这个注解是抢在 RedisAutoConfiguration 前注册 Bean ,如果不加这个,后面在给网关服务引入相关服务时,启动会报错,说有两个 Bean
1.8 在 resources 下创建自动配置
自动配置目录 : META.spring.org.springframework.boot.autoconfigure.AutoConfiguration.imports

将他们三个全部交给 Spring 容器管理

二、配置 nacos
因为想要使用 redis 必然需要 redis 的地址配置啥的。我们将 redis 的配置放在 nacos 里这样引入了 redis 依赖的服务,都可以在 nacos 拿到 redis 的配置


三、验证
再次拿 mstemplate 模版服务来进行验证,将 common-redis 的依赖引入模板服务,搞一个 controller 层,拿apifox验证一下
3.1 引入依赖

我自己当时全验证了一遍,现在就简单的验一下
TestRedisController:
java
package com.my.mstemplateservice.test;
import com.fasterxml.jackson.core.type.TypeReference;
import com.my.commondomain.domain.vo.R;
import com.my.commonredis.service.RedisService;
import com.my.mstemplateservice.domain.RegionTest;
import com.my.mstemplateservice.domain.User;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.*;
@RestController
@Slf4j
@RequestMapping("/test/redis")
public class TestRedisController {
@Autowired
private RedisService redisService;
@PostMapping("/add")
public R<Void> add () {
// redisService.setCacheObject("key", "value");
// redisService.setCacheObject("key", "value123",15, TimeUnit.SECONDS);
// Boolean b = redisService.setCacheObjectIfAbsent("key", "value123");
// if (!b) {
// return R.fail(ResultCode.FAILED.getCode(),ResultCode.FAILED.getMsg());
// }
// Boolean b = redisService.setCacheObjectIfAbsent("key", "value123",15, TimeUnit.SECONDS);
// if (!b) {
// return R.fail(ResultCode.FAILED.getCode(),ResultCode.FAILED.getMsg());
// }
RegionTest testRegion = new RegionTest();
testRegion.setId(1L);
testRegion.setName("北京");
testRegion.setFullName("北京市");
testRegion.setCode("110000");
List<Map<String, RegionTest>> list = new ArrayList<>();
Map<String, RegionTest> map = new LinkedHashMap<>();
map.put("beijing", testRegion);
list.add(map);
redisService.setCacheObject("testList",list);
return R.success();
}
@GetMapping("/get")
public R<Void> get () {
// String value = redisService.getCacheObject("key", String.class);
// System.out.println(value);
//将redis中的数据获取出来 对象的类型不会产生泛型擦除问题
List<Map<String, RegionTest>> testList = redisService.getCacheObject("testList", new TypeReference<List<Map<String, RegionTest>>>() {
});
System.out.println(testList);
return R.success();
}
@PostMapping("/list/add")
public R<Void> listAdd() {
// String str = "listKey";
// List<String> list = new ArrayList<>();
// list.add("a");
// list.add("c");
// list.add("d");
// list.add("g");
// list.add("a");
// list.add("b");
// list.add("c");
// list.add("c");
// list.add("a");
// redisService.setCacheList(str,list);
// 在左边第一位插入元素
// redisService.leftPushForList(str,"d");
// 在右边第一位插入元素
// redisService.rightPushForList(str,"p");
// String userListKey = "userListKey";
// List<User> list = new ArrayList<>();
// list.add(new User("zhangsan",21));
// list.add(new User("list",31));
// list.add(new User("wangwu",26));
// redisService.setCacheList(userListKey,list);
String userListMapKey = "userListMap";
List<Map<String,User>> list = new ArrayList<>();
// list.add(Map.of("1",new User("zhangsan",21)));
// list.add(Map.of("2",new User("list",31)));
// list.add(Map.of("3",new User("wangwu",26)));
list.add(Map.of("1",new User("zhangsan",21),"2",new User("list",31)));
list.add(Map.of("3",new User("wangwu",26)));
redisService.setCacheList(userListMapKey,list);
return R.success();
}
@DeleteMapping("/list/delete")
public R<Void> listDel() {
String str = "listKey";
// 删除从左到右的第一个 匹配元素
// redisService.removeForList(str,"c");
// 删除从右到左的第一个 匹配元素
// redisService.removeForList(str,"a");
// 删除左边第一个元素
// redisService.leftPopForList(str);
// 删除右边第一个元素
// redisService.rightPopForList(str);
// 删除 list 中的所有指定元素
redisService.removeAllForList(str,"a");
return R.success();
}
@GetMapping("/list/get")
public R<Void> listGet() {
// String str = "listKey";
// get 简单结构的 list
// List<String> cacheList = redisService.getCacheList(str, String.class);
// System.out.println(cacheList);
// List<User> userListKey = redisService.getCacheList("userListKey", User.class);
// System.out.println(userListKey);
// get 复杂结构的 list
List<Map<String, User>> userListMap = redisService.getCacheList("userListMap", new TypeReference<List<Map<String, User>>>() {
});
System.out.println(userListMap);
return R.success();
}
@PostMapping("/type/add")
public R<Void> typeAdd() {
// String str = "setKey";
// redisService.addMember(str,"a");
// redisService.addMember(str,"c");
// redisService.addMember(str,"d");
// redisService.addMember(str,"e","c","f");
// redisService.addMember(str,"a");
// redisService.addMember(str,"c");
// String zsetKey = "zset";
// redisService.addMemberZSet(zsetKey,"zhangsan",13.5);
// redisService.addMemberZSet(zsetKey,"lisi",3.6);
// redisService.addMemberZSet(zsetKey,"wangwu",5.7);
// redisService.addMemberZSet(zsetKey,"kk",1);
// String hashKey = "user1";
// User user = new User();
// user.setName("zhangsan");
// user.setAge(45);
// User user = new User();
// user.setName("wangwu");
// user.setAge(30);
// redisService.setCacheMap(hashKey, JsonUtil.convertToMap(user));
// redisService.setCacheMapValue(hashKey,"name","lisi");
// redisService.setCacheMap("user2",JsonUtil.convertToMap(user));
// redisService.setCacheMapValue(hashKey,"address","内蒙古");
// String str = "setKey";
// redisService.renameKey(str,"listKey");
return R.success();
}
@DeleteMapping("/type/delete")
public R<Void> typeDel() {
// String str = "setKey";
// redisService.deleteMember(str,"a");
// redisService.deleteMember(str,"d");
// redisService.deleteMember(str,"c","f");
// String zsetKey = "zset";
// redisService.delMemberZSet(zsetKey,"zhangsan");
// redisService.removeZSetByScore(zsetKey,1,6.0);
// String str = "setKey";
// redisService.expire("setKey",15,TimeUnit.SECONDS);
// String hashKey = "user1";
// redisService.deleteCacheMapValue(hashKey,"address");
// String str = "listKey";
// redisService.deleteObject(str);
List<String> delList = new ArrayList<>();
delList.add("user1");
delList.add("user2");
redisService.deleteObject(delList);
return R.success();
}
@GetMapping("/type/get")
public R<Void> typeGet() {
// String str = "setKey";
// Set<String> cacheSet = redisService.getCacheSet(str, new TypeReference<Set<String>>() {
// });
// System.out.println(cacheSet);
// String zsetKey = "zset";
// Set<String> cacheZSet = redisService.getCacheZSet(zsetKey, new TypeReference<LinkedHashSet<String>>() {
// });
// Set<String> cacheZSet = redisService.getCacheZSetDesc(zsetKey, new TypeReference<LinkedHashSet<String>>() {
// });
// System.out.println(cacheZSet);
String hashKey = "user1";
// Map<String, Object> cacheMap = redisService.getCacheMap(hashKey, new TypeReference<Map<String, Object>>() {
// });
// System.out.println(cacheMap);
// Object name = redisService.getCacheMapValue(hashKey, "age");
// System.out.println(name);
List<String> list = new ArrayList<>();
list.add("name");
list.add("age");
List<String> multiCacheMapValue = redisService.getMultiCacheMapValue(hashKey, list, new TypeReference<List<String>>() {
});
System.out.println(multiCacheMapValue);
return R.success();
}
}

这个 redis 的可视化管理界面是 Another Redis Desktop Manager

END
redis 中间件封装完毕!