diff --git a/pom.xml b/pom.xml index 0a55d0b..defd1f9 100644 --- a/pom.xml +++ b/pom.xml @@ -36,7 +36,6 @@ 1.1.0 3.1.0 3.12.5 - 4.0.2 2.12.1 2.17.2 3.0.3 @@ -119,12 +118,6 @@ redisson-spring-boot-starter ${redisson.version} - - - com.esotericsoftware - kryo - ${kryo.version} - org.apache.logging.log4j log4j-to-slf4j diff --git a/yami-shop-admin/src/main/resources/application-dev.yml b/yami-shop-admin/src/main/resources/application-dev.yml index 6378b93..aa3c093 100644 --- a/yami-shop-admin/src/main/resources/application-dev.yml +++ b/yami-shop-admin/src/main/resources/application-dev.yml @@ -18,12 +18,13 @@ spring: redis: cache-null-values: true redis: - redisson: - config: classpath:redisson/redisson.yml + host: 127.0.0.1 + port: 6379 + database: 0 logging: config: classpath:logback/logback-dev.xml xxl-job: accessToken: default_token logPath: /data/applogs/xxl-job/jobhandler admin: - addresses: http://localhost:8080/xxl-job-admin \ No newline at end of file + addresses: http://localhost:8080/xxl-job-admin diff --git a/yami-shop-admin/src/main/resources/application-docker.yml b/yami-shop-admin/src/main/resources/application-docker.yml index 78a6a00..cb4cb19 100644 --- a/yami-shop-admin/src/main/resources/application-docker.yml +++ b/yami-shop-admin/src/main/resources/application-docker.yml @@ -14,12 +14,13 @@ spring: auto-commit: true connection-test-query: SELECT 1 redis: - redisson: - config: classpath:redisson/redisson-docker.yml + host: ${REDIS_HOST} + port: ${REDIS_PORT} + database: ${REDIS_DATABASE:0} logging: config: classpath:logback/logback-prod.xml xxl-job: - accessToken: default_token - logPath: /data/applogs/xxl-job/jobhandler + accessToken: ${XXL_JOB_ACCESS_TOKEN:default_token} + logPath: ${XXL_JOB_LOG_PATH:/data/applogs/xxl-job/jobhandler} admin: - addresses: http://localhost:8080/xxl-job-admin \ No newline at end of file + addresses: ${XXL_JOB_ADDRESS:http://mall4j-job:8080/xxl-job-admin} \ No newline at end of file diff --git a/yami-shop-admin/src/main/resources/application-prod.yml b/yami-shop-admin/src/main/resources/application-prod.yml index bfa8e0b..5227fe3 100644 --- a/yami-shop-admin/src/main/resources/application-prod.yml +++ b/yami-shop-admin/src/main/resources/application-prod.yml @@ -14,8 +14,9 @@ spring: auto-commit: true connection-test-query: SELECT 1 redis: - redisson: - config: classpath:redisson/redisson.yml + host: 127.0.0.1 + port: 6379 + database: ${REDIS_DATABASE:0} logging: config: classpath:logback/logback-prod.xml xxl-job: diff --git a/yami-shop-admin/src/main/resources/redisson/redisson-docker.yml b/yami-shop-admin/src/main/resources/redisson/redisson-docker.yml deleted file mode 100644 index 46e08da..0000000 --- a/yami-shop-admin/src/main/resources/redisson/redisson-docker.yml +++ /dev/null @@ -1,28 +0,0 @@ -# 单节点设置 -singleServerConfig: - address: redis://${REDIS_HOST}:${REDIS_PORT} - database: ${REDIS_DATABASE} - password: ${REDIS_PASSWORD} - idleConnectionTimeout: 10000 - connectTimeout: 10000 - timeout: 3000 - retryAttempts: 3 - retryInterval: 1500 - clientName: null - # 发布和订阅连接的最小空闲连接数 默认1 - subscriptionConnectionMinimumIdleSize: 1 - # 发布和订阅连接池大小 默认50 - subscriptionConnectionPoolSize: 1 - # 单个连接最大订阅数量 默认5 - subscriptionsPerConnection: 1 - # 最小空闲连接数 默认32,现在暂时不需要那么多的线程 - connectionMinimumIdleSize: 2 - # connectionPoolSize 默认64,现在暂时不需要那么多的线程 - connectionPoolSize: 4 -# 这个线程池数量被所有RTopic对象监听器,RRemoteService调用者和RExecutorService任务共同共享。 -threads: 0 -# 这个线程池数量是在一个Redisson实例内,被其创建的所有分布式数据类型和服务,以及底层客户端所一同共享的线程池里保存的线程数量。 -nettyThreads: 0 -codec: - class: org.redisson.codec.KryoCodec -transportMode: NIO diff --git a/yami-shop-admin/src/main/resources/redisson/redisson.yml b/yami-shop-admin/src/main/resources/redisson/redisson.yml deleted file mode 100644 index 01883be..0000000 --- a/yami-shop-admin/src/main/resources/redisson/redisson.yml +++ /dev/null @@ -1,28 +0,0 @@ -# 单节点设置 -singleServerConfig: - address: redis://127.0.0.1:6379 - database: 0 - password: null - idleConnectionTimeout: 10000 - connectTimeout: 10000 - timeout: 3000 - retryAttempts: 3 - retryInterval: 1500 - clientName: null - # 发布和订阅连接的最小空闲连接数 默认1 - subscriptionConnectionMinimumIdleSize: 1 - # 发布和订阅连接池大小 默认50 - subscriptionConnectionPoolSize: 1 - # 单个连接最大订阅数量 默认5 - subscriptionsPerConnection: 1 - # 最小空闲连接数 默认32,现在暂时不需要那么多的线程 - connectionMinimumIdleSize: 2 - # connectionPoolSize 默认64,现在暂时不需要那么多的线程 - connectionPoolSize: 4 -# 这个线程池数量被所有RTopic对象监听器,RRemoteService调用者和RExecutorService任务共同共享。 -threads: 0 -# 这个线程池数量是在一个Redisson实例内,被其创建的所有分布式数据类型和服务,以及底层客户端所一同共享的线程池里保存的线程数量。 -nettyThreads: 0 -codec: - class: org.redisson.codec.KryoCodec -transportMode: NIO diff --git a/yami-shop-api/src/main/resources/application-dev.yml b/yami-shop-api/src/main/resources/application-dev.yml index de4328f..7c11224 100644 --- a/yami-shop-api/src/main/resources/application-dev.yml +++ b/yami-shop-api/src/main/resources/application-dev.yml @@ -13,8 +13,9 @@ spring: idle-timeout: 10000 connection-test-query: select 1 redis: - redisson: - config: classpath:redisson/redisson.yml + host: 127.0.0.1 + port: 6379 + database: 0 logging: config: classpath:logback/logback-dev.xml diff --git a/yami-shop-api/src/main/resources/application-docker.yml b/yami-shop-api/src/main/resources/application-docker.yml index a26ed59..f0b4092 100644 --- a/yami-shop-api/src/main/resources/application-docker.yml +++ b/yami-shop-api/src/main/resources/application-docker.yml @@ -13,7 +13,8 @@ spring: maximum-pool-size: 20 connection-test-query: select 1 redis: - redisson: - config: classpath:redisson/redisson-docker.yml + host: ${REDIS_HOST} + port: ${REDIS_PORT} + database: ${REDIS_DATABASE:0} logging: config: classpath:logback/logback-prod.xml diff --git a/yami-shop-api/src/main/resources/application-prod.yml b/yami-shop-api/src/main/resources/application-prod.yml index 09322d9..1071a33 100644 --- a/yami-shop-api/src/main/resources/application-prod.yml +++ b/yami-shop-api/src/main/resources/application-prod.yml @@ -1,7 +1,5 @@ server: port: 8112 - undertow: - worker-threads: 200 spring: datasource: @@ -15,7 +13,8 @@ spring: maximum-pool-size: 20 connection-test-query: select 1 redis: - redisson: - config: classpath:redisson/redisson.yml + host: 127.0.0.1 + port: 6379 + database: ${REDIS_DATABASE:0} logging: config: classpath:logback/logback-prod.xml diff --git a/yami-shop-api/src/main/resources/redisson/redisson-docker.yml b/yami-shop-api/src/main/resources/redisson/redisson-docker.yml deleted file mode 100644 index a79943a..0000000 --- a/yami-shop-api/src/main/resources/redisson/redisson-docker.yml +++ /dev/null @@ -1,28 +0,0 @@ -# 单节点设置 -singleServerConfig: - address: redis://${REDIS_HOST}:${REDIS_PORT} - database: ${REDIS_DATABASE} - password: ${REDIS_PASSWORD} - idleConnectionTimeout: 10000 - connectTimeout: 10000 - timeout: 3000 - retryAttempts: 3 - retryInterval: 1500 - clientName: null - # 发布和订阅连接的最小空闲连接数 默认1 - subscriptionConnectionMinimumIdleSize: 1 - # 发布和订阅连接池大小 默认50 - subscriptionConnectionPoolSize: 1 - # 单个连接最大订阅数量 默认5 - subscriptionsPerConnection: 1 - # 最小空闲连接数 默认32,现在暂时不需要那么多的线程 - connectionMinimumIdleSize: 4 - # connectionPoolSize 默认64,现在暂时不需要那么多的线程 - connectionPoolSize: 4 -# 这个线程池数量被所有RTopic对象监听器,RRemoteService调用者和RExecutorService任务共同共享。 -threads: 0 -# 这个线程池数量是在一个Redisson实例内,被其创建的所有分布式数据类型和服务,以及底层客户端所一同共享的线程池里保存的线程数量。 -nettyThreads: 0 -codec: - class: org.redisson.codec.KryoCodec -transportMode: NIO diff --git a/yami-shop-api/src/main/resources/redisson/redisson.yml b/yami-shop-api/src/main/resources/redisson/redisson.yml deleted file mode 100644 index 01883be..0000000 --- a/yami-shop-api/src/main/resources/redisson/redisson.yml +++ /dev/null @@ -1,28 +0,0 @@ -# 单节点设置 -singleServerConfig: - address: redis://127.0.0.1:6379 - database: 0 - password: null - idleConnectionTimeout: 10000 - connectTimeout: 10000 - timeout: 3000 - retryAttempts: 3 - retryInterval: 1500 - clientName: null - # 发布和订阅连接的最小空闲连接数 默认1 - subscriptionConnectionMinimumIdleSize: 1 - # 发布和订阅连接池大小 默认50 - subscriptionConnectionPoolSize: 1 - # 单个连接最大订阅数量 默认5 - subscriptionsPerConnection: 1 - # 最小空闲连接数 默认32,现在暂时不需要那么多的线程 - connectionMinimumIdleSize: 2 - # connectionPoolSize 默认64,现在暂时不需要那么多的线程 - connectionPoolSize: 4 -# 这个线程池数量被所有RTopic对象监听器,RRemoteService调用者和RExecutorService任务共同共享。 -threads: 0 -# 这个线程池数量是在一个Redisson实例内,被其创建的所有分布式数据类型和服务,以及底层客户端所一同共享的线程池里保存的线程数量。 -nettyThreads: 0 -codec: - class: org.redisson.codec.KryoCodec -transportMode: NIO diff --git a/yami-shop-common/pom.xml b/yami-shop-common/pom.xml index 9d7906c..cc9755e 100644 --- a/yami-shop-common/pom.xml +++ b/yami-shop-common/pom.xml @@ -73,10 +73,6 @@ com.vdurmont emoji-java - - com.esotericsoftware - kryo - com.github.binarywang weixin-java-pay diff --git a/yami-shop-common/src/main/java/com/yami/shop/common/config/RedisCacheConfig.java b/yami-shop-common/src/main/java/com/yami/shop/common/config/RedisCacheConfig.java index d600dc0..34c3df7 100644 --- a/yami-shop-common/src/main/java/com/yami/shop/common/config/RedisCacheConfig.java +++ b/yami-shop-common/src/main/java/com/yami/shop/common/config/RedisCacheConfig.java @@ -10,7 +10,14 @@ package com.yami.shop.common.config; -import com.yami.shop.common.serializer.redis.KryoRedisSerializer; +import com.fasterxml.jackson.annotation.JsonTypeInfo; +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.jsontype.impl.LaissezFaireSubTypeValidator; +import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; import org.springframework.cache.CacheManager; import org.springframework.cache.annotation.EnableCaching; import org.springframework.context.annotation.Bean; @@ -21,7 +28,9 @@ import org.springframework.data.redis.cache.RedisCacheWriter; import org.springframework.data.redis.connection.RedisConnectionFactory; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.data.redis.core.StringRedisTemplate; +import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer; import org.springframework.data.redis.serializer.RedisSerializationContext; +import org.springframework.data.redis.serializer.RedisSerializer; import org.springframework.data.redis.serializer.StringRedisSerializer; import java.time.Duration; @@ -37,53 +46,79 @@ import java.util.Map; public class RedisCacheConfig { @Bean - public CacheManager cacheManager(RedisConnectionFactory redisConnectionFactory) { + public CacheManager cacheManager(RedisConnectionFactory redisConnectionFactory, RedisSerializer redisSerializer) { - RedisCacheManager redisCacheManager = new RedisCacheManager( + RedisCacheManager redisCacheManager = new RedisCacheManager( RedisCacheWriter.nonLockingRedisCacheWriter(redisConnectionFactory), // 默认策略,未配置的 key 会使用这个 - this.getRedisCacheConfigurationWithTtl(3600), + this.getRedisCacheConfigurationWithTtl(3600,redisSerializer), // 指定 key 策略 - this.getRedisCacheConfigurationMap() - ); - redisCacheManager.setTransactionAware(true); + this.getRedisCacheConfigurationMap(redisSerializer) + ); + redisCacheManager.setTransactionAware(true); return redisCacheManager; } - private Map getRedisCacheConfigurationMap() { + private Map getRedisCacheConfigurationMap(RedisSerializer redisSerializer) { Map redisCacheConfigurationMap = new HashMap<>(16); -// redisCacheConfigurationMap.put("UserInfoList", this.getRedisCacheConfigurationWithTtl(3000)); -// redisCacheConfigurationMap.put("UserInfoListAnother", this.getRedisCacheConfigurationWithTtl(18000)); - + redisCacheConfigurationMap.put("product", this.getRedisCacheConfigurationWithTtl(1800, redisSerializer)); return redisCacheConfigurationMap; } - private RedisCacheConfiguration getRedisCacheConfigurationWithTtl(Integer seconds) { + private RedisCacheConfiguration getRedisCacheConfigurationWithTtl(Integer seconds,RedisSerializer redisSerializer) { + + RedisCacheConfiguration redisCacheConfiguration = RedisCacheConfiguration.defaultCacheConfig(); redisCacheConfiguration = redisCacheConfiguration.serializeValuesWith( RedisSerializationContext .SerializationPair - .fromSerializer(new KryoRedisSerializer<>()) + .fromSerializer(redisSerializer) ).entryTtl(Duration.ofSeconds(seconds)); return redisCacheConfiguration; } @Bean - public RedisTemplate redisTemplate(RedisConnectionFactory redisConnectionFactory) { - KryoRedisSerializer kryoRedisSerializer = new KryoRedisSerializer(); + public RedisTemplate redisTemplate(RedisConnectionFactory redisConnectionFactory,RedisSerializer redisSerializer) { + RedisTemplate redisTemplate = new RedisTemplate<>(); redisTemplate.setConnectionFactory(redisConnectionFactory); redisTemplate.setKeySerializer(new StringRedisSerializer()); redisTemplate.setHashKeySerializer(new StringRedisSerializer()); - redisTemplate.setValueSerializer(kryoRedisSerializer); - redisTemplate.setHashValueSerializer(kryoRedisSerializer); + redisTemplate.setValueSerializer(redisSerializer); + redisTemplate.setHashValueSerializer(redisSerializer); redisTemplate.setEnableTransactionSupport(false); redisTemplate.afterPropertiesSet(); return redisTemplate; } + /** + * 自定义redis序列化的机制,重新定义一个ObjectMapper.防止和MVC的冲突 + * https://juejin.im/post/5e869d426fb9a03c6148c97e + */ + @Bean + public RedisSerializer redisSerializer() { + ObjectMapper objectMapper = JsonMapper.builder().disable(MapperFeature.USE_ANNOTATIONS).build(); + // 反序列化时候遇到不匹配的属性并不抛出异常 + objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); + // 序列化时候遇到空对象不抛出异常 + objectMapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false); + // 反序列化的时候如果是无效子类型,不抛出异常 + objectMapper.configure(DeserializationFeature.FAIL_ON_INVALID_SUBTYPE, false); + // 不使用默认的dateTime进行序列化, + objectMapper.configure(SerializationFeature.WRITE_DATE_KEYS_AS_TIMESTAMPS, false); + // 使用JSR310提供的序列化类,里面包含了大量的JDK8时间序列化类 + objectMapper.registerModule(new JavaTimeModule()); + // 启用反序列化所需的类型信息,在属性中添加@class + objectMapper.activateDefaultTyping(LaissezFaireSubTypeValidator.instance, ObjectMapper.DefaultTyping.NON_FINAL, + JsonTypeInfo.As.PROPERTY); + // 配置null值的序列化器 + GenericJackson2JsonRedisSerializer.registerNullValueSerializer(objectMapper, null); + return new GenericJackson2JsonRedisSerializer(objectMapper); + } + + @Bean public StringRedisTemplate stringRedisTemplate(RedisConnectionFactory redisConnectionFactory){ StringRedisTemplate redisTemplate = new StringRedisTemplate(redisConnectionFactory); diff --git a/yami-shop-common/src/main/java/com/yami/shop/common/serializer/redis/KryoRedisSerializer.java b/yami-shop-common/src/main/java/com/yami/shop/common/serializer/redis/KryoRedisSerializer.java deleted file mode 100644 index d27ed3d..0000000 --- a/yami-shop-common/src/main/java/com/yami/shop/common/serializer/redis/KryoRedisSerializer.java +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Copyright (c) 2018-2999 广州市蓝海创新科技有限公司 All rights reserved. - * - * https://www.mall4j.com/ - * - * 未经允许,不可做商业用途! - * - * 版权所有,侵权必究! - */ -package com.yami.shop.common.serializer.redis; - -import com.esotericsoftware.kryo.Kryo; -import com.esotericsoftware.kryo.io.Input; -import com.esotericsoftware.kryo.io.Output; -import lombok.extern.slf4j.Slf4j; -import org.redisson.codec.KryoCodec; -import org.springframework.data.redis.serializer.RedisSerializer; -import org.springframework.data.redis.serializer.SerializationException; - -import java.io.ByteArrayOutputStream; -import java.util.Collections; - -/** - * 使用Kryo 进行reids的序列化 - * @author LGH - */ -@Slf4j -public class KryoRedisSerializer implements RedisSerializer { - - private final KryoCodec kryoPool; - - public KryoRedisSerializer() { - kryoPool = new KryoCodec(Collections.emptyList(), null); - } - - private static final byte[] EMPTY_BYTE_ARRAY = new byte[0]; - - - @Override - public byte[] serialize(T t) throws SerializationException { - if (t == null) { - return EMPTY_BYTE_ARRAY; - } - - Kryo kryo = kryoPool.get(); - - try (ByteArrayOutputStream baos = new ByteArrayOutputStream(); - Output output = new Output(baos)) { - kryo.writeClassAndObject(output, t); - output.flush(); - return baos.toByteArray(); - } catch (Exception e) { - log.error(e.getMessage(), e); - } - - return EMPTY_BYTE_ARRAY; - } - - @Override - @SuppressWarnings("unchecked") - public T deserialize(byte[] bytes) throws SerializationException { - if (bytes == null || bytes.length <= 0) { - return null; - } - Kryo kryo = kryoPool.get(); - - try (Input input = new Input(bytes)) { - return (T) kryo.readClassAndObject(input); - } catch (Exception e) { - log.error(e.getMessage(), e); - } - return null; - } -} diff --git a/yami-shop-security/yami-shop-security-common/src/main/java/com/yami/shop/security/common/manager/TokenStore.java b/yami-shop-security/yami-shop-security-common/src/main/java/com/yami/shop/security/common/manager/TokenStore.java index 1379e58..83fdab9 100644 --- a/yami-shop-security/yami-shop-security-common/src/main/java/com/yami/shop/security/common/manager/TokenStore.java +++ b/yami-shop-security/yami-shop-security-common/src/main/java/com/yami/shop/security/common/manager/TokenStore.java @@ -18,7 +18,6 @@ import cn.hutool.crypto.symmetric.AES; import com.yami.shop.common.constants.OauthCacheNames; import com.yami.shop.common.enums.YamiHttpStatus; import com.yami.shop.common.exception.YamiShopBindException; -import com.yami.shop.common.serializer.redis.KryoRedisSerializer; import com.yami.shop.common.util.PrincipalUtil; import com.yami.shop.security.common.bo.TokenInfoBO; import com.yami.shop.security.common.bo.UserInfoInTokenBO; @@ -30,6 +29,7 @@ import org.springframework.beans.factory.annotation.Value; import org.springframework.data.redis.core.RedisCallback; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.data.redis.core.StringRedisTemplate; +import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer; import org.springframework.data.redis.serializer.RedisSerializer; import org.springframework.stereotype.Component; @@ -62,12 +62,13 @@ public class TokenStore { private final StringRedisTemplate stringRedisTemplate; public TokenStore(RedisTemplate redisTemplate, - StringRedisTemplate stringRedisTemplate) { + StringRedisTemplate stringRedisTemplate, GenericJackson2JsonRedisSerializer genericJackson2JsonRedisSerializer) { this.redisTemplate = redisTemplate; - this.redisSerializer = new KryoRedisSerializer<>(); + this.redisSerializer = genericJackson2JsonRedisSerializer; this.stringRedisTemplate = stringRedisTemplate; } + /** * 将用户的部分信息存储在token中,并返回token信息 * @param userInfoInToken 用户在token中的信息