From 8bd38f630280b76b40aa95564b6e6dfc0d873699 Mon Sep 17 00:00:00 2001
From: "Ray.Hao" <1490493387@qq.com>
Date: Tue, 21 Jan 2025 17:13:04 +0800
Subject: [PATCH 01/39] =?UTF-8?q?docs:=20=E6=96=87=E6=A1=A3=E5=90=8C?=
=?UTF-8?q?=E6=AD=A5=E9=A1=B9=E7=9B=AE=E6=9B=B4=E6=96=B0=E7=9A=84=E8=B0=83?=
=?UTF-8?q?=E6=95=B4?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
README.md | 74 +++++++++++++++++++++++++++----------------------------
1 file changed, 37 insertions(+), 37 deletions(-)
diff --git a/README.md b/README.md
index 58315170..01a6f061 100644
--- a/README.md
+++ b/README.md
@@ -20,13 +20,11 @@

## 📢 项目简介
-**在线预览**: [https://vue3.youlai.tech](https://vue3.youlai.tech)
-
基于 JDK 17、Spring Boot 3、Spring Security 6、JWT、Redis、Mybatis-Plus、Knife4j、Vue 3、Element-Plus 构建的前后端分离单体权限管理系统。
- **🚀 开发框架**: 使用 Spring Boot 3 和 Vue 3,以及 Element-Plus 等主流技术栈,实时更新。
@@ -37,7 +35,37 @@
- **🛠️ 功能模块**: 包括用户管理、角色管理、菜单管理、部门管理、字典管理等多个功能。
-- **📘 接口文档**: 自动生成接口文档,支持在线调试,提高开发效率。
+
+## 🌈 项目地址
+
+- **在线预览**:[https://vue.youlai.tech](https://vue.youlai.tech)
+- **前端项目**:[vue3-element-admin](https://gitee.com/youlaiorg/vue3-element-admin)
+- **接口文档**:[https://www.apifox.cn/apidoc](https://www.apifox.cn/apidoc/shared-195e783f-4d85-4235-a038-eec696de4ea5)
+- **项目文档**:[youlai-boot 企业级权限管理系统全功能详解](https://youlai.blog.csdn.net/article/details/145178880)
+- **从0到1文档**:[从0到1搭建 youlai-boot 企业级权限管理系统](https://youlai.blog.csdn.net/article/details/145177011)
+
+## 🚀 项目启动
+
+1. **克隆项目**
+
+ ```bash
+ git clone https://gitee.com/youlaiorg/youlai-boot.git
+ ```
+
+2. **数据库初始化**
+
+ 执行 [youlai_boot.sql](sql/mysql8/youlai_boot.sql) 脚本完成数据库创建、表结构和基础数据的初始化。
+
+3. **修改配置**
+
+ [application-dev.yml](src/main/resources/application-dev.yml) 修改MySQL、Redis连接配置;
+
+4. **启动项目**
+
+ 执行 [YoulaiBootApplication.java](src/main/java/com/youlai/boot/YoulaiBootApplication.java) 的 main 方法完成后端项目启动;
+
+ 访问接口文档地址 [http://localhost:8989/doc.html](http://localhost:8989/doc.html) 验证项目启动是否成功。
+
## 📁 项目目录
```
@@ -47,6 +75,7 @@ youlai-boot
│ └── mysql8 # MySQL8 脚本
├── src # 源码目录
│ ├── common # 公共模块
+│ │ ├── annotation # 注解定义
│ │ ├── base # 基础类
│ │ ├── constant # 常量
│ │ ├── enums # 枚举类型
@@ -71,7 +100,7 @@ youlai-boot
│ │ ├── WebSocketConfig # WebSocket 自动装配配置
│ │ └── XxlJobConfig # XXL-JOB 自动装配配置
│ ├── core # 核心功能
-│ │ ├── annotation # 注解定义
+
│ │ ├── aspect # 切面
│ │ │ ├── LogAspect # 日志切面
│ │ │ └── RepeatSubmitAspect # 防重提交切面
@@ -81,7 +110,7 @@ youlai-boot
│ │ ├── handler # 处理器
│ │ │ ├── MyDataPermissionHandler # 数据权限处理器
│ │ │ └── MyMetaObjectHandler # 元对象字段填充处理器
-│ │ └── security # Security 安全中心
+│ │ └── security # Spring Security 安全模块
│ ├── modules # 业务模块
│ │ ├── member # 会员模块【业务模块演示】
│ │ ├── order # 订单模块【业务模块演示】
@@ -112,35 +141,8 @@ youlai-boot
└── end
```
-## 🌺 前端工程
-| Gitee | Github |
-|-------|------|
-| [vue3-element-admin](https://gitee.com/youlaiorg/vue3-element-admin) | [vue3-element-admin](https://github.com/youlaitech/vue3-element-admin) |
-## 🌈 接口文档
-
-- `knife4j` 接口文档:[http://localhost:8989/doc.html](http://localhost:8989/doc.html)
-- `swagger` 接口文档:[http://localhost:8989/swagger-ui/index.html](http://localhost:8989/swagger-ui/index.html)
-- `apifox` 在线接口文档:[https://www.apifox.cn/apidoc](https://www.apifox.cn/apidoc/shared-195e783f-4d85-4235-a038-eec696de4ea5)
-
-
-## 🚀 项目启动
-
-1. **数据库初始化**
-
- 执行 [youlai_boot.sql](sql/mysql8/youlai_boot.sql) 脚本完成数据库创建、表结构和基础数据的初始化。
-
-2. **修改配置**
-
- [application-dev.yml](src/main/resources/application-dev.yml) 修改MySQL、Redis连接配置;
-
-3. **启动项目**
-
- 执行 [SystemApplication.java](src/main/java/com/youlai/boot/YouLaiApplication.java) 的 main 方法完成后端项目启动;
-
- 访问接口文档地址 [http://localhost:8989/doc.html](http://localhost:8989/doc.html) 验证项目启动是否成功。
-
## ✅ 项目统计

@@ -152,9 +154,7 @@ Thanks to all the contributors!
## 💖 加交流群
-> 关注公众号【有来技术】,获取交流群二维码,不想关注公众号或二维码过期欢迎加我微信(`haoxianrui`)备注【有来】即可,拉你进群。
-
-|  |
-|---------------------------------------------------------|
+> 关注公众号 有来技术 ,点击菜单 交流群 获取加群二维码。
+
From c2ab755cf3cb4dad966a25ec8ceddbc2706693dd Mon Sep 17 00:00:00 2001
From: "Ray.Hao" <1490493387@qq.com>
Date: Wed, 22 Jan 2025 11:56:58 +0800
Subject: [PATCH 02/39] =?UTF-8?q?refactor:=20MinIO=20=E4=B8=8A=E4=BC=A0?=
=?UTF-8?q?=E5=9B=BE=E7=89=87=E8=BF=94=E5=9B=9E=E5=90=8D=E7=A7=B0=E4=B8=8D?=
=?UTF-8?q?=E5=B8=A6=E6=96=87=E4=BB=B6=E5=A4=B9=E5=92=8C=E5=85=A8=E5=B1=80?=
=?UTF-8?q?=E5=BC=82=E5=B8=B8=E6=94=AF=E6=8C=81=E8=87=AA=E5=AE=9A=E4=B9=89?=
=?UTF-8?q?=E5=BC=82=E5=B8=B8=E4=BF=A1=E6=81=AF=E3=80=82?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../common/exception/BusinessException.java | 7 +++
.../exception/GlobalExceptionHandler.java | 8 +--
.../boot/common/result/IResultCode.java | 4 +-
.../youlai/boot/common/result/ResultCode.java | 16 ++---
.../boot/shared/file/model/FileInfo.java | 7 +++
.../file/service/impl/MinioFileService.java | 58 ++++++++++---------
6 files changed, 58 insertions(+), 42 deletions(-)
diff --git a/src/main/java/com/youlai/boot/common/exception/BusinessException.java b/src/main/java/com/youlai/boot/common/exception/BusinessException.java
index c74ae972..06467091 100644
--- a/src/main/java/com/youlai/boot/common/exception/BusinessException.java
+++ b/src/main/java/com/youlai/boot/common/exception/BusinessException.java
@@ -20,6 +20,13 @@ public class BusinessException extends RuntimeException {
this.resultCode = errorCode;
}
+
+ public BusinessException(IResultCode errorCode,String message) {
+ super(message);
+ this.resultCode = errorCode;
+ }
+
+
public BusinessException(String message, Throwable cause) {
super(message, cause);
}
diff --git a/src/main/java/com/youlai/boot/common/exception/GlobalExceptionHandler.java b/src/main/java/com/youlai/boot/common/exception/GlobalExceptionHandler.java
index 2021dbd9..cf7722a8 100644
--- a/src/main/java/com/youlai/boot/common/exception/GlobalExceptionHandler.java
+++ b/src/main/java/com/youlai/boot/common/exception/GlobalExceptionHandler.java
@@ -30,7 +30,6 @@ import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
-
/**
* 全局系统异常处理器
*
@@ -219,9 +218,9 @@ public class GlobalExceptionHandler {
@ExceptionHandler(BusinessException.class)
@ResponseStatus(HttpStatus.BAD_REQUEST)
public Result handleBizException(BusinessException e) {
- log.error("biz exception: {}", e.getMessage());
+ log.error("biz exception", e);
if (e.getResultCode() != null) {
- return Result.failed(e.getResultCode());
+ return Result.failed(e.getResultCode(), e.getMessage());
}
return Result.failed(e.getMessage());
}
@@ -239,8 +238,7 @@ public class GlobalExceptionHandler {
|| e instanceof AuthenticationException) {
throw e;
}
- log.error("unknown exception: {}", e.getMessage());
- e.printStackTrace();
+ log.error("unknown exception", e);
return Result.failed(e.getLocalizedMessage());
}
diff --git a/src/main/java/com/youlai/boot/common/result/IResultCode.java b/src/main/java/com/youlai/boot/common/result/IResultCode.java
index 479639e3..741d604a 100644
--- a/src/main/java/com/youlai/boot/common/result/IResultCode.java
+++ b/src/main/java/com/youlai/boot/common/result/IResultCode.java
@@ -3,8 +3,8 @@ package com.youlai.boot.common.result;
/**
* 响应码接口
*
- * @author Ray
- * @since 2022/2/18
+ * @author Ray.Hao
+ * @since 1.0.0
**/
public interface IResultCode {
diff --git a/src/main/java/com/youlai/boot/common/result/ResultCode.java b/src/main/java/com/youlai/boot/common/result/ResultCode.java
index 73ab7752..026927ef 100644
--- a/src/main/java/com/youlai/boot/common/result/ResultCode.java
+++ b/src/main/java/com/youlai/boot/common/result/ResultCode.java
@@ -42,7 +42,7 @@ public enum ResultCode implements IResultCode, Serializable {
VOICE_VERIFICATION_CODE_INPUT_ERROR("A0133", "语音校验码输入错误"),
USER_CERTIFICATE_EXCEPTION("A0140", "用户证件异常"),
- USER_CERTIFICATE_TYPE_NOT_SELECTED("A0141", "用户证��类型未选择"),
+ USER_CERTIFICATE_TYPE_NOT_SELECTED("A0141", "用户证件类型未选择"),
MAINLAND_ID_NUMBER_VERIFICATION_ILLEGAL("A0142", "大陆身份证编号校验非法"),
USER_BASIC_INFORMATION_VERIFICATION_FAILED("A0150", "用户基本信息校验失败"),
@@ -127,12 +127,14 @@ public enum ResultCode implements IResultCode, Serializable {
USER_RESOURCE_NOT_FOUND("A0606", "用户资源不存在"),
/** 二级宏观错误码 */
- USER_UPLOAD_FILE_EXCEPTION("A0700", "用户上传文件异常"),
- USER_UPLOAD_FILE_TYPE_MISMATCH("A0701", "用户上传文件类型不匹配"),
- USER_UPLOAD_FILE_TOO_LARGE("A0702", "用户上传文件太大"),
- USER_UPLOAD_IMAGE_TOO_LARGE("A0703", "用户上传图片太大"),
- USER_UPLOAD_VIDEO_TOO_LARGE("A0704", "用户上传视频太大"),
- USER_UPLOAD_COMPRESSED_FILE_TOO_LARGE("A0705", "用户上传压缩文件太大"),
+ UPLOAD_FILE_EXCEPTION("A0700", "上传文件异常"),
+ UPLOAD_FILE_TYPE_MISMATCH("A0701", "上传文件类型不匹配"),
+ UPLOAD_FILE_TOO_LARGE("A0702", "上传文件太大"),
+ UPLOAD_IMAGE_TOO_LARGE("A0703", "上传图片太大"),
+ UPLOAD_VIDEO_TOO_LARGE("A0704", "上传视频太大"),
+ UPLOAD_COMPRESSED_FILE_TOO_LARGE("A0705", "上传压缩文件太大"),
+
+ DELETE_FILE_EXCEPTION("A0710", "删除文件异常"),
/** 二级宏观错误码 */
USER_CURRENT_VERSION_EXCEPTION("A0800", "用户当前版本异常"),
diff --git a/src/main/java/com/youlai/boot/shared/file/model/FileInfo.java b/src/main/java/com/youlai/boot/shared/file/model/FileInfo.java
index f1251dc4..ec550a18 100644
--- a/src/main/java/com/youlai/boot/shared/file/model/FileInfo.java
+++ b/src/main/java/com/youlai/boot/shared/file/model/FileInfo.java
@@ -3,6 +3,13 @@ package com.youlai.boot.shared.file.model;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
+
+/**
+ * 文件信息对象
+ *
+ * @author Ray.Hao
+ * @since 1.0.0
+ */
@Schema(description = "文件对象")
@Data
public class FileInfo {
diff --git a/src/main/java/com/youlai/boot/shared/file/service/impl/MinioFileService.java b/src/main/java/com/youlai/boot/shared/file/service/impl/MinioFileService.java
index db5fce55..59c7e576 100644
--- a/src/main/java/com/youlai/boot/shared/file/service/impl/MinioFileService.java
+++ b/src/main/java/com/youlai/boot/shared/file/service/impl/MinioFileService.java
@@ -5,30 +5,30 @@ import cn.hutool.core.io.FileUtil;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.StrUtil;
+import com.youlai.boot.common.exception.BusinessException;
+import com.youlai.boot.common.result.ResultCode;
import com.youlai.boot.shared.file.service.FileService;
import com.youlai.boot.shared.file.model.FileInfo;
import io.minio.*;
-import io.minio.errors.*;
import io.minio.http.Method;
import jakarta.annotation.PostConstruct;
import lombok.Data;
import lombok.RequiredArgsConstructor;
import lombok.SneakyThrows;
+import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;
-import java.io.IOException;
+import java.io.File;
import java.io.InputStream;
-import java.security.InvalidKeyException;
-import java.security.NoSuchAlgorithmException;
import java.time.LocalDateTime;
/**
* MinIO 文件上传服务类
*
- * @author haoxr
+ * @author Ray.Hao
* @since 2023/6/2
*/
@Component
@@ -36,6 +36,7 @@ import java.time.LocalDateTime;
@ConfigurationProperties(prefix = "oss.minio")
@RequiredArgsConstructor
@Data
+@Slf4j
public class MinioFileService implements FileService {
/**
@@ -77,7 +78,7 @@ public class MinioFileService implements FileService {
* 上传文件
*
* @param file 表单文件对象
- * @return
+ * @return 文件信息
*/
@Override
public FileInfo uploadFile(MultipartFile file) {
@@ -85,16 +86,19 @@ public class MinioFileService implements FileService {
// 创建存储桶(存储桶不存在),如果有搭建好的minio服务,建议放在init方法中
createBucketIfAbsent(bucketName);
- // 生成文件名(日期文件夹)
+ // 文件后缀
String suffix = FileUtil.getSuffix(file.getOriginalFilename());
- String uuid = IdUtil.simpleUUID();
- String fileName = DateUtil.format(LocalDateTime.now(), "yyyyMMdd") + "/" + uuid + "." + suffix;
+ // 文件夹名称
+ String dateFolder = DateUtil.format(LocalDateTime.now(), "yyyyMMdd");
+ // 文件名称
+ String fileName = IdUtil.simpleUUID() + "." + suffix;
+
// try-with-resource 语法糖自动释放流
try (InputStream inputStream = file.getInputStream()) {
// 文件上传
PutObjectArgs putObjectArgs = PutObjectArgs.builder()
.bucket(bucketName)
- .object(fileName)
+ .object(dateFolder + "/"+ fileName)
.contentType(file.getContentType())
.stream(inputStream, inputStream.available(), -1)
.build();
@@ -104,15 +108,18 @@ public class MinioFileService implements FileService {
String fileUrl;
// 未配置自定义域名
if (StrUtil.isBlank(customDomain)) {
+ // 获取文件URL
GetPresignedObjectUrlArgs getPresignedObjectUrlArgs = GetPresignedObjectUrlArgs.builder()
- .bucket(bucketName).object(fileName)
+ .bucket(bucketName)
+ .object(dateFolder + "/"+ fileName)
.method(Method.GET)
.build();
fileUrl = minioClient.getPresignedObjectUrl(getPresignedObjectUrlArgs);
fileUrl = fileUrl.substring(0, fileUrl.indexOf("?"));
- } else { // 配置自定义文件路径域名
- fileUrl = customDomain + '/' + bucketName + "/" + fileName;
+ } else {
+ // 配置自定义文件路径域名
+ fileUrl = customDomain + "/"+ bucketName + "/"+ dateFolder + "/"+ fileName;
}
FileInfo fileInfo = new FileInfo();
@@ -120,7 +127,8 @@ public class MinioFileService implements FileService {
fileInfo.setUrl(fileUrl);
return fileInfo;
} catch (Exception e) {
- throw new RuntimeException("文件上传失败");
+ log.error("上传文件失败", e);
+ throw new BusinessException(ResultCode.UPLOAD_FILE_EXCEPTION, e.getMessage());
}
}
@@ -128,9 +136,8 @@ public class MinioFileService implements FileService {
/**
* 删除文件
*
- * @param filePath 文件路径 http://localhost:9000/default/20221120/test.jpg
- *
- * @return
+ * @param filePath 文件完整路径
+ * @return 是否删除成功
*/
@Override
public boolean deleteFile(String filePath) {
@@ -152,7 +159,8 @@ public class MinioFileService implements FileService {
minioClient.removeObject(removeObjectArgs);
return true;
} catch (Exception e) {
- throw new RuntimeException("文件删除失败", e);
+ log.error("删除文件失败", e);
+ throw new BusinessException(ResultCode.DELETE_FILE_EXCEPTION, e.getMessage());
}
}
@@ -161,17 +169,11 @@ public class MinioFileService implements FileService {
* PUBLIC桶策略
* 如果不配置,则新建的存储桶默认是PRIVATE,则存储桶文件会拒绝访问 Access Denied
*
- * @param bucketName
- * @return
+ * @param bucketName 存储桶名称
+ * @return 存储桶策略
*/
private static String publicBucketPolicy(String bucketName) {
- /**
- * AWS的S3存储桶策略
- * Principal: 生效用户对象
- * Resource: 指定存储桶
- * Action: 操作行为
- */
-
+ // AWS的S3存储桶策略 JSON 格式 https://docs.aws.amazon.com/zh_cn/AmazonS3/latest/userguide/example-bucket-policies.html
return "{\"Version\":\"2012-10-17\","
+ "\"Statement\":[{\"Effect\":\"Allow\","
+ "\"Principal\":{\"AWS\":[\"*\"]},"
@@ -185,7 +187,7 @@ public class MinioFileService implements FileService {
/**
* 创建存储桶(存储桶不存在)
*
- * @param bucketName
+ * @param bucketName 存储桶名称
*/
@SneakyThrows
private void createBucketIfAbsent(String bucketName) {
From f1f30712f7c1e21ff659aa8ee570e16c7b404362 Mon Sep 17 00:00:00 2001
From: Theo <971366405@qq.com>
Date: Wed, 22 Jan 2025 16:14:43 +0800
Subject: [PATCH 03/39] =?UTF-8?q?feat(shared):=20=E4=BC=98=E5=8C=96?=
=?UTF-8?q?=E6=9C=AC=E5=9C=B0=E6=96=87=E4=BB=B6=E6=9C=8D=E5=8A=A1=E5=AE=9E?=
=?UTF-8?q?=E7=8E=B0?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
- 添加文件上传和删除方法的代码注释
- 使用 Hutool 的 DatePattern 优化日期格式化
- 修复文件路径分隔符问题,提高代码兼容性
---
.../file/service/impl/LocalFileService.java | 27 ++++++++++++++-----
1 file changed, 21 insertions(+), 6 deletions(-)
diff --git a/src/main/java/com/youlai/boot/shared/file/service/impl/LocalFileService.java b/src/main/java/com/youlai/boot/shared/file/service/impl/LocalFileService.java
index f6a217e4..46740dc4 100644
--- a/src/main/java/com/youlai/boot/shared/file/service/impl/LocalFileService.java
+++ b/src/main/java/com/youlai/boot/shared/file/service/impl/LocalFileService.java
@@ -1,5 +1,6 @@
package com.youlai.boot.shared.file.service.impl;
+import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.IdUtil;
@@ -7,6 +8,7 @@ import com.youlai.boot.shared.file.model.FileInfo;
import com.youlai.boot.shared.file.service.FileService;
import lombok.Data;
import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.ConfigurationProperties;
@@ -23,40 +25,53 @@ import java.time.LocalDateTime;
* @author Theo
* @since 2024-12-09 17:11
*/
+@Data
+@Slf4j
@Component
@ConditionalOnProperty(value = "oss.type", havingValue = "local")
@ConfigurationProperties(prefix = "oss.local")
@RequiredArgsConstructor
-@Data
public class LocalFileService implements FileService {
@Value("${oss.local.storage-path}")
private String storagePath;
+ /**
+ * 上传文件方法
+ *
+ * @param file 表单文件对象
+ * @return 文件信息
+ */
@Override
public FileInfo uploadFile(MultipartFile file) {
// 生成文件名(日期文件夹)
String suffix = FileUtil.getSuffix(file.getOriginalFilename());
String uuid = IdUtil.simpleUUID();
- String folder = DateUtil.format(LocalDateTime.now(), "yyyyMMdd") + File.separator;
- String fileName = uuid + "." + suffix;
+ String folder = DateUtil.format(LocalDateTime.now(), DatePattern.PURE_DATE_PATTERN);
+ String fileName = uuid + "." + suffix;
String filePrefix = storagePath.endsWith(File.separator) ? storagePath : storagePath + File.separator;
// try-with-resource 语法糖自动释放流
try (InputStream inputStream = file.getInputStream()) {
// 上传文件
- FileUtil.writeFromStream(inputStream, filePrefix +folder+ fileName);
+ FileUtil.writeFromStream(inputStream, filePrefix + folder + File.separator + fileName);
} catch (Exception e) {
- e.printStackTrace();
+ log.error("文件上传失败", e);
throw new RuntimeException("文件上传失败");
}
// 获取文件访问路径,因为这里是本地存储,所以直接返回文件的相对路径,需要前端自行处理访问前缀
- String fileUrl = File.separator +folder+File.separator + fileName;
+ String fileUrl = File.separator + folder + File.separator + fileName;
FileInfo fileInfo = new FileInfo();
fileInfo.setName(fileName);
fileInfo.setUrl(fileUrl);
return fileInfo;
}
+
+ /**
+ * 删除文件
+ * @param filePath 文件完整URL
+ * @return 是否删除成功
+ */
@Override
public boolean deleteFile(String filePath) {
//判断文件是否为空
From 8936f61f43b31a8df6c93336367ce2964a5e6da8 Mon Sep 17 00:00:00 2001
From: Theo <971366405@qq.com>
Date: Wed, 22 Jan 2025 16:25:13 +0800
Subject: [PATCH 04/39] =?UTF-8?q?feat(User):=20=E6=B7=BB=E5=8A=A0=E7=94=A8?=
=?UTF-8?q?=E6=88=B7=E9=82=AE=E7=AE=B1=E5=AD=97=E6=AE=B5-=20=E5=9C=A8=20Us?=
=?UTF-8?q?erMapper.xml=20=E6=96=87=E4=BB=B6=E4=B8=AD=E6=B7=BB=E5=8A=A0?=
=?UTF-8?q?=E4=BA=86=E7=94=A8=E6=88=B7=E9=82=AE=E7=AE=B1=E5=AD=97=E6=AE=B5?=
=?UTF-8?q?=20-=20=E5=9C=A8=E6=9F=A5=E8=AF=A2=E7=94=A8=E6=88=B7=E4=BF=A1?=
=?UTF-8?q?=E6=81=AF=E7=9A=84=E7=9B=B8=E5=85=B3=20SQL=20=E8=AF=AD=E5=8F=A5?=
=?UTF-8?q?=E4=B8=AD=E5=8C=85=E5=90=AB=E4=BA=86=E9=82=AE=E7=AE=B1=E5=AD=97?=
=?UTF-8?q?=E6=AE=B5?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
src/main/resources/mapper/system/UserMapper.xml | 3 +++
1 file changed, 3 insertions(+)
diff --git a/src/main/resources/mapper/system/UserMapper.xml b/src/main/resources/mapper/system/UserMapper.xml
index 88e103af..1cfc5907 100644
--- a/src/main/resources/mapper/system/UserMapper.xml
+++ b/src/main/resources/mapper/system/UserMapper.xml
@@ -14,6 +14,7 @@
u.gender,
u.avatar,
u.STATUS,
+ u.email,
d.NAME AS dept_name,
GROUP_CONCAT( r.NAME ) AS roleNames,
u.create_time
@@ -182,6 +183,7 @@
u.username,
u.nickname,
u.mobile,
+ u.email,
CASE u.gender
WHEN 1 THEN '男'
WHEN 2 THEN '女'
@@ -219,6 +221,7 @@
u.gender,
u.avatar,
u.STATUS,
+ u.email,
d.NAME AS deptName,
GROUP_CONCAT(r.NAME) AS roleNames,
u.create_time
From d15af9f51e483f46191e791c0fede1ba0b6e9249 Mon Sep 17 00:00:00 2001
From: Theo <971366405@qq.com>
Date: Wed, 22 Jan 2025 16:45:28 +0800
Subject: [PATCH 05/39] =?UTF-8?q?refactor(system):=20=E4=BC=98=E5=8C=96?=
=?UTF-8?q?=E7=94=A8=E6=88=B7=E5=AF=BC=E5=87=BA=E5=8A=9F=E8=83=BD?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
- 移除 UserMapper 中的性别转换逻辑
- 在 UserServiceImpl 中添加字典数据获取和性别转换逻辑
---
.../system/service/impl/UserServiceImpl.java | 38 ++++++++++++-------
.../resources/mapper/system/UserMapper.xml | 6 +--
2 files changed, 25 insertions(+), 19 deletions(-)
diff --git a/src/main/java/com/youlai/boot/system/service/impl/UserServiceImpl.java b/src/main/java/com/youlai/boot/system/service/impl/UserServiceImpl.java
index e9beb707..c4f74448 100644
--- a/src/main/java/com/youlai/boot/system/service/impl/UserServiceImpl.java
+++ b/src/main/java/com/youlai/boot/system/service/impl/UserServiceImpl.java
@@ -10,29 +10,29 @@ import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.youlai.boot.common.constant.RedisConstants;
import com.youlai.boot.common.constant.SystemConstants;
-import com.youlai.boot.core.security.manager.TokenManager;
+import com.youlai.boot.common.exception.BusinessException;
import com.youlai.boot.common.model.Option;
+import com.youlai.boot.core.security.manager.TokenManager;
+import com.youlai.boot.core.security.service.PermissionService;
+import com.youlai.boot.core.security.util.SecurityUtils;
import com.youlai.boot.shared.mail.service.MailService;
import com.youlai.boot.shared.sms.enums.SmsTypeEnum;
import com.youlai.boot.shared.sms.service.SmsService;
+import com.youlai.boot.system.converter.UserConverter;
+import com.youlai.boot.system.enums.DictCodeEnum;
+import com.youlai.boot.system.mapper.UserMapper;
+import com.youlai.boot.system.model.bo.UserBO;
+import com.youlai.boot.system.model.dto.UserAuthInfo;
+import com.youlai.boot.system.model.dto.UserExportDTO;
+import com.youlai.boot.system.model.entity.DictData;
import com.youlai.boot.system.model.entity.User;
import com.youlai.boot.system.model.entity.UserRole;
import com.youlai.boot.system.model.form.*;
-import com.youlai.boot.system.converter.UserConverter;
-import com.youlai.boot.common.exception.BusinessException;
-import com.youlai.boot.system.model.vo.UserProfileVO;
-import com.youlai.boot.core.security.util.SecurityUtils;
-import com.youlai.boot.system.mapper.UserMapper;
-import com.youlai.boot.system.model.dto.UserAuthInfo;
-import com.youlai.boot.system.model.bo.UserBO;
import com.youlai.boot.system.model.query.UserPageQuery;
-import com.youlai.boot.system.model.dto.UserExportDTO;
import com.youlai.boot.system.model.vo.UserInfoVO;
import com.youlai.boot.system.model.vo.UserPageVO;
-import com.youlai.boot.core.security.service.PermissionService;
-import com.youlai.boot.system.service.RoleService;
-import com.youlai.boot.system.service.UserRoleService;
-import com.youlai.boot.system.service.UserService;
+import com.youlai.boot.system.model.vo.UserProfileVO;
+import com.youlai.boot.system.service.*;
import lombok.RequiredArgsConstructor;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.security.crypto.password.PasswordEncoder;
@@ -69,6 +69,8 @@ public class UserServiceImpl extends ServiceImpl implements Us
private final TokenManager tokenManager;
+ private final DictDataService dictDataService;
+
private final UserConverter userConverter;
/**
@@ -274,7 +276,15 @@ public class UserServiceImpl extends ServiceImpl implements Us
*/
@Override
public List listExportUsers(UserPageQuery queryParams) {
- return this.baseMapper.listExportUsers(queryParams);
+ List userExportDTOS = this.baseMapper.listExportUsers(queryParams);
+ //获取角色的字典数据
+ List list = dictDataService.list(new LambdaQueryWrapper().eq(DictData::getDictCode, DictCodeEnum.GENDER.getValue()));
+ Map genderMap = list.stream().collect(Collectors.toMap(DictData::getValue, DictData::getLabel));
+ userExportDTOS.forEach(userExportDTO -> {
+ String genderLabel = genderMap.get(userExportDTO.getGender());
+ userExportDTO.setGender(genderLabel);
+ });
+ return null;
}
/**
diff --git a/src/main/resources/mapper/system/UserMapper.xml b/src/main/resources/mapper/system/UserMapper.xml
index 1cfc5907..0940c488 100644
--- a/src/main/resources/mapper/system/UserMapper.xml
+++ b/src/main/resources/mapper/system/UserMapper.xml
@@ -184,11 +184,7 @@
u.nickname,
u.mobile,
u.email,
- CASE u.gender
- WHEN 1 THEN '男'
- WHEN 2 THEN '女'
- ELSE '保密'
- END gender,
+ u.gender,
d.NAME AS dept_name,
u.create_time
FROM
From 5b97e69ef91bf959c512291433cf161ec0968ec1 Mon Sep 17 00:00:00 2001
From: "Ray.Hao" <1490493387@qq.com>
Date: Thu, 6 Feb 2025 09:51:31 +0800
Subject: [PATCH 06/39] =?UTF-8?q?fix(youlai=5Fboot.sql):=20=E4=BF=AE?=
=?UTF-8?q?=E5=A4=8DSQL=E8=84=9A=E6=9C=AC=20sys=5Fuser=20=E8=A1=A8?=
=?UTF-8?q?=E7=9A=84=20id=20=E5=AD=97=E6=AE=B5=E7=B1=BB=E5=9E=8B=E4=B8=8D?=
=?UTF-8?q?=E6=AD=A3=E7=A1=AE?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Closes #IBJQXR
---
sql/mysql5/youlai_boot.sql | 2 +-
sql/mysql8/youlai_boot.sql | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/sql/mysql5/youlai_boot.sql b/sql/mysql5/youlai_boot.sql
index b9dbe911..2459df40 100644
--- a/sql/mysql5/youlai_boot.sql
+++ b/sql/mysql5/youlai_boot.sql
@@ -393,7 +393,7 @@ INSERT INTO `sys_role_menu` VALUES (2, 143);
-- ----------------------------
DROP TABLE IF EXISTS `sys_user`;
CREATE TABLE `sys_user` (
- `id` int NOT NULL AUTO_INCREMENT,
+ `id` bigint NOT NULL AUTO_INCREMENT,
`username` varchar(64) NULL DEFAULT NULL COMMENT '用户名',
`nickname` varchar(64) NULL DEFAULT NULL COMMENT '昵称',
`gender` tinyint(1) NULL DEFAULT 1 COMMENT '性别((1-男 2-女 0-保密)',
diff --git a/sql/mysql8/youlai_boot.sql b/sql/mysql8/youlai_boot.sql
index 70247977..7aead97f 100644
--- a/sql/mysql8/youlai_boot.sql
+++ b/sql/mysql8/youlai_boot.sql
@@ -351,7 +351,7 @@ INSERT INTO `sys_role_menu` VALUES (2, 143);
-- ----------------------------
DROP TABLE IF EXISTS `sys_user`;
CREATE TABLE `sys_user` (
- `id` int NOT NULL AUTO_INCREMENT,
+ `id` bigint NOT NULL AUTO_INCREMENT,
`username` varchar(64) DEFAULT NULL COMMENT '用户名',
`nickname` varchar(64) DEFAULT NULL COMMENT '昵称',
`gender` tinyint(1) NULL DEFAULT 1 COMMENT '性别((1-男 2-女 0-保密)',
From 284f6dafb03c64cdcddf5f02c1abf82fadce2145 Mon Sep 17 00:00:00 2001
From: "Ray.Hao" <1490493387@qq.com>
Date: Thu, 6 Feb 2025 13:42:16 +0800
Subject: [PATCH 07/39] =?UTF-8?q?refactor:=20=E4=BC=98=E5=8C=96=20web=20?=
=?UTF-8?q?=E6=97=B6=E9=97=B4=E5=85=A8=E5=B1=80=E9=85=8D=E7=BD=AE=E5=92=8C?=
=?UTF-8?q?=E5=AE=8C=E5=96=84=E6=B3=A8=E9=87=8A?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../com/youlai/boot/config/WebMvcConfig.java | 33 ++++++++-----------
1 file changed, 14 insertions(+), 19 deletions(-)
diff --git a/src/main/java/com/youlai/boot/config/WebMvcConfig.java b/src/main/java/com/youlai/boot/config/WebMvcConfig.java
index ec938575..41fa407b 100644
--- a/src/main/java/com/youlai/boot/config/WebMvcConfig.java
+++ b/src/main/java/com/youlai/boot/config/WebMvcConfig.java
@@ -1,14 +1,10 @@
package com.youlai.boot.config;
-import cn.hutool.core.date.DatePattern;
-import cn.hutool.core.date.DateTime;
-import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.databind.module.SimpleModule;
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
-import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer;
import jakarta.validation.Validation;
import jakarta.validation.Validator;
import jakarta.validation.ValidatorFactory;
@@ -24,15 +20,13 @@ import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import java.math.BigInteger;
import java.text.SimpleDateFormat;
-import java.time.LocalDateTime;
-import java.time.ZoneId;
-import java.time.format.DateTimeFormatter;
import java.util.List;
+import java.util.TimeZone;
/**
- * WebMvc 自动装配配置
+ * Web 配置
*
- * @author Ray
+ * @author Ray.Hao
* @since 2020/10/16
*/
@Configuration
@@ -47,21 +41,22 @@ public class WebMvcConfig implements WebMvcConfigurer {
@Override
public void configureMessageConverters(List> converters) {
MappingJackson2HttpMessageConverter jackson2HttpMessageConverter = new MappingJackson2HttpMessageConverter();
- ObjectMapper objectMapper = jackson2HttpMessageConverter.getObjectMapper();
- objectMapper.registerModule(new JavaTimeModule());
- objectMapper.configure(JsonParser.Feature.ALLOW_UNQUOTED_FIELD_NAMES, true);
- objectMapper.configure(SerializationFeature.WRITE_ENUMS_USING_TO_STRING, true);
+ ObjectMapper objectMapper = new ObjectMapper();
- // 处理 Long 和 BigInteger 类型,避免前端精度丢失问题
+ // 注册 JavaTimeModule(替代手动注册 LocalDateTimeSerializer)
+ JavaTimeModule javaTimeModule = new JavaTimeModule();
+ objectMapper.registerModule(javaTimeModule);
+
+ // 配置全局日期格式和时区
+ objectMapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
+ objectMapper.setDateFormat(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"));
+ objectMapper.setTimeZone(TimeZone.getTimeZone("GMT+8"));
+
+ // 处理 Long/BigInteger 的精度问题
SimpleModule simpleModule = new SimpleModule();
simpleModule.addSerializer(Long.class, ToStringSerializer.instance);
simpleModule.addSerializer(BigInteger.class, ToStringSerializer.instance);
- simpleModule.addSerializer(LocalDateTime.class, new LocalDateTimeSerializer(
- DateTimeFormatter.ofPattern(DatePattern.NORM_DATETIME_PATTERN).withZone(ZoneId.of( "GMT+8"))
- ));
objectMapper.registerModule(simpleModule);
- objectMapper.setDateFormat(new SimpleDateFormat(DatePattern.NORM_DATETIME_PATTERN));
-
jackson2HttpMessageConverter.setObjectMapper(objectMapper);
converters.add(1, jackson2HttpMessageConverter);
From b0ede31721b3687518ed51b769cdff6a29d8e9a5 Mon Sep 17 00:00:00 2001
From: "Ray.Hao" <1490493387@qq.com>
Date: Thu, 6 Feb 2025 13:44:12 +0800
Subject: [PATCH 08/39] =?UTF-8?q?chore:=20=E7=A7=BB=E9=99=A4=E6=97=A0?=
=?UTF-8?q?=E7=94=A8=E5=AD=97=E6=AE=B5?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../java/com/youlai/boot/system/model/vo/VisitTrendVO.java | 5 +----
1 file changed, 1 insertion(+), 4 deletions(-)
diff --git a/src/main/java/com/youlai/boot/system/model/vo/VisitTrendVO.java b/src/main/java/com/youlai/boot/system/model/vo/VisitTrendVO.java
index 0a47b0a1..42e8a2cb 100644
--- a/src/main/java/com/youlai/boot/system/model/vo/VisitTrendVO.java
+++ b/src/main/java/com/youlai/boot/system/model/vo/VisitTrendVO.java
@@ -10,7 +10,7 @@ import java.util.List;
/**
* 访问趋势VO
*
- * @author Ray
+ * @author Ray.Hao
* @since 2.3.0
*/
@Schema(description = "访问趋势VO")
@@ -24,9 +24,6 @@ public class VisitTrendVO {
@Schema(description = "浏览量(PV)")
private List pvList;
- @Schema(description = "访客数(UV)")
- private List uvList;
-
@Schema(description = "IP数")
private List ipList;
From abfbae6f49e68bd9f2d5d31359e4c0fef7ef18ee Mon Sep 17 00:00:00 2001
From: "Ray.Hao" <1490493387@qq.com>
Date: Thu, 6 Feb 2025 13:45:59 +0800
Subject: [PATCH 09/39] =?UTF-8?q?fix:=20=E4=BF=AE=E5=A4=8D=E5=9B=A0bo?=
=?UTF-8?q?=E5=92=8Cvo=E7=9A=84=E6=97=B6=E9=97=B4=E7=B1=BB=E5=9E=8B?=
=?UTF-8?q?=E4=B8=8D=E4=B8=80=E8=87=B4=E5=AF=BC=E8=87=B4mapstruct=E6=98=A0?=
=?UTF-8?q?=E5=B0=84=E8=BD=AC=E6=8D=A2=E6=97=B6=E5=8C=BA=E9=94=99=E8=AF=AF?=
=?UTF-8?q?=E5=B0=91=E4=BA=868=E5=B0=8F=E6=97=B6=E7=9A=84=E9=97=AE?=
=?UTF-8?q?=E9=A2=98?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
src/main/java/com/youlai/boot/system/model/bo/UserBO.java | 6 ++----
.../java/com/youlai/boot/system/model/vo/UserPageVO.java | 4 ++--
2 files changed, 4 insertions(+), 6 deletions(-)
diff --git a/src/main/java/com/youlai/boot/system/model/bo/UserBO.java b/src/main/java/com/youlai/boot/system/model/bo/UserBO.java
index 2756db20..7fbc61ae 100644
--- a/src/main/java/com/youlai/boot/system/model/bo/UserBO.java
+++ b/src/main/java/com/youlai/boot/system/model/bo/UserBO.java
@@ -1,9 +1,8 @@
package com.youlai.boot.system.model.bo;
-import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Data;
-import java.util.Date;
+import java.time.LocalDateTime;
/**
* 用户持久化对象
@@ -67,6 +66,5 @@ public class UserBO {
/**
* 创建时间
*/
- @JsonFormat(pattern = "yyyy-MM-dd")
- private Date createTime;
+ private LocalDateTime createTime;
}
diff --git a/src/main/java/com/youlai/boot/system/model/vo/UserPageVO.java b/src/main/java/com/youlai/boot/system/model/vo/UserPageVO.java
index cf1ce1b0..0baa4c5b 100644
--- a/src/main/java/com/youlai/boot/system/model/vo/UserPageVO.java
+++ b/src/main/java/com/youlai/boot/system/model/vo/UserPageVO.java
@@ -4,7 +4,7 @@ import com.fasterxml.jackson.annotation.JsonFormat;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
-import java.util.Date;
+import java.time.LocalDateTime;
/**
* 用户分页视图对象
@@ -48,6 +48,6 @@ public class UserPageVO {
@Schema(description="创建时间")
@JsonFormat(pattern = "yyyy/MM/dd HH:mm")
- private Date createTime;
+ private LocalDateTime createTime;
}
From 8caf20a455de88fe797c95b8b699169c0c1ed67e Mon Sep 17 00:00:00 2001
From: "Ray.Hao" <1490493387@qq.com>
Date: Thu, 6 Feb 2025 13:49:54 +0800
Subject: [PATCH 10/39] =?UTF-8?q?chore:=20=E6=97=B6=E5=8C=BA=E5=92=8C?=
=?UTF-8?q?=E6=97=A5=E6=9C=9F=E6=A0=BC=E5=BC=8F=E7=94=B1=20WebMvcConfig=20?=
=?UTF-8?q?=E7=BB=9F=E4=B8=80=E7=AE=A1=E7=90=86=EF=BC=8C=E7=A7=BB=E9=99=A4?=
=?UTF-8?q?=E4=BA=86=E5=BD=93=E5=89=8D=E4=BB=A3=E7=A0=81=E4=B8=AD=E7=9A=84?=
=?UTF-8?q?=E9=87=8D=E5=A4=8D=E9=85=8D=E7=BD=AE=E4=BB=A5=E7=AE=80=E5=8C=96?=
=?UTF-8?q?=E7=BB=B4=E6=8A=A4?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
src/main/resources/application-dev.yml | 5 -----
src/main/resources/application-prod.yml | 5 -----
2 files changed, 10 deletions(-)
diff --git a/src/main/resources/application-dev.yml b/src/main/resources/application-dev.yml
index 0a9722ae..18094a6e 100644
--- a/src/main/resources/application-dev.yml
+++ b/src/main/resources/application-dev.yml
@@ -2,11 +2,6 @@ server:
port: 8989
spring:
- jackson:
- ## 默认序列化时间格式
- date-format: yyyy-MM-dd HH:mm:ss
- ## 默认序列化时区
- time-zone: GMT+8
datasource:
type: com.alibaba.druid.pool.DruidDataSource
driver-class-name: com.mysql.cj.jdbc.Driver
diff --git a/src/main/resources/application-prod.yml b/src/main/resources/application-prod.yml
index 24379401..2fa52d4a 100644
--- a/src/main/resources/application-prod.yml
+++ b/src/main/resources/application-prod.yml
@@ -2,11 +2,6 @@ server:
port: 8989
spring:
- jackson:
- ## 默认序列化时间格式
- date-format: yyyy-MM-dd HH:mm:ss
- ## 默认序列化时区
- time-zone: GMT+8
datasource:
type: com.alibaba.druid.pool.DruidDataSource
driver-class-name: com.mysql.cj.jdbc.Driver
From cb8a2c4f41454c3de60146d2a4febbf1b71db917 Mon Sep 17 00:00:00 2001
From: Theo <971366405@qq.com>
Date: Mon, 10 Feb 2025 10:21:39 +0800
Subject: [PATCH 11/39] =?UTF-8?q?feat(cache):=20=E6=B7=BB=E5=8A=A0=20Caffe?=
=?UTF-8?q?ine=E7=BC=93=E5=AD=98=E6=94=AF=E6=8C=81=E5=B9=B6=E4=BC=98?=
=?UTF-8?q?=E5=8C=96=E6=97=A5=E5=BF=97=E5=A4=84=E7=90=86?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
- 在应用配置中添加 Caffeine 缓存配置
- 新增 CaffeineConfig 类用于缓存管理
- 在 Log 实体中添加 userAgent 字段保存原始用户代理字符串
- 优化 LogAspect 中的用户代理解析逻辑,增加缓存支持
- 更新数据库表结构,在 log 表中添加 user_agent 列
---
pom.xml | 7 +++
sql/mysql5/youlai_boot.sql | 1 +
sql/mysql8/youlai_boot.sql | 1 +
.../youlai/boot/config/CaffeineConfig.java | 37 ++++++++++++++++
.../youlai/boot/core/aspect/LogAspect.java | 44 +++++++++++++++++--
.../system/controller/UserController.java | 2 +
.../youlai/boot/system/model/entity/Log.java | 6 ++-
src/main/resources/application-dev.yml | 2 +
src/main/resources/application-prod.yml | 3 +-
9 files changed, 97 insertions(+), 6 deletions(-)
create mode 100644 src/main/java/com/youlai/boot/config/CaffeineConfig.java
diff --git a/pom.xml b/pom.xml
index c5885bd0..8f2f43ee 100644
--- a/pom.xml
+++ b/pom.xml
@@ -57,6 +57,7 @@
4.5.5.B
+ 2.9.3
@@ -232,6 +233,12 @@
${weixin-java.version}
+
+ com.github.ben-manes.caffeine
+ caffeine
+ ${caffeine.version}
+
+
diff --git a/sql/mysql5/youlai_boot.sql b/sql/mysql5/youlai_boot.sql
index 2459df40..ab74d5ae 100644
--- a/sql/mysql5/youlai_boot.sql
+++ b/sql/mysql5/youlai_boot.sql
@@ -144,6 +144,7 @@ CREATE TABLE `sys_log` (
`browser` varchar(100) DEFAULT NULL COMMENT '浏览器',
`browser_version` varchar(100) DEFAULT NULL COMMENT '浏览器版本',
`os` varchar(100) DEFAULT NULL COMMENT '终端系统',
+ `user_agent` varchar(255) DEFAULT NULL COMMENT '原生的用户代理字符串',
`create_by` bigint DEFAULT NULL COMMENT '创建人ID',
`create_time` datetime DEFAULT NULL COMMENT '创建时间',
`is_deleted` tinyint NOT NULL DEFAULT '0' COMMENT '逻辑删除标识(1-已删除 0-未删除)',
diff --git a/sql/mysql8/youlai_boot.sql b/sql/mysql8/youlai_boot.sql
index 7aead97f..677b923a 100644
--- a/sql/mysql8/youlai_boot.sql
+++ b/sql/mysql8/youlai_boot.sql
@@ -416,6 +416,7 @@ CREATE TABLE `sys_log` (
`browser` varchar(100) DEFAULT NULL COMMENT '浏览器',
`browser_version` varchar(100) DEFAULT NULL COMMENT '浏览器版本',
`os` varchar(100) DEFAULT NULL COMMENT '终端系统',
+ `user_agent` varchar(255) DEFAULT NULL COMMENT '原生的用户代理字符串',
`create_by` bigint DEFAULT NULL COMMENT '创建人ID',
`create_time` datetime DEFAULT NULL COMMENT '创建时间',
`is_deleted` tinyint NOT NULL DEFAULT '0' COMMENT '逻辑删除标识(1-已删除 0-未删除)',
diff --git a/src/main/java/com/youlai/boot/config/CaffeineConfig.java b/src/main/java/com/youlai/boot/config/CaffeineConfig.java
new file mode 100644
index 00000000..bba14491
--- /dev/null
+++ b/src/main/java/com/youlai/boot/config/CaffeineConfig.java
@@ -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