mirror of
https://github.com/ccmjga/zhilu-admin
synced 2026-04-05 20:07:32 +00:00
Compare commits
7 Commits
b759275cf3
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
96de9a215f | ||
|
|
59631cea3d | ||
|
|
9425c2c88d | ||
|
|
38556f3417 | ||
|
|
f0a237fdf3 | ||
|
|
13d240342c | ||
|
|
8e20f561a4 |
14
README.md
14
README.md
@@ -30,31 +30,27 @@
|
|||||||
- [🍑 更多](#-更多)
|
- [🍑 更多](#-更多)
|
||||||
- [🍒 部分技术选型](#-部分技术选型)
|
- [🍒 部分技术选型](#-部分技术选型)
|
||||||
- [🔮 防失联,关注各大社区账号](#-防失联关注各大社区账号)
|
- [🔮 防失联,关注各大社区账号](#-防失联关注各大社区账号)
|
||||||
- [💌 微信打赏](#-微信打赏)
|
|
||||||
|
|
||||||
## 🥝 产品社群
|
## 🥝 产品社群
|
||||||
|
|
||||||
**加 QQ 群或微信群立送以下装备,瞬间秒杀全服!!**
|
|
||||||
1. 一键部署脚本(包含数据库 Redis 消息队列等所有中间件!)
|
1. 一键部署脚本(包含数据库 Redis 消息队列等所有中间件!)
|
||||||
2. 永久免费的 Https 证书
|
2. 永久免费的 Https 证书
|
||||||
3. 永久免费的分布式对象存储
|
3. 永久免费的分布式对象存储
|
||||||
4. 永久免费的 AI 模型
|
4. 永久免费的 AI 模型
|
||||||
5. 永久免费的 Node、Docker、Maven 国内镜像仓库
|
5. 永久免费的 Node、Docker、Maven 国内镜像仓库
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||
[](https://qm.qq.com/q/9mvVC57jPO)
|
[](https://qm.qq.com/q/9mvVC57jPO)
|
||||||
|
|
||||||
|
|
||||||
- QQ群:638254979(目前人较多)
|
- QQ群:638254979
|
||||||
- 微信:Chuck9996(若微信群已过期可以加我 vx)
|
|
||||||
|
|
||||||
|
|
||||||
## 🍅 相关课程
|
## 🍅 相关课程
|
||||||
|
|
||||||
已上线:
|
已上线:
|
||||||
|
|
||||||
- [《国内首个无幻觉式 AI 编程指南》](https://www.bilibili.com/cheese/play/ep1615343)
|
- [《AI 时代的 Java 测试驱动开发》](https://www.bilibili.com/cheese/play/ep1615343)
|
||||||
|
|
||||||
敬请期待:(加群获取)
|
敬请期待:(加群获取)
|
||||||
|
|
||||||
@@ -209,9 +205,3 @@
|
|||||||
[](https://github.com/ccmjga)
|
[](https://github.com/ccmjga)
|
||||||
|
|
||||||
[](https://qm.qq.com/q/9mvVC57jPO)
|
[](https://qm.qq.com/q/9mvVC57jPO)
|
||||||
|
|
||||||
## 💌 微信打赏
|
|
||||||
|
|
||||||
知路管理后台的发展离不开您的支持;再次对所有支持本项目的人们致以诚挚的谢意~
|
|
||||||
|
|
||||||

|
|
||||||
|
|||||||
BIN
assets/group.png
BIN
assets/group.png
Binary file not shown.
|
Before Width: | Height: | Size: 538 KiB After Width: | Height: | Size: 580 KiB |
@@ -6,40 +6,10 @@ import java.lang.annotation.Retention;
|
|||||||
import java.lang.annotation.RetentionPolicy;
|
import java.lang.annotation.RetentionPolicy;
|
||||||
import java.lang.annotation.Target;
|
import java.lang.annotation.Target;
|
||||||
|
|
||||||
/**
|
|
||||||
* 跳过AOP日志记录注解
|
|
||||||
*
|
|
||||||
* <p>在方法上添加此注解,该方法将不会被AOP日志切面拦截和记录。
|
|
||||||
*
|
|
||||||
* <p>使用场景:
|
|
||||||
*
|
|
||||||
* <ul>
|
|
||||||
* <li>敏感操作方法,不希望记录日志
|
|
||||||
* <li>高频调用方法,避免产生过多日志
|
|
||||||
* <li>内部工具方法,不需要业务日志记录
|
|
||||||
* </ul>
|
|
||||||
*
|
|
||||||
* <p>使用示例:
|
|
||||||
*
|
|
||||||
* <pre>{@code
|
|
||||||
* @SkipAopLog
|
|
||||||
* public void sensitiveMethod() {
|
|
||||||
* // 此方法不会被AOP日志记录
|
|
||||||
* }
|
|
||||||
* }</pre>
|
|
||||||
*
|
|
||||||
* @author AOP Log System
|
|
||||||
* @since 1.0
|
|
||||||
*/
|
|
||||||
@Target(ElementType.METHOD)
|
@Target(ElementType.METHOD)
|
||||||
@Retention(RetentionPolicy.RUNTIME)
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
@Documented
|
@Documented
|
||||||
public @interface SkipAopLog {
|
public @interface SkipAopLog {
|
||||||
|
|
||||||
/**
|
|
||||||
* 跳过日志记录的原因说明(可选)
|
|
||||||
*
|
|
||||||
* @return 跳过原因
|
|
||||||
*/
|
|
||||||
String reason() default "";
|
String reason() default "";
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,103 +0,0 @@
|
|||||||
# LoggingAspect generateCurlCommand 方法单元测试
|
|
||||||
|
|
||||||
## 测试概述
|
|
||||||
|
|
||||||
本测试文件 `LoggingAspectCurlGenerationTest.java` 专门针对 `LoggingAspect` 类中的 `generateCurlCommand` 方法进行全面的单元测试,验证该方法在各种场景下生成 curl 命令的正确性。
|
|
||||||
|
|
||||||
## 测试架构
|
|
||||||
|
|
||||||
测试采用 **嵌套测试类** 的结构,按功能模块组织:
|
|
||||||
|
|
||||||
### 1. GET 请求测试 (`GetRequestTests`)
|
|
||||||
- ✅ 基本 GET 请求 - 无查询参数
|
|
||||||
- ✅ GET 请求 - 包含查询参数
|
|
||||||
- ✅ GET 请求 - HTTPS 协议
|
|
||||||
- ✅ GET 请求 - 自定义端口
|
|
||||||
|
|
||||||
### 2. POST 请求测试 (`PostRequestTests`)
|
|
||||||
- ✅ POST 请求 - JSON 请求体
|
|
||||||
- ✅ POST 请求 - 空 JSON 请求体
|
|
||||||
- ✅ POST 请求 - 包含单引号的 JSON
|
|
||||||
|
|
||||||
### 3. PUT 和 PATCH 请求测试 (`PutAndPatchRequestTests`)
|
|
||||||
- ✅ PUT 请求 - JSON 请求体
|
|
||||||
- ✅ PATCH 请求 - JSON 请求体
|
|
||||||
|
|
||||||
### 4. 表单数据请求测试 (`FormDataRequestTests`)
|
|
||||||
- ✅ POST 请求 - 表单数据
|
|
||||||
- ✅ POST 请求 - 多值表单参数
|
|
||||||
- ✅ POST 请求 - 空表单数据
|
|
||||||
|
|
||||||
### 5. 请求头处理测试 (`HeaderProcessingTests`)
|
|
||||||
- ✅ 包含常规请求头
|
|
||||||
- ✅ 跳过特定请求头
|
|
||||||
- ✅ 验证跳过的请求头不会出现在 curl 命令中
|
|
||||||
|
|
||||||
### 6. 异常情况测试 (`ExceptionHandlingTests`)
|
|
||||||
- ✅ 读取请求体时发生 IOException
|
|
||||||
- ✅ 请求参数为 null
|
|
||||||
- ✅ 请求方法为 null
|
|
||||||
- ✅ 服务器信息为 null
|
|
||||||
|
|
||||||
### 7. 边界用例测试 (`BoundaryTests`)
|
|
||||||
- ✅ 最小化 GET 请求
|
|
||||||
- ✅ 复杂查询参数 - 包含特殊字符
|
|
||||||
- ✅ DELETE 请求 - 不应包含请求体
|
|
||||||
- ✅ HTTPS 请求 - 标准端口 443
|
|
||||||
- ✅ JSON 请求体为 null
|
|
||||||
|
|
||||||
## 测试覆盖的功能点
|
|
||||||
|
|
||||||
### 核心功能验证
|
|
||||||
1. **HTTP 方法处理**: GET, POST, PUT, PATCH, DELETE
|
|
||||||
2. **URL 构建**: 协议、主机名、端口、路径、查询参数
|
|
||||||
3. **请求头处理**: 包含/排除特定请求头
|
|
||||||
4. **请求体处理**: JSON、表单数据、空请求体
|
|
||||||
5. **异常处理**: 各种异常情况的优雅处理
|
|
||||||
|
|
||||||
### 特殊场景验证
|
|
||||||
1. **端口处理**: 标准端口省略,非标准端口包含
|
|
||||||
2. **字符转义**: JSON 中的单引号转义
|
|
||||||
3. **空值处理**: null 值的安全处理
|
|
||||||
4. **多值参数**: 表单中同名参数的多个值
|
|
||||||
|
|
||||||
## 测试技术特点
|
|
||||||
|
|
||||||
### 使用的测试技术
|
|
||||||
- **JUnit 5**: 现代化的测试框架
|
|
||||||
- **Mockito**: Mock 对象和行为验证
|
|
||||||
- **AssertJ**: 流畅的断言 API
|
|
||||||
- **嵌套测试**: 清晰的测试组织结构
|
|
||||||
|
|
||||||
### Mock 策略
|
|
||||||
- Mock `HttpServletRequest` 对象模拟各种 HTTP 请求场景
|
|
||||||
- Mock 依赖服务避免外部依赖
|
|
||||||
- 精确控制测试数据和行为
|
|
||||||
|
|
||||||
### 断言策略
|
|
||||||
- 验证生成的 curl 命令包含预期内容
|
|
||||||
- 验证不应包含的内容确实被排除
|
|
||||||
- 验证异常情况的错误消息
|
|
||||||
|
|
||||||
## 运行测试
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# 运行所有 generateCurlCommand 相关测试
|
|
||||||
./gradlew test --tests "com.zl.mjga.unit.LoggingAspectCurlGenerationTest"
|
|
||||||
|
|
||||||
# 运行特定测试类别
|
|
||||||
./gradlew test --tests "com.zl.mjga.unit.LoggingAspectCurlGenerationTest\$GetRequestTests"
|
|
||||||
```
|
|
||||||
|
|
||||||
## 测试价值
|
|
||||||
|
|
||||||
这套测试确保了 `generateCurlCommand` 方法在各种复杂场景下都能正确工作,为 AOP 日志功能的 curl 命令生成提供了可靠的质量保证。通过全面的测试覆盖,可以:
|
|
||||||
|
|
||||||
1. **防止回归**: 代码修改时及时发现问题
|
|
||||||
2. **文档作用**: 测试用例本身就是最好的使用文档
|
|
||||||
3. **重构支持**: 安全地进行代码重构
|
|
||||||
4. **质量保证**: 确保功能在各种边界条件下正常工作
|
|
||||||
|
|
||||||
## 测试结果
|
|
||||||
|
|
||||||
所有 **24 个测试用例** 均通过,覆盖了 `generateCurlCommand` 方法的所有主要功能和边界情况。
|
|
||||||
@@ -59,8 +59,6 @@
|
|||||||
"vue-tsc": "^2.2.8"
|
"vue-tsc": "^2.2.8"
|
||||||
},
|
},
|
||||||
"msw": {
|
"msw": {
|
||||||
"workerDirectory": [
|
"workerDirectory": ["public"]
|
||||||
"public"
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -443,10 +443,7 @@ onMounted(async () => {
|
|||||||
const $userDeleteModalElement: HTMLElement | null =
|
const $userDeleteModalElement: HTMLElement | null =
|
||||||
document.querySelector("#user-delete-modal");
|
document.querySelector("#user-delete-modal");
|
||||||
if ($userDeleteModalElement) {
|
if ($userDeleteModalElement) {
|
||||||
userDeleteModal.value = new Modal(
|
userDeleteModal.value = new Modal($userDeleteModalElement, {});
|
||||||
$userDeleteModalElement,
|
|
||||||
{}
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
const $departmentDeleteModalElement: HTMLElement | null =
|
const $departmentDeleteModalElement: HTMLElement | null =
|
||||||
document.querySelector("#department-delete-modal");
|
document.querySelector("#department-delete-modal");
|
||||||
|
|||||||
@@ -111,19 +111,23 @@ export const useAiChat = () => {
|
|||||||
const searchAction = async (message: string) => {
|
const searchAction = async (message: string) => {
|
||||||
isLoading.value = true;
|
isLoading.value = true;
|
||||||
try {
|
try {
|
||||||
const { data } = await client.POST("/ai/action/search", {
|
|
||||||
body: message,
|
|
||||||
});
|
|
||||||
messages.value.push({
|
messages.value.push({
|
||||||
content: data?.action
|
content: "",
|
||||||
? "搜索到功能,请您执行。"
|
|
||||||
: "未搜索到指定功能,请告诉我更加准确的信息。",
|
|
||||||
type: "action",
|
type: "action",
|
||||||
isUser: false,
|
isUser: false,
|
||||||
username: "知路智能体",
|
username: "知路智能体",
|
||||||
command: data?.action,
|
command: undefined,
|
||||||
});
|
});
|
||||||
return data;
|
const { data } = await client.POST("/ai/action/search", {
|
||||||
|
body: message,
|
||||||
|
});
|
||||||
|
messages.value[messages.value.length - 1].content = data?.action
|
||||||
|
? "搜索到功能,请您执行。"
|
||||||
|
: "未搜索到指定功能,请告诉我更加准确的信息。";
|
||||||
|
messages.value[messages.value.length - 1].command = data?.action;
|
||||||
|
} catch (error) {
|
||||||
|
messages.value.pop();
|
||||||
|
throw error;
|
||||||
} finally {
|
} finally {
|
||||||
isLoading.value = false;
|
isLoading.value = false;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
<div class="px-2 sm:px-4 pt-6 sm:rounded-lg">
|
<div class="px-2 sm:px-4 pt-6 sm:rounded-lg">
|
||||||
<div class="grid grid-cols-1 sm:grid-cols-2 xl:grid-cols-3 gap-4">
|
<div class="grid grid-cols-1 sm:grid-cols-2 xl:grid-cols-3 gap-4">
|
||||||
<PromotionBanner href="https://www.bilibili.com/cheese/play/ss198449120" imageSrc="/ai-tdd.png"
|
<PromotionBanner href="https://www.bilibili.com/cheese/play/ss198449120" imageSrc="/ai-tdd.png"
|
||||||
imageAlt="ai-tdd-tutorial" label="官方教程" text="无幻觉式 AI 编程方法论" />
|
imageAlt="ai-tdd-tutorial" label="官方教程" text="AI 时代的 Java 测试驱动开发" />
|
||||||
<PromotionBanner href="https://www.mjga.cc" imageSrc="/mjga.png" imageAlt="后端脚手架" label="后端脚手架"
|
<PromotionBanner href="https://www.mjga.cc" imageSrc="/mjga.png" imageAlt="后端脚手架" label="后端脚手架"
|
||||||
text="国内唯一可选配组件和元信息的脚手架" />
|
text="国内唯一可选配组件和元信息的脚手架" />
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
Reference in New Issue
Block a user