Skip to content

Commit 3fc8d9d

Browse files
committed
设置更完善的日志,抽离出redis工具类
1 parent 5d25445 commit 3fc8d9d

File tree

3 files changed

+90
-17
lines changed

3 files changed

+90
-17
lines changed

src/main/java/club/boyuan/official/config/RedisConfig.java

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,19 +21,22 @@ public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory redisC
2121

2222
// 使用StringRedisSerializer序列化和反序列化key值
2323
template.setKeySerializer(new StringRedisSerializer());
24+
template.setHashKeySerializer(new StringRedisSerializer());
2425

25-
// 配置ObjectMapper以支持Java 8时间类型和类型信息
26+
// 配置ObjectMapper以支持Java 8时间类型
2627
ObjectMapper objectMapper = new ObjectMapper();
2728
objectMapper.registerModule(new JavaTimeModule());
2829
objectMapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
2930

30-
// 修改默认的类型推断机制,避免GenericJackson2JsonRedisSerializer在处理单个对象时出现类型信息问题
31+
// 使用更安全的类型推断机制,只对非final类型启用类型信息
3132
objectMapper.activateDefaultTyping(
3233
objectMapper.getPolymorphicTypeValidator(),
33-
ObjectMapper.DefaultTyping.EVERYTHING);
34+
ObjectMapper.DefaultTyping.NON_FINAL);
3435

3536
// 使用GenericJackson2JsonRedisSerializer序列化和反序列化value值
36-
template.setValueSerializer(new GenericJackson2JsonRedisSerializer(objectMapper));
37+
GenericJackson2JsonRedisSerializer serializer = new GenericJackson2JsonRedisSerializer(objectMapper);
38+
template.setValueSerializer(serializer);
39+
template.setHashValueSerializer(serializer);
3740

3841
template.afterPropertiesSet();
3942
return template;

src/main/java/club/boyuan/official/controller/AdminController.java

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
import club.boyuan.official.exception.BusinessException;
88
import club.boyuan.official.exception.BusinessExceptionEnum;
99
import club.boyuan.official.service.IUserService;
10+
import club.boyuan.official.utils.RedisUtil;
1011
import lombok.AllArgsConstructor;
1112
import org.slf4j.Logger;
1213
import org.slf4j.LoggerFactory;
@@ -36,6 +37,8 @@ public class AdminController {
3637

3738
private final JwtTokenUtil jwtTokenUtil;
3839

40+
private final RedisUtil redisUtil;
41+
3942
private static final Logger logger = LoggerFactory.getLogger(AdminController.class);
4043

4144
private final HttpServletRequest request;
@@ -483,4 +486,49 @@ public ResponseEntity<ResponseMessage<?>> batchUpdateUserMembership(
483486
.body(ResponseMessage.error(500, "服务器内部错误: " + e.getMessage()));
484487
}
485488
}
489+
490+
/**
491+
* 清理Redis缓存接口
492+
* @param cacheRequest 缓存清理请求
493+
* @return 清理结果
494+
*/
495+
@PostMapping("/cache/clear")
496+
public ResponseEntity<ResponseMessage<?>> clearCache(
497+
@RequestBody(required = false) Map<String, String> cacheRequest) {
498+
try {
499+
checkAdminRole();
500+
501+
String cacheType = cacheRequest != null ? cacheRequest.get("type") : "field_definition";
502+
503+
switch (cacheType) {
504+
case "field_definition":
505+
redisUtil.clearFieldDefinitionCache();
506+
logger.info("管理员清理了字段定义缓存");
507+
return ResponseEntity.ok(ResponseMessage.success("字段定义缓存清理成功"));
508+
509+
case "all":
510+
redisUtil.clearAllCache();
511+
logger.info("管理员清理了所有缓存");
512+
return ResponseEntity.ok(ResponseMessage.success("所有缓存清理成功"));
513+
514+
default:
515+
if (cacheType.contains("*")) {
516+
redisUtil.clearCacheByPattern(cacheType);
517+
logger.info("管理员清理了模式 '{}' 的缓存", cacheType);
518+
return ResponseEntity.ok(ResponseMessage.success("模式缓存清理成功: " + cacheType));
519+
} else {
520+
return ResponseEntity.status(HttpStatus.BAD_REQUEST)
521+
.body(ResponseMessage.error(400, "不支持的缓存类型: " + cacheType));
522+
}
523+
}
524+
} catch (BusinessException e) {
525+
logger.warn("清理缓存失败: {}", e.getMessage());
526+
return ResponseEntity.status(HttpStatus.BAD_REQUEST)
527+
.body(ResponseMessage.error(e.getCode(), e.getMessage()));
528+
} catch (Exception e) {
529+
logger.error("清理缓存时发生服务器内部错误", e);
530+
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
531+
.body(ResponseMessage.error(500, "服务器内部错误: " + e.getMessage()));
532+
}
533+
}
486534
}

