diff --git a/common/mall-spring-boot-starter-cache/pom.xml b/common/mall-spring-boot-starter-cache/pom.xml
new file mode 100644
index 000000000..f41982b20
--- /dev/null
+++ b/common/mall-spring-boot-starter-cache/pom.xml
@@ -0,0 +1,36 @@
+
+
+
+ onemall
+ cn.iocoder.mall
+ 1.0-SNAPSHOT
+
+ 4.0.0
+
+ mall-spring-boot-starter-cache
+
+
+
+ org.springframework.boot
+ spring-boot-starter-data-redis
+
+
+
+ org.redisson
+ redisson
+ 3.10.6
+
+
+
+ redis.clients
+ jedis
+ 3.1.0
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/common/mall-spring-boot-starter-cache/src/main/java/cn/iocoder/mall/cache/config/JedisClient.java b/common/mall-spring-boot-starter-cache/src/main/java/cn/iocoder/mall/cache/config/JedisClient.java
new file mode 100644
index 000000000..6a5ef8dd5
--- /dev/null
+++ b/common/mall-spring-boot-starter-cache/src/main/java/cn/iocoder/mall/cache/config/JedisClient.java
@@ -0,0 +1,79 @@
+package cn.iocoder.mall.cache.config;
+
+
+import org.springframework.stereotype.Component;
+import org.springframework.util.StringUtils;
+import redis.clients.jedis.Jedis;
+import redis.clients.jedis.JedisSentinelPool;
+
+import javax.annotation.PostConstruct;
+import javax.annotation.Resource;
+
+
+@Component
+public class JedisClient {
+
+ @Resource
+ private static JedisSentinelPool jedisSentinelPool;
+
+ public static String get(String key) {
+ Jedis jedis = null;
+ try {
+ jedis = jedisSentinelPool.getResource();
+ return jedis.get(key);
+ } catch (Exception e) {
+ } finally {
+ if (jedis != null) {
+ jedis.close();
+ }
+ }
+ return "";
+ }
+
+ public static boolean set(String key, String value) {
+ Jedis jedis = null;
+ try {
+ jedis = jedisSentinelPool.getResource();
+ String ret = jedis.set(key, value);
+ return "ok".equalsIgnoreCase(ret);
+ } catch (Exception e) {
+ } finally {
+ if (jedis != null) {
+ jedis.close();
+ }
+ }
+ return false;
+ }
+
+ public static boolean set(String key, String value, int seconds) {
+ Jedis jedis = null;
+ try {
+ jedis = jedisSentinelPool.getResource();
+ String ret = jedis.set(key, value);
+ jedis.expire(key, seconds);
+ return "ok".equalsIgnoreCase(ret);
+ } catch (Exception e) {
+ } finally {
+ if (jedis != null) {
+ jedis.close();
+ }
+ }
+ return false;
+ }
+
+ public static boolean del(String key) {
+ Long removedSize = 0L;
+ Jedis jedis = null;
+ try {
+ jedis = jedisSentinelPool.getResource();
+ removedSize = jedis.del(key);
+ } catch (Exception e) {
+ } finally {
+ if (jedis != null) {
+ jedis.close();
+ }
+ }
+ return removedSize > 0;
+ }
+
+}
diff --git a/common/mall-spring-boot-starter-cache/src/main/java/cn/iocoder/mall/cache/config/RedissonClient.java b/common/mall-spring-boot-starter-cache/src/main/java/cn/iocoder/mall/cache/config/RedissonClient.java
new file mode 100644
index 000000000..baf19fda4
--- /dev/null
+++ b/common/mall-spring-boot-starter-cache/src/main/java/cn/iocoder/mall/cache/config/RedissonClient.java
@@ -0,0 +1,51 @@
+package cn.iocoder.mall.cache.config;
+
+
+import org.redisson.Redisson;
+import org.redisson.config.Config;
+import org.redisson.config.ReadMode;
+import org.redisson.config.SentinelServersConfig;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.context.annotation.Bean;
+import org.springframework.stereotype.Component;
+
+
+import javax.annotation.Resource;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+
+@Component
+public class RedissonClient {
+
+ @Value("${spring.redis.database}")
+ private int database;
+
+ @Value("${spring.redis.sentinel.master}")
+ private String master;
+
+ @Value("${spring.redis.sentinel.nodes}")
+ private String nodes;
+
+ /**
+ * 哨兵模式 redisson 客户端
+ * @return
+ */
+ @Bean
+ public org.redisson.api.RedissonClient redissonClient() {
+ Config config = new Config();
+ List nodes = Arrays.asList(this.nodes.split(","));
+ List newNodes = new ArrayList(nodes.size());
+ nodes .forEach((index) -> newNodes.add(
+ index.startsWith("redis://") ? index : "redis://" + index));
+
+ SentinelServersConfig serverConfig = config.useSentinelServers()
+ .addSentinelAddress(newNodes.toArray(new String[3]))
+ .setMasterName(this.master)
+ .setReadMode(ReadMode.SLAVE) ;
+
+ serverConfig.setDatabase(this.database);
+ return Redisson.create(config);
+ }
+}
diff --git a/common/mall-spring-boot-starter-cache/src/main/java/cn/iocoder/mall/cache/config/SpringDataRedisConfig.java b/common/mall-spring-boot-starter-cache/src/main/java/cn/iocoder/mall/cache/config/SpringDataRedisConfig.java
new file mode 100644
index 000000000..690dc13d6
--- /dev/null
+++ b/common/mall-spring-boot-starter-cache/src/main/java/cn/iocoder/mall/cache/config/SpringDataRedisConfig.java
@@ -0,0 +1,165 @@
+package cn.iocoder.mall.cache.config;
+
+import com.fasterxml.jackson.annotation.JsonAutoDetect;
+import com.fasterxml.jackson.annotation.PropertyAccessor;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import org.redisson.Redisson;
+import org.redisson.api.RedissonClient;
+import org.redisson.config.Config;
+import org.redisson.config.ReadMode;
+import org.redisson.config.SentinelServersConfig;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.cache.CacheManager;
+import org.springframework.cache.annotation.CachingConfigurerSupport;
+import org.springframework.cache.annotation.EnableCaching;
+import org.springframework.cache.interceptor.KeyGenerator;
+import org.springframework.cache.interceptor.SimpleKeyGenerator;
+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.lettuce.LettuceConnectionFactory;
+import org.springframework.data.redis.core.RedisTemplate;
+import org.springframework.data.redis.core.StringRedisTemplate;
+import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
+import org.springframework.data.redis.serializer.RedisSerializationContext;
+import org.springframework.data.redis.serializer.RedisSerializer;
+import org.springframework.data.redis.serializer.StringRedisSerializer;
+import redis.clients.jedis.Jedis;
+
+import java.lang.reflect.Method;
+import java.time.Duration;
+import java.util.*;
+
+import static com.fasterxml.jackson.databind.DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES;
+
+@Configuration
+@EnableCaching
+public class SpringDataRedisConfig extends CachingConfigurerSupport {
+
+ @Value("${spring.redis.database}")
+ private int database;
+
+ @Value("${spring.redis.sentinel.master}")
+ private String master;
+
+ @Value("${spring.redis.sentinel.nodes}")
+ private String nodes;
+
+ private static RedisTemplate redisTemplate;
+
+ static {
+
+ }
+
+ public static String get(String key) {
+ redisTemplate.opsForValue().get(key);
+ return "";
+ }
+
+ public static boolean set(String key, String value) {
+ redisTemplate.opsForValue().set(key,value);
+ return false;
+ }
+
+ public static boolean set(String key, String value, int seconds) {
+ redisTemplate.opsForValue().set(key,value,seconds);
+ return false;
+ }
+
+
+ /**
+ * json序列化
+ * @return
+ */
+ @Bean
+ public RedisSerializer