稳定版本-0609

This commit is contained in:
张家训
2026-06-09 09:32:34 +08:00
parent 55721b6eaf
commit 75a1049d8e
10 changed files with 151 additions and 184 deletions
@@ -1,6 +1,6 @@
package com.example.workutils.biz.batch; package com.example.workutils.biz.batch;
import com.example.workutils.biz.mybatis.service.MyBatisExportService; import com.example.workutils.biz.mybatisexport.service.MyBatisExportService;
import com.example.workutils.biz.scanner.service.ScannerService; import com.example.workutils.biz.scanner.service.ScannerService;
import com.example.workutils.system.tool.Tool; import com.example.workutils.system.tool.Tool;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
@@ -1,6 +1,6 @@
package com.example.workutils.biz.mybatis; package com.example.workutils.biz.mybatisexport;
import com.example.workutils.biz.mybatis.service.MyBatisExportService; import com.example.workutils.biz.mybatisexport.service.MyBatisExportService;
import com.example.workutils.system.tool.Tool; import com.example.workutils.system.tool.Tool;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
@@ -30,7 +30,7 @@ public class MyBatisExportTool implements Tool {
@Override @Override
public String getId() { public String getId() {
return "mybatis"; return "mybatisexport";
} }
@Override @Override
@@ -1,6 +1,6 @@
package com.example.workutils.biz.mybatis.service; package com.example.workutils.biz.mybatisexport.service;
import com.example.workutils.biz.mybatis.service.model.MybatisTag; import com.example.workutils.biz.mybatisexport.service.model.MybatisTag;
import com.example.workutils.biz.scanner.service.config.ScanConfig; import com.example.workutils.biz.scanner.service.config.ScanConfig;
import com.example.workutils.system.support.FileOperationService; import com.example.workutils.system.support.FileOperationService;
import com.example.workutils.system.support.OutputService; import com.example.workutils.system.support.OutputService;
@@ -202,8 +202,8 @@ public class MyBatisExportService {
return false; return false;
} }
String sqlText = removeSqlComments(tag.getTagOriginalXmlText()); String sqlText = removeSqlComments(tag.getTagOriginalXmlText());
for (String pattern : TABLE_PATTERNS) { for (String patternStr : TABLE_PATTERNS) {
Pattern p = Pattern.compile(pattern); Pattern p = Pattern.compile(patternStr);
Matcher m = p.matcher(sqlText); Matcher m = p.matcher(sqlText);
while (m.find()) { while (m.find()) {
String tableName = m.group(2); String tableName = m.group(2);
@@ -1,4 +1,4 @@
package com.example.workutils.biz.mybatis.service.model; package com.example.workutils.biz.mybatisexport.service.model;
import lombok.Data; import lombok.Data;
@@ -1,6 +1,6 @@
package com.example.workutils.biz.mybatis; package com.example.workutils.biz.mybatisgenerator;
import com.example.workutils.biz.mybatis.service.generator.MyBatisGeneratorService; import com.example.workutils.biz.mybatisgenerator.service.generator.MyBatisGeneratorService;
import com.example.workutils.system.tool.Tool; import com.example.workutils.system.tool.Tool;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
@@ -31,7 +31,7 @@ public class MyBatisGeneratorTool implements Tool {
@Override @Override
public String getId() { public String getId() {
return "mybatis-generator"; return "mybatisgenerator";
} }
@Override @Override
@@ -1,4 +1,4 @@
package com.example.workutils.biz.mybatis.service.generator; package com.example.workutils.biz.mybatisgenerator.service.generator;
import org.mybatis.generator.api.CommentGenerator; import org.mybatis.generator.api.CommentGenerator;
import org.mybatis.generator.api.IntrospectedColumn; import org.mybatis.generator.api.IntrospectedColumn;
@@ -1,4 +1,4 @@
package com.example.workutils.biz.mybatis.service.generator; package com.example.workutils.biz.mybatisgenerator.service.generator;
import org.mybatis.generator.api.IntrospectedColumn; import org.mybatis.generator.api.IntrospectedColumn;
import org.mybatis.generator.api.IntrospectedTable; import org.mybatis.generator.api.IntrospectedTable;
@@ -27,7 +27,6 @@ public class LombokPlugin extends PluginAdapter {
*/ */
@Override @Override
public boolean modelBaseRecordClassGenerated(TopLevelClass topLevelClass, IntrospectedTable introspectedTable) { public boolean modelBaseRecordClassGenerated(TopLevelClass topLevelClass, IntrospectedTable introspectedTable) {
// 添加 @Data 注解
topLevelClass.addAnnotation("@Data"); topLevelClass.addAnnotation("@Data");
topLevelClass.addImportedType(DATA_ANNOTATION); topLevelClass.addImportedType(DATA_ANNOTATION);
return true; return true;
@@ -1,4 +1,4 @@
package com.example.workutils.biz.mybatis.service.generator; package com.example.workutils.biz.mybatisgenerator.service.generator;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.mybatis.generator.api.MyBatisGenerator; import org.mybatis.generator.api.MyBatisGenerator;
@@ -45,7 +45,6 @@ public class MyBatisGeneratorService {
* @return 生成结果信息 * @return 生成结果信息
*/ */
public String generateByPattern(String pattern, boolean overwrite) throws Exception { public String generateByPattern(String pattern, boolean overwrite) throws Exception {
// 查询数据库中匹配通配符的表
List<String> matchedTables = queryTablesByPattern(pattern); List<String> matchedTables = queryTablesByPattern(pattern);
if (matchedTables.isEmpty()) { if (matchedTables.isEmpty()) {
@@ -70,11 +69,9 @@ public class MyBatisGeneratorService {
String username = props.getProperty("db_username"); String username = props.getProperty("db_username");
String password = props.getProperty("db_password"); String password = props.getProperty("db_password");
// 从URL中提取数据库名
String dbName = extractDatabaseName(url); String dbName = extractDatabaseName(url);
try (Connection conn = DriverManager.getConnection(url, username, password)) { try (Connection conn = DriverManager.getConnection(url, username, password)) {
// 查询匹配的表名
String sql = "SELECT TABLE_NAME FROM information_schema.TABLES WHERE TABLE_SCHEMA = ? AND TABLE_NAME LIKE ?"; String sql = "SELECT TABLE_NAME FROM information_schema.TABLES WHERE TABLE_SCHEMA = ? AND TABLE_NAME LIKE ?";
try (PreparedStatement ps = conn.prepareStatement(sql)) { try (PreparedStatement ps = conn.prepareStatement(sql)) {
ps.setString(1, dbName); ps.setString(1, dbName);
@@ -124,7 +121,6 @@ public class MyBatisGeneratorService {
* 从JDBC URL中提取数据库名 * 从JDBC URL中提取数据库名
*/ */
private String extractDatabaseName(String url) { private String extractDatabaseName(String url) {
// jdbc:mysql://localhost:3306/disburse?xxx -> disburse
int start = url.lastIndexOf('/'); int start = url.lastIndexOf('/');
int end = url.indexOf('?', start); int end = url.indexOf('?', start);
if (end == -1) { if (end == -1) {
@@ -187,14 +183,12 @@ public class MyBatisGeneratorService {
content = sb.toString(); content = sb.toString();
} }
// 移除原有的 table 元素
java.util.regex.Pattern tablePattern = java.util.regex.Pattern.compile( java.util.regex.Pattern tablePattern = java.util.regex.Pattern.compile(
"<table[^>]*/>|<table[^>]*>.*?</table>", "<table[^>]*/>|<table[^>]*>.*?</table>",
java.util.regex.Pattern.DOTALL java.util.regex.Pattern.DOTALL
); );
content = tablePattern.matcher(content).replaceAll(""); content = tablePattern.matcher(content).replaceAll("");
// 构建新的 table 元素
StringBuilder tableElements = new StringBuilder(); StringBuilder tableElements = new StringBuilder();
for (String tableName : tableNames) { for (String tableName : tableNames) {
tableElements.append(" <table schema=\"\" tableName=\"") tableElements.append(" <table schema=\"\" tableName=\"")
@@ -1,4 +1,4 @@
package com.example.workutils.biz.mybatis.service.generator; package com.example.workutils.biz.mybatisgenerator.service.generator;
import org.mybatis.generator.api.IntrospectedTable; import org.mybatis.generator.api.IntrospectedTable;
import org.mybatis.generator.api.PluginAdapter; import org.mybatis.generator.api.PluginAdapter;
@@ -24,31 +24,26 @@ public class SelectiveOnlyPlugin extends PluginAdapter {
@Override @Override
public boolean clientInsertMethodGenerated(Method method, Interface interfaze, IntrospectedTable introspectedTable) { public boolean clientInsertMethodGenerated(Method method, Interface interfaze, IntrospectedTable introspectedTable) {
// 禁用 insert(全字段插入)
return false; return false;
} }
@Override @Override
public boolean clientInsertSelectiveMethodGenerated(Method method, Interface interfaze, IntrospectedTable introspectedTable) { public boolean clientInsertSelectiveMethodGenerated(Method method, Interface interfaze, IntrospectedTable introspectedTable) {
// 保留 insertSelective
return true; return true;
} }
@Override @Override
public boolean clientUpdateByPrimaryKeyWithoutBLOBsMethodGenerated(Method method, Interface interfaze, IntrospectedTable introspectedTable) { public boolean clientUpdateByPrimaryKeyWithoutBLOBsMethodGenerated(Method method, Interface interfaze, IntrospectedTable introspectedTable) {
// 禁用 updateByPrimaryKey(全字段更新)
return false; return false;
} }
@Override @Override
public boolean clientUpdateByPrimaryKeySelectiveMethodGenerated(Method method, Interface interfaze, IntrospectedTable introspectedTable) { public boolean clientUpdateByPrimaryKeySelectiveMethodGenerated(Method method, Interface interfaze, IntrospectedTable introspectedTable) {
// 保留 updateByPrimaryKeySelective
return true; return true;
} }
@Override @Override
public boolean clientDeleteByPrimaryKeyMethodGenerated(Method method, Interface interfaze, IntrospectedTable introspectedTable) { public boolean clientDeleteByPrimaryKeyMethodGenerated(Method method, Interface interfaze, IntrospectedTable introspectedTable) {
// 禁用 deleteByPrimaryKey(根据主键删除)
return false; return false;
} }
@@ -56,19 +51,16 @@ public class SelectiveOnlyPlugin extends PluginAdapter {
@Override @Override
public boolean sqlMapInsertElementGenerated(XmlElement element, IntrospectedTable introspectedTable) { public boolean sqlMapInsertElementGenerated(XmlElement element, IntrospectedTable introspectedTable) {
// 禁用 insert XML元素(全字段插入)
return false; return false;
} }
@Override @Override
public boolean sqlMapUpdateByPrimaryKeyWithoutBLOBsElementGenerated(XmlElement element, IntrospectedTable introspectedTable) { public boolean sqlMapUpdateByPrimaryKeyWithoutBLOBsElementGenerated(XmlElement element, IntrospectedTable introspectedTable) {
// 禁用 updateByPrimaryKey XML元素(全字段更新)
return false; return false;
} }
@Override @Override
public boolean sqlMapDeleteByPrimaryKeyElementGenerated(XmlElement element, IntrospectedTable introspectedTable) { public boolean sqlMapDeleteByPrimaryKeyElementGenerated(XmlElement element, IntrospectedTable introspectedTable) {
// 禁用 deleteByPrimaryKey XML元素(根据主键删除)
return false; return false;
} }
} }
+132 -150
View File
@@ -38,65 +38,57 @@ workutils/
``` ```
src/main/java/com/example/workutils/ src/main/java/com/example/workutils/
├── WorkUtilsApplication.java # 应用启动入口 ├── WorkUtilsApplication.java # 应用启动入口
├── system/ # 系统框架层 ├── system/ # 系统框架层(平台规范定义 + 共享基础设施)
│ ├── ConsoleHelper.java # 控制台交互工具类(消除重复I/O代码)
│ ├── config/ │ ├── config/
│ │ └── WorkUtilsProperties.java # 全局配置属性类 │ │ └── WorkUtilsProperties.java # 全局配置属性类
│ ├── menu/ │ ├── support/ # 共享基础设施
│ │ └── MenuRunner.java # 交互式菜单运行器 │ │ ├── ConsoleHelper.java # 控制台交互工具类
│ └── tool/ │ │ ├── FileOperationService.java# 文件操作服务(读取/扫描/写入/路径管理)
│ ├── Tool.java # 工具策略接口 │ │ └── OutputService.java # 输出服务(CSV/Excel)
│ ├── AbstractTool.java # 工具基类(模板方法模式) │ └── tool/ # Tool 契约与注册中心
│ └── ToolRegistry.java # 工具注册中心 │ ├── Tool.java # 工具契约接口(所有 biz 模块必须实现)
└── biz/ # 业务模块层 │ └── ToolRegistry.java # 工具注册中心(主菜单循环 + 按命令分发)
├── git/ # Git操作业务模块 └── biz/ # 业务工具层(各模块是独立 Tool)
│ ├── config/ ├── batch/ # 批量处理工具
│ │ └── GitOptimizationConfig.java # Git性能优化配置 │ └── BatchTool.java # 批量检查入口(实现 Tool)
│ ├── menu/ ├── git/ # Git 操作工具
│ │ └── GitMenu.java # Git仓库健康检测菜单(仅交互逻辑) │ ├── GitTool.java # Git 工具入口(实现 Tool)
│ ├── model/ │ └── service/ # 服务实现层
│ │ └── GitCommandDTO.java # Git命令传输对象 │ ├── GitService.java # Git 服务接口
│ ├── service/ │ ├── GitServiceImpl.java # Git 服务实现
│ │ ├── GitCommandStrategy.java # Git命令策略接口 │ ├── config/
│ │ ├── GitService.java # Git服务接口 │ │ └── GitOptimizationConfig.java # Git 性能优化配置
│ │ └── impl/ │ ├── model/
│ │ ├── GitServiceImpl.java # Git服务实现 │ │ └── GitCommand.java # Git 命令传输对象
│ │ ├── GitStrategyFactory.java # Git策略工厂 │ └── internal/ # 内部实现(不对外暴露)
│ │ └── strategy/ │ ├── GitCommandController.java # Git 命令控制器(异步/中断)
│ │ ├── CheckBranchChangesStrategy.java # 检查分支变更策略 │ ├── GitCommandExecutor.java # Git 命令执行器(核心)
│ │ └── CheckoutAndPullStrategy.java # 切换并拉取策略 │ ├── GitRepositoryManager.java # Git 仓库管理器
│ └── util/ │ ├── GitResultCache.java # Git 结果缓存管理器
│ ├── GitCommandController.java # Git命令控制器(异步/中断) │ └── strategy/ # 策略模式实现
│ ├── GitCommandExecutor.java # Git命令执行器(核心) │ ├── GitCommandStrategy.java # 策略接口
│ ├── GitRepositoryManager.java # Git仓库管理器 │ ├── GitStrategyFactory.java # 策略工厂
│ └── GitResultCache.java # Git结果缓存管理器 │ ├── CheckBranchChangesStrategy.java
├── mybatis/ # MyBatis业务模块 │ └── CheckoutAndPullStrategy.java
│ ├── export/ ├── mybatisexport/ # MyBatis SQL导出工具(独立插件)
│ │ └── MyBatisExportService.java # MyBatis SQL导出服务 │ ├── MyBatisExportTool.java # SQL 导出入口(实现 Tool)
│ ├── 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/ │ └── service/
│ └── XMLMapperChecker.java # XML Mapper检查器(旧版,包路径异常) │ ├── MyBatisExportService.java # SQL 导出服务
├── output/ │ └── model/
│ ├── OutputService.java # 输出服务(CSV/Excel) │ └── MybatisTag.java # MyBatis 标签数据对象
│ └── menu/ ├── mybatisgenerator/ # MyBatis逆向工程工具(独立插件)
│ └── BatchMenu.java # 批量处理菜单(仅交互逻辑) │ ├── MyBatisGeneratorTool.java # 逆向工程入口(实现 Tool)
└── scanner/ # 扫描业务模块 │ └── service/generator/
├── config/ │ ├── MyBatisGeneratorService.java # 逆向工程服务
│ └── ScanConfigBO.java # 扫描配置对象 │ ├── CustomCommentGenerator.java # 自定义注释生成器
├── menu/ │ ├── LombokPlugin.java # Lombok 插件(@Data)
│ └── ScanMenu.java # 扫描功能菜单(仅交互逻辑) │ └── SelectiveOnlyPlugin.java # 只保留 Selective 方法插件
└── service/ └── scanner/ # 扫描工具
├── FileOperationService.java # 文件操作服务 ├── ScannerTool.java # 扫描工具入口(实现 Tool)
└── ScanService.java # 扫描服务 └── service/ # 服务实现层
├── ScannerService.java # 扫描服务
└── config/
└── ScanConfig.java # 扫描配置
``` ```
--- ---
@@ -108,99 +100,92 @@ src/main/java/com/example/workutils/
#### `WorkUtilsApplication.java` #### `WorkUtilsApplication.java`
- **作用**: Spring Boot 应用启动类,实现 `CommandLineRunner` - **作用**: Spring Boot 应用启动类,实现 `CommandLineRunner`
- **功能**: - **功能**:
- 支持交互式菜单模式(无参数启动) - 支持交互式菜单模式(无参数启动),委托 `ToolRegistry.runMainMenu()`
- 支持命令行模式,通过 `ToolRegistry.getToolByCommand()` 按命令名分发到对应 Tool - 支持命令行模式,通过 `ToolRegistry.getToolByCommand()` 按命令名分发
- 不依赖任何具体业务 Service,完全解耦 - 不依赖任何具体业务 Service,完全解耦
--- ---
### 3.2 系统框架层(`system/`) ### 3.2 系统框架层(`system/`)
#### `config/WorkUtilsProperties.java` #### `system/tool/Tool.java`
- **作用**: 工具契约接口,所有 biz 工具模块必须实现此接口
- **核心方法**: `getId()`、`getName()`、`getMenuOptions()`、`execute()`(模板方法,含默认实现)、`getCommandName()`(命令行模式)、`executeCommand()`(命令行模式执行)
#### `system/tool/ToolRegistry.java`
- **作用**: 工具注册中心,Spring 自动发现 `Tool` Bean,提供主菜单循环
- **功能**: 根据配置过滤启用/禁用工具,支持白名单(enabled)和黑名单(disabled)模式,维护按命令名的索引,支持命令行模式按命令名分发
#### `system/support/ConsoleHelper.java`
- **作用**: 控制台交互工具类(静态方法),统一控制台 I/O
#### `system/support/FileOperationService.java`
- **作用**: 文件操作服务,提供文件读取、扫描、写入、项目路径管理等基础能力
#### `system/support/OutputService.java`
- **作用**: 输出服务,负责将数据输出为 CSV(OpenCSV)或 Excel(EasyExcel)格式,支持单Sheet/多Sheet、追加写入等
#### `system/config/WorkUtilsProperties.java`
- **作用**: 全局配置属性类,绑定 `application.yml` 中 `workutils` 前缀的配置 - **作用**: 全局配置属性类,绑定 `application.yml` 中 `workutils` 前缀的配置
- **功能**: - **功能**: 管理基础目录、配置目录、导出目录路径,提供带日期时间戳的导出文件路径生成,管理工具启用/禁用白名单和黑名单
- 管理基础目录、配置目录、导出目录路径
- 提供带日期时间戳的导出文件路径生成
- 管理工具启用/禁用白名单和黑名单
#### `tool/Tool.java`
- **作用**: 工具策略接口,所有可插拔工具需实现此接口
- **核心方法**: `getId()`、`getName()`、`getMenuOptions()`、`execute()`、`getCommandName()`(命令行模式命令名)、`executeCommand()`(命令行模式执行)
#### `tool/AbstractTool.java`
- **作用**: 工具基类,使用模板方法模式
- **功能**: 提供标准菜单交互循环(显示菜单→读取选择→处理选择→循环),子类只需实现 `handleChoice()`
- **控制台I/O**: 委托给 `ConsoleHelper`,子类通过 `printMenuTitle()`、`displayMenu()` 等 protected 方法间接调用
#### `ConsoleHelper.java`
- **作用**: 控制台交互工具类(静态方法)
- **功能**: 统一 `MenuRunner` 和 `AbstractTool` 中重复的控制台 I/O 方法,消除代码重复
#### `tool/ToolRegistry.java`
- **作用**: 工具注册中心,Spring 自动发现 `Tool` Bean
- **功能**: 根据配置过滤启用/禁用工具,支持白名单(enabled)和黑名单(disabled)模式,同时维护按命令名(`getCommandName()`)的索引,支持命令行模式按命令名分发
--- ---
### 3.3 菜单层(`system/menu/`) ### 3.3 业务工具层(`biz/`)
#### `MenuRunner.java` > **架构约定**: 每个 biz 模块的 Tool 类(如 `GitTool.java`)放在模块根目录作为入口,所有服务实现及附属文件(config/model/internal/generator)收在 `service/` 子包下,内部细节用 `internal/` 隔离。
- **作用**: 交互式主菜单运行器
- **功能**: 从 `ToolRegistry` 动态构建主菜单,无需硬编码 Menu 引用
> **重构说明**: 原先的 `menu/handler/` 下的 Handler 类已全部移除。菜单交互类已分散到各业务模块的 `menu/` 子包中,统一命名为 `XxxMenu`,仅负责菜单展示和用户交互,业务逻辑委托给对应 Service。 #### 3.3.1 扫描工具(`biz/scanner/`)
---
### 3.4 业务模块(`biz/`)
#### 3.4.1 Git 操作模块(`biz/git/`)
| 文件 | 作用 | | 文件 | 作用 |
|------|------| |------|------|
| `menu/GitMenu.java` | **Git 菜单类**(仅交互),显示菜单、接收用户输入、委托 GitService 执行业务逻辑 | | `ScannerTool.java` | 扫描工具入口(实现 Tool),负责菜单交互,委托 ScannerService 执行业务逻辑 |
| `GitOptimizationConfig.java` | Git 性能优化配置类,管理超时、线程池、缓存、批处理、Fetch、网络等配置参数 | | `service/ScannerService.java` | 扫描服务,支持关键词扫描、Redis Key 扫描、Dubbo 接口扫描三种类型,支持并发多项目扫描 |
| `GitCommandDTO.java` | Git 命令传输对象,定义命令类型枚举(CHECK_BRANCH_CHANGES、CHECKOUT_AND_PULL 等6种) | | `service/config/ScanConfig.java` | 扫描配置,定义文件扩展名、排除目录、最大文件大小等参数 |
| `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/`) #### 3.3.2a MyBatis SQL导出工具(`biz/mybatisexport/`)
| 文件 | 作用 | | 文件 | 作用 |
|------|------| |------|------|
| `menu/MyBatisMenu.java` | **MyBatis SQL 导出菜单**(仅交互),显示导出选项、接收用户输入、委托 MyBatisExportService 执行 | | `MyBatisExportTool.java` | SQL 导出工具入口(实现 Tool),负责菜单交互,委托 MyBatisExportService 执行 |
| `menu/MyBatisGeneratorMenu.java` | **MyBatis 逆向工程菜单**(仅交互),显示生成选项、接收用户输入、委托 MyBatisGeneratorService 执行 | | `service/MyBatisExportService.java` | SQL 导出核心服务,从 XML 文件中提取 select/insert/update/delete 标签,支持按表名/关键字/标签ID 过滤导出为 CSV |
| `MyBatisExportService.java` | **MyBatis SQL 导出核心服务**,从 XML 文件中提取 select/insert/update/delete 标签,支持按表名、关键字、标签ID 过滤导出为 CSV | | `service/model/MybatisTag.java` | MyBatis 标签数据对象,封装 tagId、tagName、parameterType、resultMap、namespace |
| `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/`) #### 3.3.2b MyBatis逆向工程工具(`biz/mybatisgenerator/`)
| 文件 | 作用 | | 文件 | 作用 |
|------|------| |------|------|
| `menu/BatchMenu.java` | **批量处理菜单**(仅交互),显示批量检查选项、接收用户输入、委托各 Service 执行 | | `MyBatisGeneratorTool.java` | 逆向工程工具入口(实现 Tool),负责菜单交互,委托 MyBatisGeneratorService 执行 |
| `OutputService.java` | 输出服务,负责将数据输出为 CSV(OpenCSV)或 Excel(EasyExcel)格式,支持单Sheet/多Sheet、追加写入等 | | `service/generator/MyBatisGeneratorService.java` | MyBatis 逆向工程服务,根据数据库表生成 PO、Mapper 接口、XML 映射文件 |
| `service/generator/CustomCommentGenerator.java` | 自定义注释生成器,生成简洁中文注释 |
| `service/generator/LombokPlugin.java` | Lombok 插件,为 PO 类添加 `@Data` 注解 |
| `service/generator/SelectiveOnlyPlugin.java` | 自定义插件,只保留 `insertSelective` 和 `updateByPrimaryKeySelective` |
#### 3.4.4 扫描模块(`biz/scanner/`) > **设计说明**: 原 `biz/mybatis/` 已按工具维度拆分为 `mybatisexport` 和 `mybatisgenerator` 两个独立包,为后续**插件化设计**做准备——每个工具将独立打包、独立加载。
#### 3.3.3 Git 工具(`biz/git/`)
| 文件 | 作用 | | 文件 | 作用 |
|------|------| |------|------|
| `menu/ScanMenu.java` | **扫描功能菜单**(仅交互),显示扫描选项、接收用户输入、委托 ScanService 执行 | | `GitTool.java` | Git 工具入口(实现 Tool),负责菜单交互,委托 GitService 执行 |
| `ScanConfigBO.java` | 扫描配置对象,定义文件扩展名、排除目录、最大文件大小等扫描参数 | | `service/GitService.java` | Git 服务接口,定义分支变更检查、切换拉取、健康检测、修复仓库等方法 |
| `FileOperationService.java` | 文件操作服务,提供文件读取、扫描、写入、项目路径管理等基础能力 | | `service/GitServiceImpl.java` | Git 服务实现,协调各策略执行仓库健康检测和修复逻辑 |
| `ScanService.java` | 扫描服务,支持关键词扫描、Redis Key 扫描、Dubbo 接口扫描三种类型,支持并发多项目扫描 | | `service/config/GitOptimizationConfig.java` | Git 性能优化配置,管理超时、线程池、缓存、批处理、Fetch、网络等参数 |
| `service/model/GitCommand.java` | Git 命令传输对象,定义命令类型枚举(CHECK_BRANCH_CHANGES、CHECKOUT_AND_PULL 等6种) |
| `service/internal/GitCommandExecutor.java` | **核心执行器**,封装原生 git 命令执行(跨平台),提供超时控制、并发线程池、命令批处理 |
| `service/internal/GitCommandController.java` | Git 命令控制器,管理命令的异步执行、跳过、中断 |
| `service/internal/GitRepositoryManager.java` | Git 仓库管理器,提供仓库发现、分支操作、批量操作等高级封装 |
| `service/internal/GitResultCache.java` | Git 结果缓存管理器,缓存仓库信息/分支信息/提交ID,减少重复 git 命令 |
| `service/internal/strategy/GitCommandStrategy.java` | Git 命令策略接口 |
| `service/internal/strategy/GitStrategyFactory.java` | Git 策略工厂,注册和管理所有策略实现 |
| `service/internal/strategy/CheckBranchChangesStrategy.java` | 分支变更检查策略,比较两个分支的差异 |
| `service/internal/strategy/CheckoutAndPullStrategy.java` | 切换并拉取策略,批量切换分支并拉取最新代码 |
#### 3.3.4 批量工具(`biz/batch/`)
| 文件 | 作用 |
|------|------|
| `BatchTool.java` | 批量处理工具入口(实现 Tool),显示批量检查选项,委托各 Service 执行 |
--- ---
@@ -230,16 +215,16 @@ src/main/resources/
| 模式/特点 | 应用位置 | 说明 | | 模式/特点 | 应用位置 | 说明 |
|-----------|---------|------| |-----------|---------|------|
| **策略模式** | `Tool` + `AbstractTool` + Menu 实现 | 各工具通过实现 `Tool` 接口注册,可插拔扩展,支持交互和命令行双模式 | | **策略模式** | `Tool` 接口 + 各 biz Tool 实现 | 各工具通过实现 `Tool` 接口注册到 `ToolRegistry`,可插拔扩展,支持交互和命令行双模式 |
| **模板方法模式** | `AbstractTool` | 定义菜单交互骨架,子类实现 `handleChoice()` |
| **策略模式** | `GitCommandStrategy` + 各 Strategy 实现 | Git 命令执行策略,`GitStrategyFactory` 管理注册 | | **策略模式** | `GitCommandStrategy` + 各 Strategy 实现 | Git 命令执行策略,`GitStrategyFactory` 管理注册 |
| **工厂模式** | `ToolRegistry`、`GitStrategyFactory` | 自动发现和注册 Bean | | **工厂模式** | `ToolRegistry`、`GitStrategyFactory` | Spring 自动发现和注入 Bean |
| **命令模式** | `GitCommandDTO` + `GitCommandController` | 封装 Git 命令的异步执行、中断、跳过 | | **命令模式** | `GitCommand` + `GitCommandController` | 封装 Git 命令的异步执行、中断、跳过 |
| **缓存模式** | `GitResultCache` | 缓存 Git 查询结果,减少重复命令执行 | | **缓存模式** | `GitResultCache` | 缓存 Git 查询结果,减少重复命令执行 |
| **并发处理** | `GitCommandExecutor`、`ScanService` | 线程池并发执行 Git 命令和多项目扫描 | | **并发处理** | `GitCommandExecutor`、`ScannerService` | 线程池并发执行 Git 命令和多项目扫描 |
| **过滤器模式** | `MyBatisExportService` 内部类 | `SqlFilter` 接口实现表名/关键字/标签ID 过滤 | | **过滤器模式** | `MyBatisExportService` 内部类 | `SqlFilter` 接口实现表名/关键字/标签ID 过滤 |
| **模板回调** | `FileOperationService.scanFilesRecursively` | 使用 `SimpleFileVisitor` 实现文件遍历回调 | | **模板回调** | `FileOperationService.scanFilesRecursively` | 使用 `SimpleFileVisitor` 实现文件遍历回调 |
| **工具类提取** | `ConsoleHelper` | 提取 `MenuRunner` 和 `AbstractTool` 中的重复控制台 I/O 代码 | | **分层架构** | `system/` vs `biz/` | system 定义平台契约与共享基础设施,biz 实现具体工具 |
| **内部隔离** | `biz/*/service/internal/` | 内部实现类用 `internal/` 隔离,不对外暴露 |
--- ---
@@ -247,24 +232,25 @@ src/main/resources/
``` ```
WorkUtilsApplication (入口) WorkUtilsApplication (入口)
├── 交互模式 → MenuRunner ├── 交互模式 → ToolRegistry.runMainMenu()
│ └── ToolRegistry.getEnabledTools() │ └── ToolRegistry.getEnabledTools()
│ ├── GitMenu ────────────────→ GitService │ ├── ScannerTool ────────────→ ScannerService
│ ├── MyBatisMenu ────────────→ MyBatisExportService │ ├── MyBatisExportTool ──────→ MyBatisExportService
│ ├── MyBatisGeneratorMenu ───→ MyBatisGeneratorService │ ├── MyBatisGeneratorTool ───→ MyBatisGeneratorService
│ ├── ScanMenu ───────────────→ ScanService │ ├── GitTool ────────────────→ GitService → GitStrategyFactory
│ └── BatchMenu ──────────────→ ScanService + MyBatisExportService │ └── BatchTool ──────────────→ ScannerService + MyBatisExportService
│ │
└── 命令行模式 → ToolRegistry.getToolByCommand(command) └── 命令行模式 → ToolRegistry.getToolByCommand(command)
├── "sql" → MyBatisMenu.executeCommand(args) ├── "scan" → ScannerTool.executeCommand(args)
├── "scan" → ScanMenu.executeCommand(args) ├── "sql" → MyBatisExportTool.executeCommand(args)
└── "batch" → BatchMenu.executeCommand(args) ├── "batch" → BatchTool.executeCommand(args)
(启动类不依赖任何具体业务Service) └── "git" → GitTool.executeCommand(args)
(启动类不依赖任何具体业务 Service)
核心依赖链: 核心依赖链:
ScannerService → FileOperationService + OutputService
MyBatisExportService → FileOperationService + OutputService MyBatisExportService → FileOperationService + OutputService
ScanService → FileOperationService + OutputService GitService → FileOperationService + GitCommandExecutor
GitServiceImpl → FileOperationService + GitCommandExecutor
OutputService → FileOperationService + WorkUtilsProperties OutputService → FileOperationService + WorkUtilsProperties
FileOperationService → WorkUtilsProperties FileOperationService → WorkUtilsProperties
``` ```
@@ -273,21 +259,17 @@ WorkUtilsApplication (入口)
## 七、问题与改进建议 ## 七、问题与改进建议
### 7.1 发现的问题 ### 7.1 已知问题
| 问题 | 位置 | 说明 | | 问题 | 位置 | 说明 |
|------|------|------| |------|------|------|
| 包路径不一致 | `XMLMapperChecker.java` | 实际包路径 `com.example.workutils.service`,但位于 `biz/mybatis/service/` 目录下 | | 配置文件硬编码 | `mybatis-generator.properties` | 包含明文密码 |
| 未使用文件 | `XMLMapperChecker.java` | 代码中没有任何地方引用此类 |
| 配置文件硬编码 | `mybatis-generator.properties` | 包含明文密码 `1Qaz@4772` |
| pom.xml 重复依赖 | `fastjson` 1.2.83 和 2.0.57 | 两个版本的 fastjson 同时存在 | | 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 | | 项目说明版本不匹配 | `项目说明.md` | 描述为 Spring Boot 3.2.3 + Java 21,实际为 Spring Boot 2.7.18 + Java 8 |
### 7.2 重构建议 ### 7.2 重构建议
1. **修复 `XMLMapperChecker` 包路径**,或将其删除(未被引用) 1. **统一 fastjson 版本**,建议只保留 2.0.57
2. **统一 fastjson 版本**,建议只保留 2.0.57 2. **将数据库密码移到外部配置文件**或使用环境变量
3. **将数据库密码移到外部配置文件**或使用环境变量 3. **更新 `项目说明.md`** 使其与实际技术栈一致
4. **更新 `项目说明.md`** 使其与实际技术栈一致 4. **增加单元测试**,目前无测试代码
5. **考虑提取公共的 CSV 操作到 `OutputService`**,减少 `MyBatisExportService` 中的 CSV 相关代码
6. **增加单元测试**,目前无测试代码