refactor(framework): 优化代码结构和类型安全

This commit is contained in:
2026-01-09 11:42:45 +08:00
parent 2ece7de4de
commit 42b9adc5bd
15 changed files with 152 additions and 204 deletions
@@ -13,12 +13,12 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package cn.odboy.framework.context;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import lombok.NonNull;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.DisposableBean;
@@ -28,7 +28,6 @@ import org.springframework.core.env.Environment;
import org.springframework.stereotype.Service;
@Slf4j
@SuppressWarnings({"unchecked", "all"})
public class KitSpringBeanHolder implements ApplicationContextAware, DisposableBean {
private static final List<CallBack> CALL_BACKS = new ArrayList<>();
@@ -136,7 +135,7 @@ public class KitSpringBeanHolder implements ApplicationContextAware, DisposableB
}
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
public void setApplicationContext(@NonNull ApplicationContext applicationContext) throws BeansException {
if (KitSpringBeanHolder.applicationContext != null) {
log.warn("SpringContextHolder中的ApplicationContext被覆盖, 原有ApplicationContext为:" +
KitSpringBeanHolder.applicationContext);
@@ -151,7 +150,7 @@ public class KitSpringBeanHolder implements ApplicationContextAware, DisposableB
KitSpringBeanHolder.addCallback = false;
}
interface CallBack {
public interface CallBack {
/**
* 回调执行方法
@@ -13,17 +13,14 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package cn.odboy.framework.mybatisplus.config;
import cn.odboy.framework.exception.BadRequestException;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;
/**
* @author /
*/
@Getter
@Slf4j
@SuppressWarnings({"unchecked", "all"})
public enum DataTypeEnum {
/**
* mysql
@@ -86,13 +83,13 @@ public enum DataTypeEnum {
*/
IMPALA("impala", "impala", "com.cloudera.impala.jdbc41.Driver", "", "", "'", "'");
private static final String JDBC_URL_PREFIX = "jdbc:";
private String feature;
private String desc;
private String driver;
private String keywordPrefix;
private String keywordSuffix;
private String aliasPrefix;
private String aliasSuffix;
private final String feature;
private final String desc;
private final String driver;
private final String keywordPrefix;
private final String keywordSuffix;
private final String aliasPrefix;
private final String aliasSuffix;
DataTypeEnum(String feature, String desc, String driver, String keywordPrefix, String keywordSuffix,
String aliasPrefix, String aliasSuffix) {
@@ -110,10 +107,7 @@ public enum DataTypeEnum {
for (DataTypeEnum dataTypeEnum : values()) {
if (url.startsWith(JDBC_URL_PREFIX + dataTypeEnum.feature)) {
try {
Class<?> aClass = Class.forName(dataTypeEnum.getDriver());
if (null == aClass) {
throw new BadRequestException("Unable to get driver instance for jdbcUrl: " + jdbcUrl);
}
Class.forName(dataTypeEnum.getDriver());
} catch (ClassNotFoundException e) {
throw new BadRequestException("Unable to get driver instance: " + jdbcUrl);
}
@@ -123,31 +117,4 @@ public enum DataTypeEnum {
return null;
}
public String getFeature() {
return feature;
}
public String getDesc() {
return desc;
}
public String getDriver() {
return driver;
}
public String getKeywordPrefix() {
return keywordPrefix;
}
public String getKeywordSuffix() {
return keywordSuffix;
}
public String getAliasPrefix() {
return aliasPrefix;
}
public String getAliasSuffix() {
return aliasSuffix;
}
}
@@ -36,7 +36,6 @@ import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
@SuppressWarnings({"unchecked", "all"})
@ConditionalOnWebApplication
@AutoConfigureAfter(DruidDataSourceAutoConfigure.class)
@ConditionalOnProperty(name = "spring.datasource.druid.stat-view-servlet.enabled", havingValue = "true",
@@ -50,7 +49,7 @@ public class RemoveDruidAdConfig {
* @return org.springframework.boot.web.servlet.FilterRegistrationBean
*/
@Bean
public FilterRegistrationBean removeDruidAdFilterRegistrationBean(DruidStatProperties properties) {
public FilterRegistrationBean<Filter> removeDruidAdFilterRegistrationBean(DruidStatProperties properties) {
// 获取web监控页面的参数
DruidStatProperties.StatViewServlet config = properties.getStatViewServlet();
@@ -89,7 +88,7 @@ public class RemoveDruidAdConfig {
public void destroy() {
}
};
FilterRegistrationBean registrationBean = new FilterRegistrationBean();
FilterRegistrationBean<Filter> registrationBean = new FilterRegistrationBean();
registrationBean.setFilter(filter);
registrationBean.addUrlPatterns(commonJsPattern);
return registrationBean;
@@ -13,7 +13,6 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package cn.odboy.framework.quartz.core;
import cn.odboy.framework.context.KitSpringBeanHolder;
@@ -45,13 +44,12 @@ public class QuartzRunnable implements Callable<Object> {
}
@Override
@SuppressWarnings({"unchecked", "all"})
public Object call() throws Exception {
ReflectionUtils.makeAccessible(method);
if (StringUtils.isNotBlank(params)) {
return method.invoke(target, params);
} else {
return method.invoke(target);
return method.invoke(target, "");
}
}
}
@@ -13,7 +13,6 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package cn.odboy.framework.redis;
import cn.hutool.core.util.ObjUtil;
@@ -29,13 +28,13 @@ import java.util.Objects;
import java.util.Optional;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.data.redis.connection.RedisConnection;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.ConvertingCursor;
import org.springframework.data.redis.core.Cursor;
import org.springframework.data.redis.core.RedisCallback;
import org.springframework.data.redis.core.RedisConnectionUtils;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ScanOptions;
@@ -43,12 +42,10 @@ import org.springframework.data.redis.serializer.StringRedisSerializer;
import org.springframework.stereotype.Component;
@Component
@SuppressWarnings({"unchecked", "all"})
public class KitRedisHelper {
private static final Logger log = LoggerFactory.getLogger(KitRedisHelper.class);
private RedisTemplate<Object, Object> redisTemplate;
private final RedisTemplate<Object, Object> redisTemplate;
public KitRedisHelper(RedisTemplate<Object, Object> redisTemplate) {
this.redisTemplate = redisTemplate;
@@ -99,7 +96,7 @@ public class KitRedisHelper {
* @param key 键 不能为null
* @return 时间(秒) 返回0代表为永久有效
*/
public long getExpire(Object key) {
public Long getExpire(Object key) {
return redisTemplate.getExpire(key, TimeUnit.SECONDS);
}
@@ -172,7 +169,7 @@ public class KitRedisHelper {
*/
public boolean hasKey(String key) {
try {
return redisTemplate.hasKey(key);
return Boolean.TRUE.equals(redisTemplate.hasKey(key));
} catch (Exception e) {
log.error(e.getMessage(), e);
return false;
@@ -182,27 +179,23 @@ public class KitRedisHelper {
/**
* 删除缓存
*
* @param key 可以传一个值 或多个
* @param keys 可以传一个值 或多个
*/
public void del(String... keys) {
if (keys != null && keys.length > 0) {
if (keys.length == 1) {
boolean result = redisTemplate.delete(keys[0]);
log.debug("--------------------------------------------");
log.debug(new StringBuilder("删除缓存:").append(keys[0]).append(", 结果:").append(result).toString());
log.debug("--------------------------------------------");
boolean result = Boolean.TRUE.equals(redisTemplate.delete(keys[0]));
log.debug("删除缓存:{}, 结果:{}", keys[0], result);
} else {
Set<Object> keySet = new HashSet<>();
for (String key : keys) {
if (redisTemplate.hasKey(key)) {
if (Boolean.TRUE.equals(redisTemplate.hasKey(key))) {
keySet.add(key);
}
}
long count = redisTemplate.delete(keySet);
log.debug("--------------------------------------------");
log.debug("成功删除缓存:" + keySet.toString());
log.debug("缓存删除数量:" + count + "个");
log.debug("--------------------------------------------");
Long count = redisTemplate.delete(keySet);
log.debug("成功删除缓存:{}", keySet);
log.debug("缓存删除数量:{}个", count);
}
}
}
@@ -210,19 +203,36 @@ public class KitRedisHelper {
/**
* 批量模糊删除key
*
* @param pattern
* @param pattern /
*/
public void scanDel(String pattern) {
ScanOptions options = ScanOptions.scanOptions().match(pattern).build();
try (Cursor<byte[]> cursor = redisTemplate.executeWithStickyConnection(
(RedisCallback<Cursor<byte[]>>) connection -> (Cursor<byte[]>) new ConvertingCursor<>(
connection.scan(options), redisTemplate.getKeySerializer()::deserialize))) {
while (cursor.hasNext()) {
redisTemplate.delete(cursor.next());
ScanOptions options = ScanOptions.scanOptions().match(pattern).count(100).build();
try (Cursor<byte[]> cursor = redisTemplate.executeWithStickyConnection(connection -> {
try {
return (Cursor<byte[]>) new ConvertingCursor<>(
connection.scan(options), redisTemplate.getKeySerializer()::deserialize);
} catch (Exception e) {
throw new RuntimeException("Redis scan operation failed", e);
}
})) {
List<Object> keysToDelete = new ArrayList<>();
while (cursor.hasNext()) {
Object key = cursor.next();
keysToDelete.add(key);
// 批量删除,避免一次性删除过多key
if (keysToDelete.size() >= 100) {
redisTemplate.delete(keysToDelete);
keysToDelete.clear();
}
}
// 删除剩余的key
if (!keysToDelete.isEmpty()) {
redisTemplate.delete(keysToDelete);
}
} catch (Exception e) {
throw new RuntimeException("Error during scan and delete operation", e);
}
}
// ============================String=============================
/**
@@ -246,7 +256,7 @@ public class KitRedisHelper {
if (value == null) {
return null;
}
// 如果 value 不是目标类型, 则尝试将其反序列化为 clazz 类型 by
// 如果 value 不是目标类型, 则尝试将其反序列化为 clazz 类型
if (!clazz.isInstance(value)) {
return JSON.parseObject(value.toString(), clazz);
} else if (clazz.isInstance(value)) {
@@ -268,10 +278,11 @@ public class KitRedisHelper {
if (value == null) {
return null;
}
if (value instanceof List<?> list) {
if (value instanceof List<?>) {
List<?> list = (List<?>) value;
// 检查每个元素是否为指定类型
if (list.stream().allMatch(clazz::isInstance)) {
return list.stream().map(clazz::cast).toList();
return list.stream().map(clazz::cast).collect(Collectors.toList());
}
}
return null;
@@ -302,8 +313,8 @@ public class KitRedisHelper {
* @return
*/
public List<Object> multiGet(List<String> keys) {
List list = redisTemplate.opsForValue().multiGet(Sets.newHashSet(keys));
List resultList = Lists.newArrayList();
List<Object> list = redisTemplate.opsForValue().multiGet(Sets.newHashSet(keys));
List<Object> resultList = Lists.newArrayList();
Optional.ofNullable(list)
.ifPresent(e -> list.forEach(ele -> Optional.ofNullable(ele).ifPresent(resultList::add)));
return resultList;
@@ -374,7 +385,6 @@ public class KitRedisHelper {
return false;
}
}
// ================================Map=================================
/**
@@ -520,7 +530,6 @@ public class KitRedisHelper {
public double hdecr(String key, String item, double by) {
return redisTemplate.opsForHash().increment(key, item, -by);
}
// ============================set=============================
/**
@@ -547,7 +556,7 @@ public class KitRedisHelper {
*/
public boolean sHasKey(String key, Object value) {
try {
return redisTemplate.opsForSet().isMember(key, value);
return Boolean.TRUE.equals(redisTemplate.opsForSet().isMember(key, value));
} catch (Exception e) {
log.error(e.getMessage(), e);
return false;
@@ -563,10 +572,11 @@ public class KitRedisHelper {
*/
public long sSet(String key, Object... values) {
try {
return redisTemplate.opsForSet().add(key, values);
Long add = redisTemplate.opsForSet().add(key, values);
return add == null ? 0L : add;
} catch (Exception e) {
log.error(e.getMessage(), e);
return 0;
return 0L;
}
}
@@ -584,7 +594,7 @@ public class KitRedisHelper {
if (time > 0) {
expire(key, time);
}
return count;
return count == null ? 0 : count;
} catch (Exception e) {
log.error(e.getMessage(), e);
return 0;
@@ -599,7 +609,8 @@ public class KitRedisHelper {
*/
public long sGetSetSize(String key) {
try {
return redisTemplate.opsForSet().size(key);
Long size = redisTemplate.opsForSet().size(key);
return size == null ? 0 : size;
} catch (Exception e) {
log.error(e.getMessage(), e);
return 0;
@@ -622,7 +633,6 @@ public class KitRedisHelper {
return 0;
}
}
// ===============================list=================================
/**
@@ -795,7 +805,6 @@ public class KitRedisHelper {
}
long count = redisTemplate.delete(keys);
}
// ============================incr=============================
/**
@@ -838,7 +847,7 @@ public class KitRedisHelper {
* @param unit 时间单位
* @return 如果设置成功返回true,否则返回false
*/
public Boolean setIfAbsent(String key, Object value, long timeout, TimeUnit unit) {
public boolean setIfAbsent(String key, Object value, long timeout, TimeUnit unit) {
try {
String stringValue = ObjUtil.toString(value);
// 使用Redis的SETNX命令实现原子性操作
@@ -13,6 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package cn.odboy.framework.redis;
import com.alibaba.fastjson2.JSON;
@@ -22,12 +23,12 @@ import java.nio.charset.StandardCharsets;
import java.time.Duration;
import java.util.HashMap;
import java.util.Map;
import lombok.NonNull;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.digest.MurmurHash3;
import org.springframework.boot.autoconfigure.AutoConfigureBefore;
import org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration;
import org.springframework.cache.Cache;
import org.springframework.cache.annotation.CachingConfigurerSupport;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.cache.interceptor.CacheErrorHandler;
import org.springframework.cache.interceptor.KeyGenerator;
@@ -47,19 +48,14 @@ import org.springframework.data.redis.serializer.StringRedisSerializer;
@Configuration
@EnableCaching
@AutoConfigureBefore(RedisAutoConfiguration.class)
public class RedisConfiguration extends CachingConfigurerSupport {
public class RedisConfiguration {
/**
* 自动识别json对象白名单配置(仅允许解析的包名, 范围越小越安全)<br/> 未配置可能导致, 登录失败, 反复登录等问题
*/
private static final String[] WHITELIST_STR =
{
"org.springframework",
"cn.odboy.system.dal.dataobject",
"cn.odboy.system.dal.model",
"cn.odboy.task.dal.dataobject",
"cn.odboy.task.dal.model",
};
{"org.springframework", "cn.odboy.system.dal.dataobject", "cn.odboy.system.dal.model",
"cn.odboy.task.dal.dataobject", "cn.odboy.task.dal.model",};
/**
* 设置 redis 数据默认过期时间,默认2小时 设置@cacheable 序列化方式
@@ -68,7 +64,9 @@ public class RedisConfiguration extends CachingConfigurerSupport {
public RedisCacheConfiguration redisCacheConfiguration() {
FastJsonRedisSerializer<Object> fastJsonRedisSerializer = new FastJsonRedisSerializer<>(Object.class);
RedisCacheConfiguration configuration = RedisCacheConfiguration.defaultCacheConfig();
configuration = configuration.serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(fastJsonRedisSerializer)).entryTtl(Duration.ofHours(2));
configuration = configuration.serializeValuesWith(
RedisSerializationContext.SerializationPair.fromSerializer(fastJsonRedisSerializer))
.entryTtl(Duration.ofHours(2));
return configuration;
}
@@ -106,8 +104,8 @@ public class RedisConfiguration extends CachingConfigurerSupport {
/**
* 自定义缓存key生成策略
*/
@Bean
@Override
public KeyGenerator keyGenerator() {
return (target, method, params) -> {
Map<String, Object> container = new HashMap<>(8);
@@ -130,29 +128,28 @@ public class RedisConfiguration extends CachingConfigurerSupport {
}
@Bean
@SuppressWarnings({"unchecked", "all"})
public CacheErrorHandler errorHandler() {
return new SimpleCacheErrorHandler() {
@Override
public void handleCacheGetError(RuntimeException exception, Cache cache, Object key) {
public void handleCacheGetError(@NonNull RuntimeException exception, @NonNull Cache cache, @NonNull Object key) {
// 处理缓存读取错误
log.error("Cache Get Error: {}", exception.getMessage());
}
@Override
public void handleCachePutError(RuntimeException exception, Cache cache, Object key, Object value) {
public void handleCachePutError(@NonNull RuntimeException exception, @NonNull Cache cache, @NonNull Object key, @NonNull Object value) {
// 处理缓存写入错误
log.error("Cache Put Error: {}", exception.getMessage());
}
@Override
public void handleCacheEvictError(RuntimeException exception, Cache cache, Object key) {
public void handleCacheEvictError(@NonNull RuntimeException exception, @NonNull Cache cache, @NonNull Object key) {
// 处理缓存删除错误
log.error("Cache Evict Error: {}", exception.getMessage());
}
@Override
public void handleCacheClearError(RuntimeException exception, Cache cache) {
public void handleCacheClearError(@NonNull RuntimeException exception, @NonNull Cache cache) {
// 处理缓存清除错误
log.error("Cache Clear Error: {}", exception.getMessage());
}
@@ -26,8 +26,7 @@ import lombok.experimental.UtilityClass;
@UtilityClass
public final class KitClassUtil {
@SuppressWarnings({"unchecked", "all"})
public static List<Field> getAllFields(Class clazz, List<Field> fields) {
public static List<Field> getAllFields(Class<?> clazz, List<Field> fields) {
if (clazz != null) {
fields.addAll(Arrays.asList(clazz.getDeclaredFields()));
getAllFields(clazz.getSuperclass(), fields);