src/main/java/club/boyuan/official/service/impl/ResumeFieldDefinitionServiceImpl.java

Lines changed: 35 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -47,28 +47,50 @@ public ResumeFieldDefinition getFieldDefinitionById(Integer fieldId) {
4747
try {
4848
// 尝试从Redis缓存中获取数据
4949
String cacheKey = "field_definition:" + fieldId;
50-
Object cachedObject = redisTemplate.opsForValue().get(cacheKey);
50+
ResumeFieldDefinition cachedDefinition = null;
5151

52-
if (cachedObject != null) {
53-
// 检查缓存对象类型并进行适当转换
54-
if (cachedObject instanceof ResumeFieldDefinition) {
55-
logger.debug("从Redis缓存中获取到字段定义,字段ID: {}", fieldId);
56-
return (ResumeFieldDefinition) cachedObject;
57-
} else if (cachedObject instanceof Map) {
58-
// 如果是Map类型,尝试手动转换
59-
logger.debug("从Redis缓存中获取到字段定义Map,字段ID: {}", fieldId);
60-
// 由于复杂的类型转换可能出错,我们选择直接从数据库查询
61-
logger.debug("缓存中对象类型不匹配,将从数据库重新查询");
52+
try {
53+
Object cachedObject = redisTemplate.opsForValue().get(cacheKey);
54+
55+
if (cachedObject != null) {
56+
// 检查缓存对象类型并进行适当转换
57+
if (cachedObject instanceof ResumeFieldDefinition) {
58+
cachedDefinition = (ResumeFieldDefinition) cachedObject;
59+
logger.debug("从Redis缓存中获取到字段定义,字段ID: {}", fieldId);
60+
} else {
61+
// 如果类型不匹配,删除损坏的缓存数据
62+
logger.warn("缓存中对象类型不匹配,将清除损坏的缓存数据,字段ID: {}", fieldId);
63+
redisTemplate.delete(cacheKey);
64+
}
65+
}
66+
} catch (Exception redisException) {
67+
// Redis反序列化失败,记录警告并清除损坏的缓存
68+
logger.warn("从Redis获取数据失败,将清除损坏的缓存数据,字段ID: {}, 错误: {}",
69+
fieldId, redisException.getMessage());
70+
try {
71+
redisTemplate.delete(cacheKey);
72+
} catch (Exception deleteException) {
73+
logger.error("清除损坏缓存失败,字段ID: {}", fieldId, deleteException);
6274
}
6375
}
6476

77+
// 如果缓存命中,直接返回
78+
if (cachedDefinition != null) {
79+
return cachedDefinition;
80+
}
81+
6582
// 缓存未命中或类型不匹配,从数据库查询
6683
ResumeFieldDefinition definition = resumeFieldDefinitionMapper.findById(fieldId);
6784

6885
// 将查询结果存入Redis缓存,设置过期时间为1小时
6986
if (definition != null) {
70-
redisTemplate.opsForValue().set(cacheKey, definition, 1, TimeUnit.HOURS);
71-
logger.debug("将字段定义存入Redis缓存,字段ID: {},过期时间1小时", fieldId);
87+
try {
88+
redisTemplate.opsForValue().set(cacheKey, definition, 1, TimeUnit.HOURS);
89+
logger.debug("将字段定义存入Redis缓存,字段ID: {},过期时间1小时", fieldId);
90+
} catch (Exception cacheException) {
91+
// 缓存存储失败不影响主流程,只记录警告
92+
logger.warn("存储字段定义到Redis缓存失败,字段ID: {}", fieldId, cacheException);
93+
}
7294
}
7395

7496
return definition;

0 commit comments

Comments
 (0)