feat(cache): 添加 Caffeine缓存支持并优化日志处理

- 在应用配置中添加 Caffeine 缓存配置
- 新增 CaffeineConfig 类用于缓存管理
- 在 Log 实体中添加 userAgent 字段保存原始用户代理字符串
- 优化 LogAspect 中的用户代理解析逻辑,增加缓存支持
- 更新数据库表结构,在 log 表中添加 user_agent 列
This commit is contained in:
Theo
2025-02-10 10:21:39 +08:00
parent 8caf20a455
commit cb8a2c4f41
9 changed files with 97 additions and 6 deletions

View File

@@ -0,0 +1,37 @@
package com.youlai.boot.config;
import com.github.benmanes.caffeine.cache.Caffeine;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cache.CacheManager;
import org.springframework.cache.caffeine.CaffeineCacheManager;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* caffeine缓存配置
*
* @author Theo
* @since 2025-01-22 17:40:23
*/
@Slf4j
@Configuration
public class CaffeineConfig {
@Value("${spring.cache.caffeine.spec}")
private String caffeineSpec;
/**
* 缓存管理器
*
* @return CacheManager 缓存管理器
*/
@Bean
public CacheManager cacheManager() {
CaffeineCacheManager caffeineCacheManager = new CaffeineCacheManager();
Caffeine<Object, Object> caffeineBuilder = Caffeine.from(caffeineSpec);
caffeineCacheManager.setCaffeine(caffeineBuilder);
return caffeineCacheManager;
}
}

View File

@@ -3,9 +3,11 @@ package com.youlai.boot.core.aspect;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.date.TimeInterval;
import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.digest.DigestUtil;
import cn.hutool.http.useragent.UserAgent;
import cn.hutool.http.useragent.UserAgentUtil;
import cn.hutool.json.JSONUtil;
import com.alibaba.excel.util.StringUtils;
import com.aliyun.oss.HttpMethod;
import com.youlai.boot.common.enums.LogModuleEnum;
import com.youlai.boot.common.util.IPUtils;
@@ -21,6 +23,7 @@ import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.cache.CacheManager;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
@@ -37,14 +40,18 @@ import java.util.Objects;
* @author Ray.Hao
* @since 2024/6/25
*/
@Slf4j
@Aspect
@Component
@RequiredArgsConstructor
@Slf4j
public class LogAspect {
private final LogService logService;
private final HttpServletRequest request;
private final CacheManager cacheManager;
/**
* 切点
*/
@Pointcut("@annotation(com.youlai.boot.common.annotation.Log)")
public void logPointcut() {
}
@@ -72,7 +79,12 @@ public class LogAspect {
}
/**
* 保日志
* 保日志
*
* @param joinPoint 切点
* @param e 异常
* @param jsonResult 响应结果
* @param logAnnotation 日志注解
*/
private void saveLog(final JoinPoint joinPoint, final Exception e, Object jsonResult, com.youlai.boot.common.annotation.Log logAnnotation) {
String requestURI = request.getRequestURI();
@@ -120,8 +132,9 @@ public class LogAspect {
log.setExecutionTime(executionTime);
// 获取浏览器和终端系统信息
String userAgentString = request.getHeader("User-Agent");
UserAgent userAgent = UserAgentUtil.parse(userAgentString);
if(Objects.nonNull(userAgent)) {
log.setUserAgent(userAgentString);
UserAgent userAgent = resolveUserAgent(userAgentString);
if (Objects.nonNull(userAgent)) {
// 系统信息
log.setOs(userAgent.getOs().getName());
// 浏览器信息
@@ -193,4 +206,27 @@ public class LogAspect {
return obj instanceof MultipartFile || obj instanceof HttpServletRequest || obj instanceof HttpServletResponse;
}
/**
* 解析UserAgent
*
* @param userAgentString UserAgent字符串
* @return UserAgent
*/
public UserAgent resolveUserAgent(String userAgentString) {
if (StringUtils.isBlank(userAgentString)) {
return null;
}
// 给userAgentStringMD5加密一次防止过长
String userAgentStringMD5 = DigestUtil.md5Hex(userAgentString);
//判断是否命中缓存
UserAgent userAgent = Objects.requireNonNull(cacheManager.getCache("userAgent")).get(userAgentStringMD5, UserAgent.class);
if (userAgent != null) {
return userAgent;
}
userAgent = UserAgentUtil.parse(userAgentString);
Objects.requireNonNull(cacheManager.getCache("userAgent")).put(userAgentStringMD5, userAgent);
return userAgent;
}
}

View File

@@ -1,5 +1,6 @@
package com.youlai.boot.system.controller;
import cn.hutool.json.JSONUtil;
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.ExcelWriter;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
@@ -63,6 +64,7 @@ public class UserController {
@Valid UserPageQuery queryParams
) {
IPage<UserPageVO> result = userService.getUserPage(queryParams);
return PageResult.success(result);
}

View File

@@ -2,7 +2,6 @@ package com.youlai.boot.system.model.entity;
import com.baomidou.mybatisplus.annotation.*;
import com.youlai.boot.common.enums.LogModuleEnum;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.io.Serializable;
@@ -87,6 +86,11 @@ public class Log implements Serializable {
*/
private String os;
/**
* 原生的用户代理字符串
*/
private String userAgent;
/**
* 执行时间(毫秒)
*/