mirror of
https://github.com/continew-org/continew-starter.git
synced 2025-09-08 16:57:09 +08:00
feat: 新增 Redisson 自动配置
This commit is contained in:
@@ -0,0 +1,25 @@
|
||||
<?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>top.charles7c.continew</groupId>
|
||||
<artifactId>continew-starter-cache</artifactId>
|
||||
<version>${revision}</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>continew-starter-cache-redisson</artifactId>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<name>${project.artifactId}</name>
|
||||
<description>ContiNew Starter 缓存 - Redisson 模块</description>
|
||||
|
||||
<dependencies>
|
||||
<!-- Redisson(不仅仅是一个 Redis Java 客户端) -->
|
||||
<dependency>
|
||||
<groupId>org.redisson</groupId>
|
||||
<artifactId>redisson-spring-boot-starter</artifactId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
@@ -0,0 +1,119 @@
|
||||
/*
|
||||
* Copyright (c) 2022-present Charles7c Authors. All Rights Reserved.
|
||||
* <p>
|
||||
* 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
|
||||
* <p>
|
||||
* http://www.gnu.org/licenses/lgpl.html
|
||||
* <p>
|
||||
* 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.redisson.autoconfigure;
|
||||
|
||||
import cn.hutool.core.bean.BeanUtil;
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.redisson.codec.JsonJacksonCodec;
|
||||
import org.redisson.config.ClusterServersConfig;
|
||||
import org.redisson.config.SentinelServersConfig;
|
||||
import org.redisson.config.SingleServerConfig;
|
||||
import org.redisson.spring.starter.RedissonAutoConfigurationCustomizer;
|
||||
import org.springframework.boot.autoconfigure.AutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||
import org.springframework.boot.autoconfigure.data.redis.RedisProperties;
|
||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import top.charles7c.continew.starter.core.constant.StringConsts;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Redisson 自动配置
|
||||
*
|
||||
* @author gengwei.zheng(<a href="https://gitee.com/herodotus/dante-engine">Dante Engine</a>)
|
||||
* @author Charles7c
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@Slf4j
|
||||
@AutoConfiguration
|
||||
@RequiredArgsConstructor
|
||||
@ConditionalOnProperty(prefix = "spring.data.redisson", name = "enabled", havingValue = "true")
|
||||
@EnableConfigurationProperties(RedissonProperties.class)
|
||||
public class RedissonAutoConfiguration {
|
||||
|
||||
private final RedissonProperties properties;
|
||||
private final RedisProperties redisProperties;
|
||||
private final ObjectMapper objectMapper;
|
||||
|
||||
@Bean
|
||||
public RedissonAutoConfigurationCustomizer redissonAutoConfigurationCustomizer() {
|
||||
return config -> {
|
||||
RedissonProperties.Mode mode = properties.getMode();
|
||||
String protocol = redisProperties.getSsl().isEnabled() ? "rediss://" : "redis://";
|
||||
switch (mode) {
|
||||
case CLUSTER -> {
|
||||
ClusterServersConfig clusterServersConfig = config.useClusterServers();
|
||||
ClusterServersConfig customClusterServersConfig = properties.getClusterServersConfig();
|
||||
if (null != customClusterServersConfig) {
|
||||
BeanUtil.copyProperties(customClusterServersConfig, clusterServersConfig);
|
||||
clusterServersConfig.setNodeAddresses(customClusterServersConfig.getNodeAddresses());
|
||||
}
|
||||
// 下方配置如果为空,则使用 Redis 的配置
|
||||
if (CollUtil.isEmpty(clusterServersConfig.getNodeAddresses())) {
|
||||
List<String> nodeList = redisProperties.getCluster().getNodes();
|
||||
nodeList.stream().map(node -> protocol + node).forEach(clusterServersConfig::addNodeAddress);
|
||||
}
|
||||
if (StrUtil.isBlank(clusterServersConfig.getPassword())) {
|
||||
clusterServersConfig.setPassword(redisProperties.getPassword());
|
||||
}
|
||||
}
|
||||
case SENTINEL -> {
|
||||
SentinelServersConfig sentinelServersConfig = config.useSentinelServers();
|
||||
SentinelServersConfig customSentinelServersConfig = properties.getSentinelServersConfig();
|
||||
if (null != customSentinelServersConfig) {
|
||||
BeanUtil.copyProperties(customSentinelServersConfig, sentinelServersConfig);
|
||||
sentinelServersConfig.setSentinelAddresses(customSentinelServersConfig.getSentinelAddresses());
|
||||
}
|
||||
// 下方配置如果为空,则使用 Redis 的配置
|
||||
if (CollUtil.isEmpty(sentinelServersConfig.getSentinelAddresses())) {
|
||||
List<String> nodeList = redisProperties.getSentinel().getNodes();
|
||||
nodeList.stream().map(node -> protocol + node).forEach(sentinelServersConfig::addSentinelAddress);
|
||||
}
|
||||
if (StrUtil.isBlank(sentinelServersConfig.getPassword())) {
|
||||
sentinelServersConfig.setPassword(redisProperties.getPassword());
|
||||
}
|
||||
if (StrUtil.isBlank(sentinelServersConfig.getMasterName())) {
|
||||
sentinelServersConfig.setMasterName(redisProperties.getSentinel().getMaster());
|
||||
}
|
||||
}
|
||||
default -> {
|
||||
SingleServerConfig singleServerConfig = config.useSingleServer();
|
||||
SingleServerConfig customSingleServerConfig = properties.getSingleServerConfig();
|
||||
if (null != customSingleServerConfig) {
|
||||
BeanUtil.copyProperties(properties.getSingleServerConfig(), singleServerConfig);
|
||||
}
|
||||
// 下方配置如果为空,则使用 Redis 的配置
|
||||
singleServerConfig.setDatabase(redisProperties.getDatabase());
|
||||
if (StrUtil.isBlank(singleServerConfig.getPassword())) {
|
||||
singleServerConfig.setPassword(redisProperties.getPassword());
|
||||
}
|
||||
if (StrUtil.isBlank(singleServerConfig.getAddress())) {
|
||||
singleServerConfig.setAddress(protocol + redisProperties.getHost() + StringConsts.COLON + redisProperties.getPort());
|
||||
}
|
||||
}
|
||||
}
|
||||
// Jackson 处理
|
||||
config.setCodec(new JsonJacksonCodec(objectMapper));
|
||||
log.info("[ContiNew Starter] - Auto Configuration 'Redisson' completed initialization.");
|
||||
};
|
||||
}
|
||||
}
|
@@ -0,0 +1,81 @@
|
||||
/*
|
||||
* Copyright (c) 2022-present Charles7c Authors. All Rights Reserved.
|
||||
* <p>
|
||||
* 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
|
||||
* <p>
|
||||
* http://www.gnu.org/licenses/lgpl.html
|
||||
* <p>
|
||||
* 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.redisson.autoconfigure;
|
||||
|
||||
import lombok.Data;
|
||||
import org.redisson.config.ClusterServersConfig;
|
||||
import org.redisson.config.SentinelServersConfig;
|
||||
import org.redisson.config.SingleServerConfig;
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
|
||||
|
||||
/**
|
||||
* Redisson 配置属性
|
||||
*
|
||||
* @author gengwei.zheng(<a href="https://gitee.com/herodotus/dante-engine">Dante Engine</a>)
|
||||
* @author Charles7c
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@Data
|
||||
@ConfigurationProperties(prefix = "spring.data.redisson")
|
||||
public class RedissonProperties {
|
||||
|
||||
/**
|
||||
* 是否启用 Redisson
|
||||
*/
|
||||
private boolean enabled = false;
|
||||
|
||||
/**
|
||||
* Redis 模式
|
||||
*/
|
||||
private Mode mode = Mode.SINGLE;
|
||||
|
||||
/**
|
||||
* 单机服务配置
|
||||
*/
|
||||
private SingleServerConfig singleServerConfig;
|
||||
|
||||
/**
|
||||
* 集群服务配置
|
||||
*/
|
||||
private ClusterServersConfig clusterServersConfig;
|
||||
|
||||
/**
|
||||
* 哨兵服务配置
|
||||
*/
|
||||
private SentinelServersConfig sentinelServersConfig;
|
||||
|
||||
/**
|
||||
* Redis 模式
|
||||
*/
|
||||
public enum Mode {
|
||||
/**
|
||||
* 单机
|
||||
*/
|
||||
SINGLE,
|
||||
|
||||
/**
|
||||
* 集群
|
||||
*/
|
||||
CLUSTER,
|
||||
|
||||
/**
|
||||
* 哨兵
|
||||
*/
|
||||
SENTINEL
|
||||
}
|
||||
}
|
@@ -0,0 +1,171 @@
|
||||
/*
|
||||
* Copyright (c) 2022-present Charles7c Authors. All Rights Reserved.
|
||||
* <p>
|
||||
* 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
|
||||
* <p>
|
||||
* http://www.gnu.org/licenses/lgpl.html
|
||||
* <p>
|
||||
* 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.redisson.util;
|
||||
|
||||
import cn.hutool.extra.spring.SpringUtil;
|
||||
import lombok.AccessLevel;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
import org.redisson.api.*;
|
||||
import org.redisson.config.Config;
|
||||
import top.charles7c.continew.starter.core.constant.StringConsts;
|
||||
|
||||
import java.time.Duration;
|
||||
import java.util.Collection;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
/**
|
||||
* Redis 工具类
|
||||
*
|
||||
* @author Charles7c
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@Data
|
||||
@NoArgsConstructor(access = AccessLevel.PRIVATE)
|
||||
public class RedisUtils {
|
||||
|
||||
private static final RedissonClient CLIENT = SpringUtil.getBean(RedissonClient.class);
|
||||
|
||||
/**
|
||||
* 设置缓存
|
||||
*
|
||||
* @param key 键
|
||||
* @param value 值
|
||||
*/
|
||||
public static <T> void set(final String key, final T value) {
|
||||
CLIENT.getBucket(key).set(value);
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置缓存
|
||||
*
|
||||
* @param key 键
|
||||
* @param value 值
|
||||
* @param duration 过期时间
|
||||
*/
|
||||
public static <T> void set(final String key, final T value, final Duration duration) {
|
||||
RBatch batch = CLIENT.createBatch();
|
||||
RBucketAsync<T> bucket = batch.getBucket(key);
|
||||
bucket.setAsync(value);
|
||||
bucket.expireAsync(duration);
|
||||
batch.execute();
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询指定缓存
|
||||
*
|
||||
* @param key 键
|
||||
* @return 值
|
||||
*/
|
||||
public static <T> T get(final String key) {
|
||||
RBucket<T> bucket = CLIENT.getBucket(key);
|
||||
return bucket.get();
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除缓存
|
||||
*
|
||||
* @param key 键
|
||||
* @return true 设置成功;false 设置失败
|
||||
*/
|
||||
public static boolean delete(final String key) {
|
||||
return CLIENT.getBucket(key).delete();
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置缓存过期时间
|
||||
*
|
||||
* @param key 键
|
||||
* @param timeout 过期时间(单位:秒)
|
||||
* @return true 设置成功;false 设置失败
|
||||
*/
|
||||
public static boolean expire(final String key, final long timeout) {
|
||||
return expire(key, Duration.ofSeconds(timeout));
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置缓存过期时间
|
||||
*
|
||||
* @param key 键
|
||||
* @param duration 过期时间
|
||||
* @return true 设置成功;false 设置失败
|
||||
*/
|
||||
public static boolean expire(final String key, final Duration duration) {
|
||||
return CLIENT.getBucket(key).expire(duration);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询缓存剩余过期时间
|
||||
*
|
||||
* @param key
|
||||
* 键
|
||||
* @return 缓存剩余过期时间(单位:毫秒)
|
||||
*/
|
||||
public static long getTimeToLive(final String key) {
|
||||
return CLIENT.getBucket(key).remainTimeToLive();
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否存在指定缓存
|
||||
*
|
||||
* @param key 键
|
||||
* @return true 存在;false 不存在
|
||||
*/
|
||||
public static boolean hasKey(String key) {
|
||||
RKeys keys = CLIENT.getKeys();
|
||||
return keys.countExists(getNameMapper().map(key)) > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询缓存列表
|
||||
*
|
||||
* @param keyPattern
|
||||
* 键表达式
|
||||
* @return 缓存列表
|
||||
*/
|
||||
public static Collection<String> keys(final String keyPattern) {
|
||||
Stream<String> stream = CLIENT.getKeys().getKeysStreamByPattern(getNameMapper().map(keyPattern));
|
||||
return stream.map(key -> getNameMapper().unmap(key)).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
/**
|
||||
* 格式化键,将各子键用 : 拼接起来
|
||||
*
|
||||
* @param subKeys 子键列表
|
||||
* @return 键
|
||||
*/
|
||||
public static String formatKey(String... subKeys) {
|
||||
return String.join(StringConsts.COLON, subKeys);
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据 Redisson 配置,获取名称映射器
|
||||
*
|
||||
* @return 名称映射器
|
||||
*/
|
||||
private static NameMapper getNameMapper() {
|
||||
Config config = CLIENT.getConfig();
|
||||
if (config.isClusterConfig()) {
|
||||
return config.useClusterServers().getNameMapper();
|
||||
}
|
||||
if (config.isSentinelConfig()) {
|
||||
return config.useSentinelServers().getNameMapper();
|
||||
}
|
||||
return config.useSingleServer().getNameMapper();
|
||||
}
|
||||
}
|
@@ -0,0 +1 @@
|
||||
top.charles7c.continew.starter.cache.redisson.autoconfigure.RedissonAutoConfiguration
|
29
continew-starter-cache/pom.xml
Normal file
29
continew-starter-cache/pom.xml
Normal file
@@ -0,0 +1,29 @@
|
||||
<?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>top.charles7c.continew</groupId>
|
||||
<artifactId>continew-starter</artifactId>
|
||||
<version>${revision}</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>continew-starter-cache</artifactId>
|
||||
<packaging>pom</packaging>
|
||||
|
||||
<name>${project.artifactId}</name>
|
||||
<description>ContiNew Starter 缓存模块</description>
|
||||
|
||||
<modules>
|
||||
<module>continew-starter-cache-redisson</module>
|
||||
</modules>
|
||||
|
||||
<dependencies>
|
||||
<!-- 核心模块 -->
|
||||
<dependency>
|
||||
<groupId>top.charles7c.continew</groupId>
|
||||
<artifactId>continew-starter-core</artifactId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
@@ -55,12 +55,20 @@
|
||||
|
||||
<properties>
|
||||
<revision>1.0.0-SNAPSHOT</revision>
|
||||
<redisson.version>3.24.3</redisson.version>
|
||||
<knife4j.version>4.3.0</knife4j.version>
|
||||
<hutool.version>5.8.23</hutool.version>
|
||||
</properties>
|
||||
|
||||
<dependencyManagement>
|
||||
<dependencies>
|
||||
<!-- Redisson(不仅仅是一个 Redis Java 客户端) -->
|
||||
<dependency>
|
||||
<groupId>org.redisson</groupId>
|
||||
<artifactId>redisson-spring-boot-starter</artifactId>
|
||||
<version>${redisson.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- Knife4j(前身是 swagger-bootstrap-ui,集 Swagger2 和 OpenAPI3 为一体的增强解决方案) -->
|
||||
<dependency>
|
||||
<groupId>com.github.xiaoymin</groupId>
|
||||
@@ -77,6 +85,13 @@
|
||||
<version>${hutool.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- 缓存 - Redisson 模块 -->
|
||||
<dependency>
|
||||
<groupId>top.charles7c.continew</groupId>
|
||||
<artifactId>continew-starter-cache-redisson</artifactId>
|
||||
<version>${revision}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- API 文档模块 -->
|
||||
<dependency>
|
||||
<groupId>top.charles7c.continew</groupId>
|
||||
|
@@ -14,4 +14,11 @@
|
||||
|
||||
<name>${project.artifactId}</name>
|
||||
<description>ContiNew Starter JSON - Jackson 模块</description>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>com.fasterxml.jackson.datatype</groupId>
|
||||
<artifactId>jackson-datatype-jsr310</artifactId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
@@ -17,7 +17,6 @@
|
||||
package top.charles7c.continew.starter.json.jackson.autoconfigure;
|
||||
|
||||
import cn.hutool.core.date.DatePattern;
|
||||
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
|
||||
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
|
||||
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateDeserializer;
|
||||
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer;
|
||||
@@ -31,7 +30,6 @@ import org.springframework.boot.autoconfigure.jackson.Jackson2ObjectMapperBuilde
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import top.charles7c.continew.starter.json.jackson.serializer.BigNumberSerializer;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.math.BigInteger;
|
||||
import java.time.LocalDate;
|
||||
import java.time.LocalDateTime;
|
||||
@@ -57,7 +55,6 @@ public class JacksonAutoConfiguration {
|
||||
javaTimeModule.addSerializer(Long.class, BigNumberSerializer.SERIALIZER_INSTANCE);
|
||||
javaTimeModule.addSerializer(Long.TYPE, BigNumberSerializer.SERIALIZER_INSTANCE);
|
||||
javaTimeModule.addSerializer(BigInteger.class, BigNumberSerializer.SERIALIZER_INSTANCE);
|
||||
javaTimeModule.addSerializer(BigDecimal.class, ToStringSerializer.instance);
|
||||
// 针对时间类型:LocalDateTime 的序列化和反序列化处理
|
||||
DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern(DatePattern.NORM_DATETIME_PATTERN);
|
||||
javaTimeModule.addSerializer(LocalDateTime.class, new LocalDateTimeSerializer(dateTimeFormatter));
|
||||
|
Reference in New Issue
Block a user