diff --git a/continew-starter-cache/continew-starter-cache-springcache/pom.xml b/continew-starter-cache/continew-starter-cache-springcache/pom.xml new file mode 100644 index 00000000..734f2b89 --- /dev/null +++ b/continew-starter-cache/continew-starter-cache-springcache/pom.xml @@ -0,0 +1,25 @@ + + + 4.0.0 + + top.charles7c.continew + continew-starter-cache + ${revision} + + + continew-starter-cache-springcache + jar + + ${project.artifactId} + ContiNew Starter 缓存模块 - Spring Cache + + + + + top.charles7c.continew + continew-starter-cache-redisson + + + \ No newline at end of file diff --git a/continew-starter-cache/continew-starter-cache-springcache/src/main/java/top/charles7c/continew/starter/cache/springcache/autoconfigure/SpringCacheAutoConfiguration.java b/continew-starter-cache/continew-starter-cache-springcache/src/main/java/top/charles7c/continew/starter/cache/springcache/autoconfigure/SpringCacheAutoConfiguration.java new file mode 100644 index 00000000..1f16507b --- /dev/null +++ b/continew-starter-cache/continew-starter-cache-springcache/src/main/java/top/charles7c/continew/starter/cache/springcache/autoconfigure/SpringCacheAutoConfiguration.java @@ -0,0 +1,104 @@ +/* + * Copyright (c) 2022-present Charles7c Authors. All Rights Reserved. + *

+ * Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0; + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + *

+ * http://www.gnu.org/licenses/lgpl.html + *

+ * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package top.charles7c.continew.starter.cache.springcache.autoconfigure; + +import cn.hutool.core.map.MapUtil; +import cn.hutool.core.util.StrUtil; +import cn.hutool.crypto.digest.DigestUtil; +import cn.hutool.json.JSONUtil; +import com.fasterxml.jackson.annotation.JsonTypeInfo; +import com.fasterxml.jackson.databind.ObjectMapper; +import jakarta.annotation.PostConstruct; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.boot.autoconfigure.AutoConfiguration; +import org.springframework.boot.autoconfigure.cache.CacheProperties; +import org.springframework.cache.annotation.CachingConfigurer; +import org.springframework.cache.interceptor.KeyGenerator; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.PropertySource; +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; +import top.charles7c.continew.starter.core.handler.GeneralPropertySourceFactory; + +import java.util.Map; + +/** + * Spring Cache 自动配置 + * + * @author Charles7c + * @since 1.2.0 + */ +@Slf4j +@AutoConfiguration +@RequiredArgsConstructor +@PropertySource(value = "classpath:default-cache-springcache.yml", factory = GeneralPropertySourceFactory.class) +public class SpringCacheAutoConfiguration implements CachingConfigurer { + + private final ObjectMapper objectMapper; + + /** + * Redis 缓存配置 + * + *

解决 Spring Cache(@Cacheable)Jackson 解析缓存乱码问题

+ */ + @Bean + public RedisCacheConfiguration redisCacheConfiguration(CacheProperties cacheProperties) { + ObjectMapper objectMapperCopy = objectMapper.copy(); + objectMapperCopy.activateDefaultTyping(objectMapperCopy + .getPolymorphicTypeValidator(), ObjectMapper.DefaultTyping.NON_FINAL, JsonTypeInfo.As.PROPERTY); + RedisCacheConfiguration redisCacheConfiguration = RedisCacheConfiguration.defaultCacheConfig() + .serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(new StringRedisSerializer())) + .serializeValuesWith(RedisSerializationContext.SerializationPair + .fromSerializer(new GenericJackson2JsonRedisSerializer(objectMapperCopy))); + CacheProperties.Redis redisCacheProperties = cacheProperties.getRedis(); + if (null != redisCacheProperties.getTimeToLive()) { + redisCacheConfiguration = redisCacheConfiguration.entryTtl(redisCacheProperties.getTimeToLive()); + } + if (!redisCacheProperties.isCacheNullValues()) { + redisCacheConfiguration = redisCacheConfiguration.disableCachingNullValues(); + } + return redisCacheConfiguration; + } + + /** + * 自定义缓存 key 生成策略 + * + *

+ * 如果 @Cacheable 不指定 key,则默认使用该策略 + *

+ */ + @Bean + @Override + public KeyGenerator keyGenerator() { + return (target, method, params) -> { + String key = StrUtil.toUnderlineCase(method.getName()).toUpperCase(); + Map paramMap = MapUtil.newHashMap(params.length); + for (int i = 0; i < params.length; i++) { + paramMap.put(String.valueOf(i), params[i]); + } + return String.format("%s:%s", key, DigestUtil.sha256Hex(JSONUtil.toJsonStr(paramMap))); + }; + } + + @PostConstruct + public void postConstruct() { + log.debug("[ContiNew Starter] - Auto Configuration 'Spring Cache' completed initialization."); + } +} diff --git a/continew-starter-cache/continew-starter-cache-springcache/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/continew-starter-cache/continew-starter-cache-springcache/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports new file mode 100644 index 00000000..5f3d0c7f --- /dev/null +++ b/continew-starter-cache/continew-starter-cache-springcache/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports @@ -0,0 +1 @@ +top.charles7c.continew.starter.cache.springcache.autoconfigure.SpringCacheAutoConfiguration \ No newline at end of file diff --git a/continew-starter-cache/continew-starter-cache-springcache/src/main/resources/default-cache-springcache.yml b/continew-starter-cache/continew-starter-cache-springcache/src/main/resources/default-cache-springcache.yml new file mode 100644 index 00000000..92705ee8 --- /dev/null +++ b/continew-starter-cache/continew-starter-cache-springcache/src/main/resources/default-cache-springcache.yml @@ -0,0 +1,7 @@ +--- ### Spring Cache 配置 +spring.cache: + redis: + # 缓存过期时长(单位:毫秒,默认 -1,表示永不过期) + time-to-live: 7200000 + # 是否允许缓存空值(默认 true,表示允许,可以解决缓存穿透问题) + cache-null-values: true \ No newline at end of file diff --git a/continew-starter-cache/pom.xml b/continew-starter-cache/pom.xml index 3585c03c..cf0103e8 100644 --- a/continew-starter-cache/pom.xml +++ b/continew-starter-cache/pom.xml @@ -17,6 +17,7 @@ continew-starter-cache-redisson + continew-starter-cache-springcache diff --git a/continew-starter-dependencies/pom.xml b/continew-starter-dependencies/pom.xml index be1e41ca..49f815cf 100644 --- a/continew-starter-dependencies/pom.xml +++ b/continew-starter-dependencies/pom.xml @@ -262,6 +262,13 @@ ${revision} + + + top.charles7c.continew + continew-starter-cache-springcache + ${revision} + + top.charles7c.continew