diff --git a/kkmall-mq/pom.xml b/kkmall-mq/pom.xml
new file mode 100644
index 0000000..b1aa3c5
--- /dev/null
+++ b/kkmall-mq/pom.xml
@@ -0,0 +1,110 @@
+
+
+ 4.0.0
+
+ org.springframework.boot
+ spring-boot-starter-parent
+ 2.5.2
+
+
+ name.lkk.kkmall
+ kkmall-mq
+ 0.0.1-SNAPSHOT
+ kkmall-mq
+ KK商城-MQ
+
+ 1.8
+ 2020.0.3
+
+
+
+
+ name.lkk.kkmall
+ kkmall-common
+ 0.0.1-SNAPSHOT
+
+
+
+ com.baomidou
+ mybatis-plus-boot-starter
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+
+ org.springframework.cloud
+ spring-cloud-starter-openfeign
+
+
+ org.springframework.cloud
+ spring-cloud-starter-loadbalancer
+
+
+
+ com.github.ben-manes.caffeine
+ caffeine
+
+
+ org.springframework.boot
+ spring-boot-starter-thymeleaf
+
+
+
+ org.springframework.boot
+ spring-boot-starter-data-redis
+
+
+
+ org.redisson
+ redisson
+ 3.12.5
+
+
+
+ org.springframework.boot
+ spring-boot-starter-cache
+
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-configuration-processor
+ true
+
+
+ org.springframework.boot
+ spring-boot-starter-test
+ test
+
+
+
+
+
+ org.springframework.cloud
+ spring-cloud-dependencies
+ ${spring-cloud.version}
+ pom
+ import
+
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+
+
+
+
diff --git a/kkmall-mq/src/main/java/name/lkk/kkmall/mq/KkmallMqApplication.java b/kkmall-mq/src/main/java/name/lkk/kkmall/mq/KkmallMqApplication.java
new file mode 100644
index 0000000..8074b14
--- /dev/null
+++ b/kkmall-mq/src/main/java/name/lkk/kkmall/mq/KkmallMqApplication.java
@@ -0,0 +1,17 @@
+package name.lkk.kkmall.mq;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
+import org.springframework.cloud.openfeign.EnableFeignClients;
+
+@SpringBootApplication
+@EnableDiscoveryClient
+@EnableFeignClients("name.lkk.kkmall.mq.feign")
+public class KkmallMqApplication {
+
+ public static void main(String[] args) {
+ SpringApplication.run(KkmallMqApplication.class, args);
+ }
+
+}
diff --git a/kkmall-mq/src/main/java/name/lkk/kkmall/mq/config/ListenerConfig.java b/kkmall-mq/src/main/java/name/lkk/kkmall/mq/config/ListenerConfig.java
new file mode 100644
index 0000000..b171dd9
--- /dev/null
+++ b/kkmall-mq/src/main/java/name/lkk/kkmall/mq/config/ListenerConfig.java
@@ -0,0 +1,56 @@
+package name.lkk.kkmall.mq.config;
+
+import name.lkk.kkmall.mq.service.ConsumerService;
+import org.springframework.beans.factory.annotation.Autowired;
+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.StringRedisTemplate;
+import org.springframework.data.redis.listener.PatternTopic;
+import org.springframework.data.redis.listener.RedisMessageListenerContainer;
+import org.springframework.data.redis.listener.adapter.MessageListenerAdapter;
+
+import java.util.concurrent.ThreadPoolExecutor;
+
+/**
+ * @Description redis消息队列的监听者
+ */
+@Configuration
+public class ListenerConfig {
+
+ @Autowired
+ ThreadPoolExecutor threadPoolExecutor;
+
+ @Bean
+ RedisMessageListenerContainer container(RedisConnectionFactory connectionFactory,
+ MessageListenerAdapter listenerAdapter) {
+ RedisMessageListenerContainer container = new RedisMessageListenerContainer();
+ container.setConnectionFactory(connectionFactory);
+ container.addMessageListener(listenerAdapter, new PatternTopic("lkk"));
+ container.setTaskExecutor(threadPoolExecutor);
+ return container;
+ }
+
+ /**
+ * 利用反射来创建监听到的消息之后执行方法
+ *
+ * @param consumerService
+ * @return
+ */
+ @Bean
+ MessageListenerAdapter listenerAdapter(ConsumerService consumerService) {
+ return new MessageListenerAdapter(consumerService, "receiveMessage");
+ }
+
+ /**
+ * 使用默认的工厂初始化redis操作模板
+ *
+ * @param connectionFactory
+ * @return
+ */
+ @Bean
+ StringRedisTemplate template(RedisConnectionFactory connectionFactory) {
+ return new StringRedisTemplate(connectionFactory);
+ }
+
+}
diff --git a/kkmall-mq/src/main/java/name/lkk/kkmall/mq/config/MallCacheConfig.java b/kkmall-mq/src/main/java/name/lkk/kkmall/mq/config/MallCacheConfig.java
new file mode 100644
index 0000000..674903d
--- /dev/null
+++ b/kkmall-mq/src/main/java/name/lkk/kkmall/mq/config/MallCacheConfig.java
@@ -0,0 +1,57 @@
+package name.lkk.kkmall.mq.config;
+
+import org.springframework.boot.autoconfigure.cache.CacheProperties;
+import org.springframework.boot.context.properties.EnableConfigurationProperties;
+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.serializer.GenericJackson2JsonRedisSerializer;
+import org.springframework.data.redis.serializer.RedisSerializationContext;
+import org.springframework.data.redis.serializer.StringRedisSerializer;
+
+/**
+ * @author: kirklin
+ * @date: 2021/6/24 3:32 下午
+ * @description:Spring Cache配置
+ */
+@Configuration
+@EnableCaching
+@EnableConfigurationProperties(CacheProperties.class)
+public class MallCacheConfig {
+ /**
+ * 配置文件中 TTL设置没用上
+ *
+ * 原来:
+ * @ConfigurationProperties(prefix = "spring.cache")
+ * public class CacheProperties
+ *
+ * 现在要让这个配置文件生效 : @EnableConfigurationProperties(CacheProperties.class)
+ *
+ */
+ @Bean
+ RedisCacheConfiguration redisCacheConfiguration(CacheProperties cacheProperties){
+
+ RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig();
+
+ // 设置kv的序列化机制
+ config = config.serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(new StringRedisSerializer()));
+ config = config.serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(new GenericJackson2JsonRedisSerializer()));
+ CacheProperties.Redis redisProperties = cacheProperties.getRedis();
+
+ // 设置配置
+ if(redisProperties.getTimeToLive() != null){
+ config = config.entryTtl(redisProperties.getTimeToLive());
+ }
+ if(redisProperties.getKeyPrefix() != null){
+ config = config.prefixCacheNameWith(redisProperties.getKeyPrefix());
+ }
+ if(!redisProperties.isCacheNullValues()){
+ config = config.disableCachingNullValues();
+ }
+ if(!redisProperties.isUseKeyPrefix()){
+ config = config.disableKeyPrefix();
+ }
+ return config;
+ }
+}
diff --git a/kkmall-mq/src/main/java/name/lkk/kkmall/mq/config/MallRedissonConfig.java b/kkmall-mq/src/main/java/name/lkk/kkmall/mq/config/MallRedissonConfig.java
new file mode 100644
index 0000000..eb80475
--- /dev/null
+++ b/kkmall-mq/src/main/java/name/lkk/kkmall/mq/config/MallRedissonConfig.java
@@ -0,0 +1,29 @@
+package name.lkk.kkmall.mq.config;
+
+import org.redisson.Redisson;
+import org.redisson.api.RedissonClient;
+import org.redisson.config.Config;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+/**
+ * @author: kirklin
+ * @date: 2021/6/23 8:43 下午
+ * @description:
+ */
+@Configuration
+public class MallRedissonConfig {
+
+ @Value("${spring.redis.host}")
+ private String redisHost;
+ @Value("${spring.redis.port}")
+ private String redisPort;
+
+ @Bean(destroyMethod = "shutdown")
+ public RedissonClient redisson() {
+ Config config = new Config();
+ config.useSingleServer().setAddress("redis://"+redisHost+":"+redisPort);
+ return Redisson.create(config);
+ }
+}
diff --git a/kkmall-mq/src/main/java/name/lkk/kkmall/mq/config/MyThreadConfig.java b/kkmall-mq/src/main/java/name/lkk/kkmall/mq/config/MyThreadConfig.java
new file mode 100644
index 0000000..fc780d5
--- /dev/null
+++ b/kkmall-mq/src/main/java/name/lkk/kkmall/mq/config/MyThreadConfig.java
@@ -0,0 +1,33 @@
+package name.lkk.kkmall.mq.config;
+
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+import java.util.concurrent.Executors;
+import java.util.concurrent.LinkedBlockingDeque;
+import java.util.concurrent.ThreadPoolExecutor;
+import java.util.concurrent.TimeUnit;
+
+@Configuration
+public class MyThreadConfig {
+
+ @Bean
+ public ThreadPoolExecutor threadPoolExecutor(ThreadPoolConfigProperties threadPoolConfigProperties){
+ /**
+ * 线程池创建的七个参数
+ * @param corePoolSize 线程池核心线程大小
+ * @param maximumPoolSize 线程最大线程数量
+ * @param keepAliveTime 空闲线程存活时间
+ * @param unit 空闲线程存活时间单位
+ * @param workQueue 工作队列
+ * @param threadFactory 线程工厂
+ * @param handler 拒绝策略
+ * CallerRunsPolicy 直接拒绝
+ * AbortPolicy 直接丢弃任务并抛异常
+ * DiscardPolicy 直接丢弃任务,并且什么都不做
+ * DiscardOldestPolicy 抛弃进入队列最早的任务,然后尝试把这次拒绝的任务放入队列
+ *
+ */
+ return new ThreadPoolExecutor(threadPoolConfigProperties.getCoreSize(), threadPoolConfigProperties.getMaxSize(), threadPoolConfigProperties.getKeepAliveTime() , TimeUnit.SECONDS, new LinkedBlockingDeque<>(10000), Executors.defaultThreadFactory(),new ThreadPoolExecutor.AbortPolicy());
+ }
+}
diff --git a/kkmall-mq/src/main/java/name/lkk/kkmall/mq/config/RedisConfiguration.java b/kkmall-mq/src/main/java/name/lkk/kkmall/mq/config/RedisConfiguration.java
new file mode 100644
index 0000000..7cf1781
--- /dev/null
+++ b/kkmall-mq/src/main/java/name/lkk/kkmall/mq/config/RedisConfiguration.java
@@ -0,0 +1,40 @@
+package name.lkk.kkmall.mq.config;
+
+import com.fasterxml.jackson.annotation.JsonAutoDetect;
+import com.fasterxml.jackson.annotation.PropertyAccessor;
+import com.fasterxml.jackson.databind.ObjectMapper;
+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.Jackson2JsonRedisSerializer;
+import org.springframework.data.redis.serializer.StringRedisSerializer;
+
+
+@Configuration
+public class RedisConfiguration {
+
+ @Bean
+ @SuppressWarnings("all")
+ public RedisTemplate redisTemplate(RedisConnectionFactory factory) {
+ RedisTemplate template = new RedisTemplate();
+ template.setConnectionFactory(factory);
+ Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
+ ObjectMapper om = new ObjectMapper();
+ om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
+ om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
+ jackson2JsonRedisSerializer.setObjectMapper(om);
+ StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();
+ // key采用String的序列化方式
+ template.setKeySerializer(stringRedisSerializer);
+ // hash的key也采用String的序列化方式
+ template.setHashKeySerializer(stringRedisSerializer);
+ // value序列化方式采用jackson
+ template.setValueSerializer(jackson2JsonRedisSerializer);
+ // hash的value序列化方式采用jackson
+ template.setHashValueSerializer(jackson2JsonRedisSerializer);
+ template.afterPropertiesSet();
+ return template;
+
+ }
+}
diff --git a/kkmall-mq/src/main/java/name/lkk/kkmall/mq/config/RedisUtil.java b/kkmall-mq/src/main/java/name/lkk/kkmall/mq/config/RedisUtil.java
new file mode 100644
index 0000000..8b1715b
--- /dev/null
+++ b/kkmall-mq/src/main/java/name/lkk/kkmall/mq/config/RedisUtil.java
@@ -0,0 +1,616 @@
+package name.lkk.kkmall.mq.config;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.data.redis.core.RedisTemplate;
+import org.springframework.stereotype.Component;
+import org.springframework.util.CollectionUtils;
+
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * @Description redis的工具类
+ */
+@Component
+public class RedisUtil {
+
+ @Autowired
+ private RedisTemplate redisTemplate;
+
+ /**
+ * 根据key 获取过期时间
+ *
+ * @param key 键 不能为null
+ * @return 时间(秒) 返回0代表为永久有效
+ */
+ public long getExpire(String key) {
+ return redisTemplate.getExpire(key, TimeUnit.SECONDS);
+ }
+
+ /**
+ * 判断key是否存在
+ *
+ * @param key 键
+ * @return true 存在 false不存在
+ */
+ public boolean hasKey(String key) {
+ try {
+ return redisTemplate.hasKey(key);
+ }
+ catch (Exception e) {
+ e.printStackTrace();
+ return false;
+ }
+ }
+
+ /**
+ * 删除缓存
+ *
+ * @param key 可以传一个值 或多个
+ */
+ @SuppressWarnings("unchecked")
+ public void del(String... key) {
+ if (key != null && key.length > 0) {
+ if (key.length == 1) {
+ redisTemplate.delete(key[0]);
+ } else {
+ redisTemplate.delete((Collection) CollectionUtils.arrayToList(key));
+ }
+ }
+ }
+ // ============================String=============================
+
+ /**
+ * 普通缓存获取
+ *
+ * @param key 键
+ * @return 值
+ */
+ public Object get(String key) {
+ return key == null ? null : redisTemplate.opsForValue().get(key);
+ }
+
+ /**
+ * 普通缓存放入
+ *
+ * @param key 键
+ * @param value 值
+ * @return true成功 false失败
+ */
+ public boolean set(String key, Object value) {
+ try {
+ redisTemplate.opsForValue().set(key, value);
+ return true;
+ }
+ catch (Exception e) {
+ e.printStackTrace();
+ return false;
+ }
+ }
+
+ /**
+ * 普通缓存放入并设置时间
+ *
+ * @param key 键
+ * @param value 值
+ * @param time 时间(秒) time要大于0 如果time小于等于0 将设置无限期
+ * @return true成功 false 失败
+ */
+ public boolean set(String key, Object value, long time) {
+ try {
+ if (time > 0) {
+ redisTemplate.opsForValue().set(key, value, time, TimeUnit.SECONDS);
+ } else {
+ set(key, value);
+ }
+ return true;
+ }
+ catch (Exception e) {
+ e.printStackTrace();
+ return false;
+ }
+ }
+
+ /**
+ * 递增
+ *
+ * @param key 键
+ * @param delta 要增加几(大于0)
+ * @return
+ */
+ public long incr(String key, long delta) {
+ if (delta < 0) {
+ throw new RuntimeException("递增因子必须大于0");
+ }
+ return redisTemplate.opsForValue().increment(key, delta);
+ }
+
+ /**
+ * 递减
+ *
+ * @param key 键
+ * @param delta 要减少几(小于0)
+ * @return
+ */
+ public long decr(String key, long delta) {
+ if (delta < 0) {
+ throw new RuntimeException("递减因子必须大于0");
+ }
+ return redisTemplate.opsForValue().increment(key, -delta);
+ }
+
+ /**
+ * HashGet
+ *
+ * @param key 键 不能为null
+ * @param item 项 不能为null
+ * @return 值
+ */
+ public Object hget(String key, String item) {
+ return redisTemplate.opsForHash().get(key, item);
+ }
+
+ /**
+ * 获取hashKey对应的所有键值
+ *
+ * @param key 键
+ * @return 对应的多个键值
+ */
+ public Map