菜单优化

This commit is contained in:
张家训
2026-06-08 17:28:22 +08:00
parent 2308854c15
commit ecdfb1f1a1
6 changed files with 304 additions and 18 deletions
@@ -1,4 +1,4 @@
package com.example.workutils.menu.handler; package com.example.workutils.biz.git.menu;
import com.example.workutils.biz.git.service.GitService; import com.example.workutils.biz.git.service.GitService;
import com.example.workutils.biz.git.util.GitCommandExecutor; import com.example.workutils.biz.git.util.GitCommandExecutor;
@@ -13,12 +13,13 @@ import java.util.Scanner;
import java.util.stream.Collectors; import java.util.stream.Collectors;
/** /**
* Git仓库健康检测工具 * Git仓库健康检测菜单
* 仅负责菜单展示和用户交互,业务逻辑委托给GitService
*/ */
@Slf4j @Slf4j
@Component @Component
@RequiredArgsConstructor @RequiredArgsConstructor
public class GitHealthHandler extends AbstractTool { public class GitMenu extends AbstractTool {
private static final String[] MENU_OPTIONS = { private static final String[] MENU_OPTIONS = {
"1. 检测所有仓库健康状态", "1. 检测所有仓库健康状态",
@@ -1,4 +1,4 @@
package com.example.workutils.menu.handler; package com.example.workutils.biz.mybatis.menu;
import com.example.workutils.biz.mybatis.generator.MyBatisGeneratorService; import com.example.workutils.biz.mybatis.generator.MyBatisGeneratorService;
import com.example.workutils.tool.AbstractTool; import com.example.workutils.tool.AbstractTool;
@@ -11,12 +11,13 @@ import java.util.List;
import java.util.Scanner; import java.util.Scanner;
/** /**
* MyBatis逆向工程工具 * MyBatis逆向工程菜单
* 仅负责菜单展示和用户交互,业务逻辑委托给MyBatisGeneratorService
*/ */
@Slf4j @Slf4j
@Component @Component
@RequiredArgsConstructor @RequiredArgsConstructor
public class MyBatisGeneratorHandler extends AbstractTool { public class MyBatisGeneratorMenu extends AbstractTool {
private static final String[] MENU_OPTIONS = { private static final String[] MENU_OPTIONS = {
"1. 根据表名生成(单表)", "1. 根据表名生成(单表)",
@@ -1,4 +1,4 @@
package com.example.workutils.menu.handler; package com.example.workutils.biz.mybatis.menu;
import com.example.workutils.biz.mybatis.export.MyBatisExportService; import com.example.workutils.biz.mybatis.export.MyBatisExportService;
import com.example.workutils.tool.AbstractTool; import com.example.workutils.tool.AbstractTool;
@@ -10,12 +10,13 @@ import java.util.Arrays;
import java.util.Scanner; import java.util.Scanner;
/** /**
* MyBatis导出功能工具 * MyBatis SQL导出菜单
* 仅负责菜单展示和用户交互,业务逻辑委托给MyBatisExportService
*/ */
@Slf4j @Slf4j
@Component @Component
@RequiredArgsConstructor @RequiredArgsConstructor
public class MyBatisHandler extends AbstractTool { public class MyBatisMenu extends AbstractTool {
private static final String[] MENU_OPTIONS = { private static final String[] MENU_OPTIONS = {
"1. 导出所有SQL", "1. 导出所有SQL",
@@ -1,4 +1,4 @@
package com.example.workutils.menu.handler; package com.example.workutils.biz.output.menu;
import com.example.workutils.biz.mybatis.export.MyBatisExportService; import com.example.workutils.biz.mybatis.export.MyBatisExportService;
import com.example.workutils.biz.scanner.service.ScanService; import com.example.workutils.biz.scanner.service.ScanService;
@@ -12,12 +12,13 @@ import java.util.List;
import java.util.Scanner; import java.util.Scanner;
/** /**
* 批量处理功能工具 * 批量处理菜单
* 仅负责菜单展示和用户交互,业务逻辑委托给各Service
*/ */
@Slf4j @Slf4j
@Component @Component
@RequiredArgsConstructor @RequiredArgsConstructor
public class BatchHandler extends AbstractTool { public class BatchMenu extends AbstractTool {
@FunctionalInterface @FunctionalInterface
public interface ExceptionRunnable { public interface ExceptionRunnable {
@@ -1,4 +1,4 @@
package com.example.workutils.menu.handler; package com.example.workutils.biz.scanner.menu;
import com.example.workutils.biz.scanner.service.ScanService; import com.example.workutils.biz.scanner.service.ScanService;
import com.example.workutils.tool.AbstractTool; import com.example.workutils.tool.AbstractTool;
@@ -9,12 +9,13 @@ import org.springframework.stereotype.Component;
import java.util.Scanner; import java.util.Scanner;
/** /**
* 扫描功能工具 * 扫描功能菜单
* 仅负责菜单展示和用户交互,业务逻辑委托给ScanService
*/ */
@Slf4j @Slf4j
@Component @Component
@RequiredArgsConstructor @RequiredArgsConstructor
public class ScanHandler extends AbstractTool { public class ScanMenu extends AbstractTool {
private static final String[] MENU_OPTIONS = { private static final String[] MENU_OPTIONS = {
"1. 关键词扫描", "1. 关键词扫描",
@@ -50,9 +51,6 @@ public class ScanHandler extends AbstractTool {
} }
} }
/**
* 关键词扫描
*/
private void scanByKeyword(Scanner scanner) throws Exception { private void scanByKeyword(Scanner scanner) throws Exception {
printMenuTitle("关键词扫描"); printMenuTitle("关键词扫描");
info("开始关键词扫描"); info("开始关键词扫描");
+284
View File
@@ -0,0 +1,284 @@
# 项目目录结构说明
> **项目名称**: workutils
> **技术栈**: Spring Boot 2.7.18 + Java 8 + Maven
> **项目类型**: Java 工作工具集项目(金融科技 FinTech 开发和维护工具集)
---
## 一、项目顶层目录
```
workutils/
├── export/ # 导出文件目录(运行结果输出)
├── logs/ # 日志文件目录
├── src/ # 源代码目录
├── target/ # Maven 编译输出目录(67个.class文件)
├── generator.rar # MyBatis Generator 压缩包
├── mvnw # Maven Wrapper(Unix/Mac)
├── mvnw.cmd # Maven Wrapper(Windows)
├── pom.xml # Maven 项目配置文件
├── 项目说明.md # 项目概述文档
└── 项目目录结构说明.md # 本文件
```
| 文件/目录 | 说明 |
|-----------|------|
| `pom.xml` | Maven 项目配置,定义依赖(Spring Boot、MyBatis、EasyExcel、JGit、Dubbo、Redis Jedis、OpenCSV 等) |
| `mvnw` / `mvnw.cmd` | Maven Wrapper 脚本,无需本地安装 Maven 即可构建项目 |
| `generator.rar` | MyBatis Generator 相关资源压缩包 |
| `export/` | 运行工具后输出的结果文件目录,按日期分子目录(如 `20260608/`) |
| `logs/` | 应用程序日志输出目录 |
| `target/` | Maven 编译产物,包含编译后的 `.class` 文件和资源文件副本 |
---
## 二、源码目录结构(`src/main/java/com/example/workutils/`)
```
src/main/java/com/example/workutils/
├── WorkUtilsAppliction.java # 应用启动入口
├── config/
│ └── WorkUtilsProperties.java # 全局配置属性类
├── tool/
│ ├── Tool.java # 工具策略接口
│ ├── AbstractTool.java # 工具基类(模板方法模式)
│ └── ToolRegistry.java # 工具注册中心
├── menu/
│ └── api/
│ └── MenuRunner.java # 交互式菜单运行器
└── biz/
├── git/ # Git操作业务模块
│ ├── config/
│ │ └── GitOptimizationConfig.java # Git性能优化配置
│ ├── menu/
│ │ └── GitMenu.java # Git仓库健康检测菜单(仅交互逻辑)
│ ├── model/
│ │ └── GitCommandDTO.java # Git命令传输对象
│ ├── service/
│ │ ├── GitCommandStrategy.java # Git命令策略接口
│ │ ├── GitService.java # Git服务接口
│ │ └── impl/
│ │ ├── GitServiceImpl.java # Git服务实现
│ │ ├── GitStrategyFactory.java # Git策略工厂
│ │ └── strategy/
│ │ ├── CheckBranchChangesStrategy.java # 检查分支变更策略
│ │ └── CheckoutAndPullStrategy.java # 切换并拉取策略
│ └── util/
│ ├── GitCommandController.java # Git命令控制器(异步/中断)
│ ├── GitCommandExecutor.java # Git命令执行器(核心)
│ ├── GitRepositoryManager.java # Git仓库管理器
│ └── GitResultCache.java # Git结果缓存管理器
├── mybatis/ # MyBatis业务模块
│ ├── export/
│ │ └── MyBatisExportService.java # MyBatis SQL导出服务
│ ├── generator/
│ │ ├── CustomCommentGenerator.java # 自定义注释生成器
│ │ ├── LombokPlugin.java # Lombok插件(@Data)
│ │ ├── MyBatisGeneratorService.java # MyBatis逆向工程服务
│ │ └── SelectiveOnlyPlugin.java # 只保留Selective方法插件
│ ├── menu/
│ │ ├── MyBatisMenu.java # MyBatis SQL导出菜单(仅交互逻辑)
│ │ └── MyBatisGeneratorMenu.java # MyBatis逆向工程菜单(仅交互逻辑)
│ ├── model/
│ │ └── MybatisTagBO.java # MyBatis标签数据对象
│ └── service/
│ └── XMLMapperChecker.java # XML Mapper检查器(旧版,包路径异常)
├── output/
│ ├── OutputService.java # 输出服务(CSV/Excel)
│ └── menu/
│ └── BatchMenu.java # 批量处理菜单(仅交互逻辑)
└── scanner/ # 扫描业务模块
├── config/
│ └── ScanConfigBO.java # 扫描配置对象
├── menu/
│ └── ScanMenu.java # 扫描功能菜单(仅交互逻辑)
└── service/
├── FileOperationService.java # 文件操作服务
└── ScanService.java # 扫描服务
```
---
## 三、核心文件详解
### 3.1 入口层
#### `WorkUtilsAppliction.java`
- **作用**: Spring Boot 应用启动类,实现 `CommandLineRunner`
- **功能**:
- 支持交互式菜单模式(无参数启动)
- 支持命令行模式(`sql`、`scan` 命令)
- 通过 `MenuRunner` 动态构建主菜单
#### `WorkUtilsProperties.java`
- **作用**: 全局配置属性类,绑定 `application.yml` 中 `workutils` 前缀的配置
- **功能**:
- 管理基础目录、配置目录、导出目录路径
- 提供带日期时间戳的导出文件路径生成
- 管理工具启用/禁用白名单和黑名单
---
### 3.2 工具框架层(`tool/`)
#### `Tool.java`
- **作用**: 工具策略接口,所有可插拔工具需实现此接口
- **核心方法**: `getId()`、`getName()`、`getMenuOptions()`、`execute()`
#### `AbstractTool.java`
- **作用**: 工具基类,使用模板方法模式
- **功能**: 提供标准菜单交互循环(显示菜单→读取选择→处理选择→循环),子类只需实现 `handleChoice()`
#### `ToolRegistry.java`
- **作用**: 工具注册中心,Spring 自动发现 `Tool` Bean
- **功能**: 根据配置过滤启用/禁用工具,支持白名单(enabled)和黑名单(disabled)模式
---
### 3.3 菜单层(`menu/`)
#### `MenuRunner.java`
- **作用**: 交互式主菜单运行器
- **功能**: 从 `ToolRegistry` 动态构建主菜单,无需硬编码 Menu 引用
> **重构说明**: 原先的 `menu/handler/` 下的 Handler 类已全部移除。菜单交互类已分散到各业务模块的 `menu/` 子包中,统一命名为 `XxxMenu`,仅负责菜单展示和用户交互,业务逻辑委托给对应 Service。
---
### 3.4 业务模块(`biz/`)
#### 3.4.1 Git 操作模块(`biz/git/`)
| 文件 | 作用 |
|------|------|
| `menu/GitMenu.java` | **Git 菜单类**(仅交互),显示菜单、接收用户输入、委托 GitService 执行业务逻辑 |
| `GitOptimizationConfig.java` | Git 性能优化配置类,管理超时、线程池、缓存、批处理、Fetch、网络等配置参数 |
| `GitCommandDTO.java` | Git 命令传输对象,定义命令类型枚举(CHECK_BRANCH_CHANGES、CHECKOUT_AND_PULL 等6种) |
| `GitService.java` | Git 服务接口,定义分支变更检查、切换拉取、健康检测、修复仓库等方法 |
| `GitCommandStrategy.java` | Git 命令策略接口,策略模式的核心接口 |
| `GitServiceImpl.java` | Git 服务实现,协调各策略执行,实现仓库健康检测和修复逻辑 |
| `GitStrategyFactory.java` | Git 策略工厂,注册和管理所有策略实现 |
| `CheckBranchChangesStrategy.java` | 分支变更检查策略实现,比较两个分支的差异 |
| `CheckoutAndPullStrategy.java` | 切换并拉取策略实现,批量切换分支并拉取最新代码 |
| `GitCommandExecutor.java` | **核心执行器**,封装原生 git 命令执行(支持 Windows/Linux),提供超时控制、并发线程池、命令批处理 |
| `GitCommandController.java` | Git 命令控制器,管理命令的异步执行、跳过、中断功能 |
| `GitRepositoryManager.java` | Git 仓库管理器,提供仓库发现、分支操作、批量操作等高级封装 |
| `GitResultCache.java` | Git 结果缓存管理器,缓存仓库信息/分支信息/提交ID,减少重复 git 命令 |
#### 3.4.2 MyBatis 模块(`biz/mybatis/`)
| 文件 | 作用 |
|------|------|
| `menu/MyBatisMenu.java` | **MyBatis SQL 导出菜单**(仅交互),显示导出选项、接收用户输入、委托 MyBatisExportService 执行 |
| `menu/MyBatisGeneratorMenu.java` | **MyBatis 逆向工程菜单**(仅交互),显示生成选项、接收用户输入、委托 MyBatisGeneratorService 执行 |
| `MyBatisExportService.java` | **MyBatis SQL 导出核心服务**,从 XML 文件中提取 select/insert/update/delete 标签,支持按表名、关键字、标签ID 过滤导出为 CSV |
| `XMLMapperChecker.java` | XML Mapper 检查器,检查 XML 文件格式是否正确(注意:此文件包路径为 `com.example.workutils.service`,与项目结构不一致) |
| `MybatisTagBO.java` | MyBatis 标签数据对象,封装 tagId、tagName、parameterType、resultMap、namespace 等信息 |
| `MyBatisGeneratorService.java` | MyBatis 逆向工程服务,根据数据库表生成 PO、Mapper 接口、XML 映射文件 |
| `CustomCommentGenerator.java` | 自定义注释生成器,生成简洁中文注释(字段备注、方法名中文说明) |
| `LombokPlugin.java` | Lombok 插件,为 PO 类添加 `@Data` 注解并禁用 getter/setter 方法生成 |
| `SelectiveOnlyPlugin.java` | 自定义插件,只保留 `insertSelective` 和 `updateByPrimaryKeySelective`,移除全字段版本 |
#### 3.4.3 输出模块(`biz/output/`)
| 文件 | 作用 |
|------|------|
| `menu/BatchMenu.java` | **批量处理菜单**(仅交互),显示批量检查选项、接收用户输入、委托各 Service 执行 |
| `OutputService.java` | 输出服务,负责将数据输出为 CSV(OpenCSV)或 Excel(EasyExcel)格式,支持单Sheet/多Sheet、追加写入等 |
#### 3.4.4 扫描模块(`biz/scanner/`)
| 文件 | 作用 |
|------|------|
| `menu/ScanMenu.java` | **扫描功能菜单**(仅交互),显示扫描选项、接收用户输入、委托 ScanService 执行 |
| `ScanConfigBO.java` | 扫描配置对象,定义文件扩展名、排除目录、最大文件大小等扫描参数 |
| `FileOperationService.java` | 文件操作服务,提供文件读取、扫描、写入、项目路径管理等基础能力 |
| `ScanService.java` | 扫描服务,支持关键词扫描、Redis Key 扫描、Dubbo 接口扫描三种类型,支持并发多项目扫描 |
---
## 四、资源配置文件(`src/main/resources/`)
```
src/main/resources/
├── application.yml # Spring Boot 主配置文件
├── logback.xml # 日志框架配置
├── mybatis-generator.xml # MyBatis Generator 配置文件
├── mybatis-generator.properties # MyBatis Generator 数据库连接配置
└── config/
└── 代码仓库项目路径.txt # 要扫描的代码仓库路径列表(含状态标记)
```
| 文件 | 说明 |
|------|------|
| `application.yml` | 配置应用名、`workutils` 路径配置、工具启用/禁用、日志级别 |
| `logback.xml` | Logback 日志配置,控制台输出格式为 `HH:mm:ss.SSS [线程] 级别 Logger - 消息` |
| `mybatis-generator.xml` | MyBatis Generator 配置,引用自定义插件(LombokPlugin、SelectiveOnlyPlugin、CustomCommentGenerator),配置模型/Mapper/XML 生成路径 |
| `mybatis-generator.properties` | 数据库连接信息(MySQL),JDBC URL/用户名/密码/驱动路径,以及生成的包路径 |
| `代码仓库项目路径.txt` | 待扫描的代码仓库绝对路径列表,每行格式 `路径|状态`(NORMAL/CORRUPTED),共约72个项目 |
---
## 五、设计模式与架构特点
| 模式/特点 | 应用位置 | 说明 |
|-----------|---------|------|
| **策略模式** | `Tool` + `AbstractTool` + Handler 实现 | 各工具通过实现 `Tool` 接口注册,可插拔扩展 |
| **模板方法模式** | `AbstractTool` | 定义菜单交互骨架,子类实现 `handleChoice()` |
| **策略模式** | `GitCommandStrategy` + 各 Strategy 实现 | Git 命令执行策略,`GitStrategyFactory` 管理注册 |
| **工厂模式** | `ToolRegistry`、`GitStrategyFactory` | 自动发现和注册 Bean |
| **命令模式** | `GitCommandDTO` + `GitCommandController` | 封装 Git 命令的异步执行、中断、跳过 |
| **缓存模式** | `GitResultCache` | 缓存 Git 查询结果,减少重复命令执行 |
| **并发处理** | `GitCommandExecutor`、`ScanService` | 线程池并发执行 Git 命令和多项目扫描 |
| **过滤器模式** | `MyBatisExportService` 内部类 | `SqlFilter` 接口实现表名/关键字/标签ID 过滤 |
| **模板回调** | `FileOperationService.scanFilesRecursively` | 使用 `SimpleFileVisitor` 实现文件遍历回调 |
---
## 六、依赖关系图
```
WorkUtilsAppliction (入口)
├── MenuRunner (菜单系统)
│ └── ToolRegistry (工具注册)
│ ├── BatchMenu ──────────────→ ScanService + MyBatisExportService
│ ├── GitMenu ────────────────→ GitService
│ ├── MyBatisMenu ────────────→ MyBatisExportService
│ ├── MyBatisGeneratorMenu ───→ MyBatisGeneratorService
│ └── ScanMenu ───────────────→ ScanService
│
└── 命令行模式
├── sql → MyBatisExportService
└── scan → ScanService
核心依赖链:
MyBatisExportService → FileOperationService + OutputService
ScanService → FileOperationService + OutputService
GitServiceImpl → FileOperationService + GitCommandExecutor
OutputService → FileOperationService + WorkUtilsProperties
FileOperationService → WorkUtilsProperties
```
---
## 七、问题与改进建议
### 7.1 发现的问题
| 问题 | 位置 | 说明 |
|------|------|------|
| 包路径不一致 | `XMLMapperChecker.java` | 实际包路径 `com.example.workutils.service`,但位于 `biz/mybatis/service/` 目录下 |
| 未使用文件 | `XMLMapperChecker.java` | 代码中没有任何地方引用此类 |
| 配置文件硬编码 | `mybatis-generator.properties` | 包含明文密码 `1Qaz@4772` |
| pom.xml 重复依赖 | `fastjson` 1.2.83 和 2.0.57 | 两个版本的 fastjson 同时存在 |
| 项目说明版本不匹配 | `项目说明.md` | 描述为 Spring Boot 3.2.3 + Java 21,实际为 Spring Boot 2.7.18 + Java 8 |
### 7.2 重构建议
1. **修复 `XMLMapperChecker` 包路径**,或将其删除(未被引用)
2. **统一 fastjson 版本**,建议只保留 2.0.57
3. **将数据库密码移到外部配置文件**或使用环境变量
4. **更新 `项目说明.md`** 使其与实际技术栈一致
5. **考虑提取公共的 CSV 操作到 `OutputService`**,减少 `MyBatisExportService` 中的 CSV 相关代码
6. **增加单元测试**,目前无测试代码