代码优化
This commit is contained in:
@@ -1,8 +1,7 @@
|
||||
package com.example.workutils;
|
||||
|
||||
import com.example.workutils.system.menu.MenuRunner;
|
||||
import com.example.workutils.system.tool.Tool;
|
||||
import com.example.workutils.system.tool.ToolRegistry;
|
||||
import com.example.workutils.system.tool.Registry;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.boot.CommandLineRunner;
|
||||
import org.springframework.boot.SpringApplication;
|
||||
@@ -17,12 +16,10 @@ import java.util.Scanner;
|
||||
@Slf4j
|
||||
public class WorkUtilsApplication implements CommandLineRunner {
|
||||
|
||||
private final MenuRunner menuRunner;
|
||||
private final ToolRegistry toolRegistry;
|
||||
private final Registry registry;
|
||||
|
||||
public WorkUtilsApplication(MenuRunner menuRunner, ToolRegistry toolRegistry) {
|
||||
this.menuRunner = menuRunner;
|
||||
this.toolRegistry = toolRegistry;
|
||||
public WorkUtilsApplication(Registry registry) {
|
||||
this.registry = registry;
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
@@ -40,7 +37,7 @@ public class WorkUtilsApplication implements CommandLineRunner {
|
||||
|
||||
private void showInteractiveMenu() {
|
||||
Scanner scanner = new Scanner(System.in);
|
||||
menuRunner.run(scanner);
|
||||
registry.runMainMenu(scanner);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -50,7 +47,7 @@ public class WorkUtilsApplication implements CommandLineRunner {
|
||||
private void processCommand(String... args) throws Exception {
|
||||
String command = args[0].toLowerCase();
|
||||
|
||||
Optional<Tool> toolOpt = toolRegistry.getToolByCommand(command);
|
||||
Optional<Tool> toolOpt = registry.getToolByCommand(command);
|
||||
if (toolOpt.isPresent()) {
|
||||
Tool tool = toolOpt.get();
|
||||
try {
|
||||
|
||||
@@ -2,7 +2,7 @@ package com.example.workutils.biz.git.menu;
|
||||
|
||||
import com.example.workutils.biz.git.service.GitService;
|
||||
import com.example.workutils.biz.git.util.GitCommandExecutor;
|
||||
import com.example.workutils.system.tool.AbstractTool;
|
||||
import com.example.workutils.system.tool.Tool;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Component;
|
||||
@@ -19,7 +19,7 @@ import java.util.stream.Collectors;
|
||||
@Slf4j
|
||||
@Component
|
||||
@RequiredArgsConstructor
|
||||
public class GitMenu extends AbstractTool {
|
||||
public class GitMenu implements Tool {
|
||||
|
||||
private static final String[] MENU_OPTIONS = {
|
||||
"1. 检测所有仓库健康状态",
|
||||
@@ -45,7 +45,7 @@ public class GitMenu extends AbstractTool {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void handleChoice(int choice, Scanner scanner) throws Exception {
|
||||
public void handleChoice(int choice, Scanner scanner) throws Exception {
|
||||
switch (choice) {
|
||||
case 1:
|
||||
checkAllReposHealth(scanner);
|
||||
@@ -61,13 +61,13 @@ public class GitMenu extends AbstractTool {
|
||||
|
||||
private void checkAllReposHealth(Scanner scanner) {
|
||||
printMenuTitle("开始检测所有仓库");
|
||||
info("开始检测所有仓库健康状态");
|
||||
log.info("开始检测所有仓库健康状态");
|
||||
|
||||
List<GitCommandExecutor.RepoHealthResult> results = gitService.checkCorruptedRepos(scanner);
|
||||
|
||||
if (results.isEmpty()) {
|
||||
System.out.println("所有仓库状态正常!");
|
||||
info("所有仓库状态正常");
|
||||
log.info("所有仓库状态正常");
|
||||
} else {
|
||||
System.out.println("\n发现 " + results.size() + " 个损坏的仓库:");
|
||||
for (int i = 0; i < results.size(); i++) {
|
||||
@@ -76,7 +76,7 @@ public class GitMenu extends AbstractTool {
|
||||
extractProjectName(result.getRepoPath()),
|
||||
result.getCorruptionReason());
|
||||
}
|
||||
info("检测完成,发现 {} 个损坏仓库", results.size());
|
||||
log.info("检测完成,发现 {} 个损坏仓库", results.size());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -108,11 +108,11 @@ public class GitMenu extends AbstractTool {
|
||||
String confirm = scanner.nextLine().trim();
|
||||
if (!"y".equalsIgnoreCase(confirm)) {
|
||||
System.out.println("已取消修复操作。");
|
||||
info("用户取消修复操作");
|
||||
log.info("用户取消修复操作");
|
||||
return;
|
||||
}
|
||||
|
||||
info("开始修复 {} 个仓库", selectedIndices.size());
|
||||
log.info("开始修复 {} 个仓库", selectedIndices.size());
|
||||
int successCount = 0;
|
||||
int failCount = 0;
|
||||
for (Integer index : selectedIndices) {
|
||||
@@ -132,7 +132,7 @@ public class GitMenu extends AbstractTool {
|
||||
printMenuTitle("修复完成");
|
||||
System.out.println("成功: " + successCount);
|
||||
System.out.println("失败: " + failCount);
|
||||
info("修复完成,成功: {},失败: {}", successCount, failCount);
|
||||
log.info("修复完成,成功: {},失败: {}", successCount, failCount);
|
||||
}
|
||||
|
||||
private List<Integer> parseSelectedIndices(String input, int repoCount) {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package com.example.workutils.biz.mybatis.menu;
|
||||
|
||||
import com.example.workutils.biz.mybatis.generator.MyBatisGeneratorService;
|
||||
import com.example.workutils.system.tool.AbstractTool;
|
||||
import com.example.workutils.system.tool.Tool;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Component;
|
||||
@@ -17,7 +17,7 @@ import java.util.Scanner;
|
||||
@Slf4j
|
||||
@Component
|
||||
@RequiredArgsConstructor
|
||||
public class MyBatisGeneratorMenu extends AbstractTool {
|
||||
public class MyBatisGeneratorMenu implements Tool {
|
||||
|
||||
private static final String[] MENU_OPTIONS = {
|
||||
"1. 根据表名生成(单表)",
|
||||
@@ -46,7 +46,7 @@ public class MyBatisGeneratorMenu extends AbstractTool {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void handleChoice(int choice, Scanner scanner) throws Exception {
|
||||
public void handleChoice(int choice, Scanner scanner) throws Exception {
|
||||
switch (choice) {
|
||||
case 1:
|
||||
generateBySingleTable(scanner);
|
||||
@@ -78,7 +78,7 @@ public class MyBatisGeneratorMenu extends AbstractTool {
|
||||
return;
|
||||
}
|
||||
|
||||
info("开始生成表 [{}] 的Mapper文件", tableName);
|
||||
log.info("开始生成表 [{}] 的Mapper文件", tableName);
|
||||
String result = generatorService.generateByTableNames(Arrays.asList(tableName), true);
|
||||
System.out.println(result);
|
||||
printSuccess("生成完成");
|
||||
@@ -98,7 +98,7 @@ public class MyBatisGeneratorMenu extends AbstractTool {
|
||||
tableNames.set(i, tableNames.get(i).trim());
|
||||
}
|
||||
|
||||
info("开始生成 {} 个表的Mapper文件", tableNames.size());
|
||||
log.info("开始生成 {} 个表的Mapper文件", tableNames.size());
|
||||
String result = generatorService.generateByTableNames(tableNames, true);
|
||||
System.out.println(result);
|
||||
printSuccess("生成完成");
|
||||
@@ -131,7 +131,7 @@ public class MyBatisGeneratorMenu extends AbstractTool {
|
||||
return;
|
||||
}
|
||||
|
||||
info("开始根据通配符 [{}] 生成 {} 张表的Mapper文件", pattern, matchedTables.size());
|
||||
log.info("开始根据通配符 [{}] 生成 {} 张表的Mapper文件", pattern, matchedTables.size());
|
||||
String result = generatorService.generateByTableNames(matchedTables, true);
|
||||
System.out.println(result);
|
||||
printSuccess("生成完成");
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package com.example.workutils.biz.mybatis.menu;
|
||||
|
||||
import com.example.workutils.biz.mybatis.export.MyBatisExportService;
|
||||
import com.example.workutils.system.tool.AbstractTool;
|
||||
import com.example.workutils.system.tool.Tool;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Component;
|
||||
@@ -16,7 +16,7 @@ import java.util.Scanner;
|
||||
@Slf4j
|
||||
@Component
|
||||
@RequiredArgsConstructor
|
||||
public class MyBatisMenu extends AbstractTool {
|
||||
public class MyBatisMenu implements Tool {
|
||||
|
||||
private static final String[] MENU_OPTIONS = {
|
||||
"1. 导出所有SQL",
|
||||
@@ -85,7 +85,7 @@ public class MyBatisMenu extends AbstractTool {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void handleChoice(int choice, Scanner scanner) throws Exception {
|
||||
public void handleChoice(int choice, Scanner scanner) throws Exception {
|
||||
switch (choice) {
|
||||
case 1:
|
||||
exportAllSql();
|
||||
@@ -110,7 +110,7 @@ public class MyBatisMenu extends AbstractTool {
|
||||
|
||||
private void exportAllSql() throws Exception {
|
||||
printMenuTitle("导出所有SQL");
|
||||
info("开始导出所有SQL");
|
||||
log.info("开始导出所有SQL");
|
||||
myBatisExportService.exportSQL();
|
||||
printSuccess("导出所有SQL");
|
||||
}
|
||||
@@ -122,7 +122,7 @@ public class MyBatisMenu extends AbstractTool {
|
||||
System.out.println("表名不能为空");
|
||||
return;
|
||||
}
|
||||
info("按表名导出SQL: {}", tableName);
|
||||
log.info("按表名导出SQL: {}", tableName);
|
||||
myBatisExportService.exportSQLByTable(tableName);
|
||||
printSuccess("按表名导出SQL");
|
||||
}
|
||||
@@ -134,7 +134,7 @@ public class MyBatisMenu extends AbstractTool {
|
||||
System.out.println("表名不能为空");
|
||||
return;
|
||||
}
|
||||
info("按多个表名导出SQL: {}", tableNames);
|
||||
log.info("按多个表名导出SQL: {}", tableNames);
|
||||
myBatisExportService.exportSQLByTables(Arrays.asList(tableNames.split(",")));
|
||||
printSuccess("按多个表名导出SQL");
|
||||
}
|
||||
@@ -146,7 +146,7 @@ public class MyBatisMenu extends AbstractTool {
|
||||
System.out.println("关键字不能为空");
|
||||
return;
|
||||
}
|
||||
info("按关键字导出SQL: {}", keyword);
|
||||
log.info("按关键字导出SQL: {}", keyword);
|
||||
myBatisExportService.exportSQLByKeyword(keyword);
|
||||
printSuccess("按关键字导出SQL");
|
||||
}
|
||||
@@ -158,7 +158,7 @@ public class MyBatisMenu extends AbstractTool {
|
||||
System.out.println("标签ID不能为空");
|
||||
return;
|
||||
}
|
||||
info("按标签ID导出SQL: {}", tagId);
|
||||
log.info("按标签ID导出SQL: {}", tagId);
|
||||
myBatisExportService.exportSQLByTagId(tagId);
|
||||
printSuccess("按标签ID导出SQL");
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@ package com.example.workutils.biz.output.menu;
|
||||
|
||||
import com.example.workutils.biz.mybatis.export.MyBatisExportService;
|
||||
import com.example.workutils.biz.scanner.service.ScanService;
|
||||
import com.example.workutils.system.tool.AbstractTool;
|
||||
import com.example.workutils.system.tool.Tool;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Component;
|
||||
@@ -18,7 +18,7 @@ import java.util.Scanner;
|
||||
@Slf4j
|
||||
@Component
|
||||
@RequiredArgsConstructor
|
||||
public class BatchMenu extends AbstractTool {
|
||||
public class BatchMenu implements Tool {
|
||||
|
||||
@FunctionalInterface
|
||||
public interface ExceptionRunnable {
|
||||
@@ -63,13 +63,13 @@ public class BatchMenu extends AbstractTool {
|
||||
|
||||
@Override
|
||||
public void executeCommand(String... args) throws Exception {
|
||||
info("命令行模式: 开始执行所有检查");
|
||||
log.info("命令行模式: 开始执行所有检查");
|
||||
executeAllChecks();
|
||||
System.out.println("批量处理完成!");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void handleChoice(int choice, Scanner scanner) throws Exception {
|
||||
public void handleChoice(int choice, Scanner scanner) throws Exception {
|
||||
switch (choice) {
|
||||
case 1:
|
||||
executeAllChecks();
|
||||
@@ -85,7 +85,7 @@ public class BatchMenu extends AbstractTool {
|
||||
|
||||
private void executeAllChecks() throws Exception {
|
||||
printMenuTitle("执行所有检查");
|
||||
info("开始执行所有检查");
|
||||
log.info("开始执行所有检查");
|
||||
|
||||
executeStep("1. 导出SQL...", () -> myBatisExportService.exportSQL());
|
||||
executeStep("2. 扫描Dubbo接口...",
|
||||
@@ -94,7 +94,7 @@ public class BatchMenu extends AbstractTool {
|
||||
() -> scanService.scanRedisKeysWithDefaultName("redis\\.opsFor"));
|
||||
|
||||
printSuccess("所有检查");
|
||||
info("所有检查执行完成");
|
||||
log.info("所有检查执行完成");
|
||||
}
|
||||
|
||||
private void executeCustomChecks(Scanner scanner) throws Exception {
|
||||
@@ -105,7 +105,7 @@ public class BatchMenu extends AbstractTool {
|
||||
String choices = scanner.nextLine().trim();
|
||||
List<String> choiceList = parseCommaSeparatedInput(choices);
|
||||
|
||||
info("用户选择执行检查项: {}", choiceList);
|
||||
log.info("用户选择执行检查项: {}", choiceList);
|
||||
|
||||
for (String choice : choiceList) {
|
||||
try {
|
||||
@@ -132,7 +132,7 @@ public class BatchMenu extends AbstractTool {
|
||||
break;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
error("执行检查项失败: " + choice, e);
|
||||
log.error("执行检查项失败: " + choice, e);
|
||||
System.out.println("检查项 " + choice + " 执行失败: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package com.example.workutils.biz.scanner.menu;
|
||||
|
||||
import com.example.workutils.biz.scanner.service.ScanService;
|
||||
import com.example.workutils.system.tool.AbstractTool;
|
||||
import com.example.workutils.system.tool.Tool;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Component;
|
||||
@@ -15,7 +15,7 @@ import java.util.Scanner;
|
||||
@Slf4j
|
||||
@Component
|
||||
@RequiredArgsConstructor
|
||||
public class ScanMenu extends AbstractTool {
|
||||
public class ScanMenu implements Tool {
|
||||
|
||||
private static final String[] MENU_OPTIONS = {
|
||||
"1. 关键词扫描",
|
||||
@@ -75,7 +75,7 @@ public class ScanMenu extends AbstractTool {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void handleChoice(int choice, Scanner scanner) throws Exception {
|
||||
public void handleChoice(int choice, Scanner scanner) throws Exception {
|
||||
switch (choice) {
|
||||
case 1:
|
||||
scanByKeyword(scanner);
|
||||
@@ -88,7 +88,7 @@ public class ScanMenu extends AbstractTool {
|
||||
|
||||
private void scanByKeyword(Scanner scanner) throws Exception {
|
||||
printMenuTitle("关键词扫描");
|
||||
info("开始关键词扫描");
|
||||
log.info("开始关键词扫描");
|
||||
|
||||
System.out.print("请输入关键词: ");
|
||||
String keyword = scanner.nextLine().trim();
|
||||
@@ -98,7 +98,7 @@ public class ScanMenu extends AbstractTool {
|
||||
return;
|
||||
}
|
||||
|
||||
info("扫描关键词: {}", keyword);
|
||||
log.info("扫描关键词: {}", keyword);
|
||||
scanService.scanKeywordsWithDefaultName(keyword);
|
||||
|
||||
printSuccess("关键词扫描");
|
||||
|
||||
@@ -1,82 +0,0 @@
|
||||
package com.example.workutils.system.menu;
|
||||
|
||||
import com.example.workutils.system.ConsoleHelper;
|
||||
import com.example.workutils.system.tool.Tool;
|
||||
import com.example.workutils.system.tool.ToolRegistry;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Scanner;
|
||||
|
||||
/**
|
||||
* 菜单运行器
|
||||
* 从ToolRegistry动态构建主菜单,无需硬编码Menu引用
|
||||
*/
|
||||
@Slf4j
|
||||
@Component
|
||||
public class MenuRunner {
|
||||
|
||||
private static final int EXIT_CODE = 0;
|
||||
|
||||
private final ToolRegistry toolRegistry;
|
||||
|
||||
public MenuRunner(ToolRegistry toolRegistry) {
|
||||
this.toolRegistry = toolRegistry;
|
||||
}
|
||||
|
||||
/**
|
||||
* 运行主菜单循环
|
||||
*/
|
||||
public void run(Scanner scanner) {
|
||||
log.info("启动主菜单");
|
||||
while (true) {
|
||||
ConsoleHelper.printMenuTitle("主菜单");
|
||||
displayMainMenu();
|
||||
|
||||
int choice = ConsoleHelper.readChoice(scanner);
|
||||
scanner.nextLine();
|
||||
|
||||
if (choice == EXIT_CODE) {
|
||||
log.info("用户退出系统");
|
||||
System.out.println("感谢使用,再见!");
|
||||
break;
|
||||
}
|
||||
|
||||
handleChoice(choice, scanner);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 动态构建主菜单
|
||||
*/
|
||||
private void displayMainMenu() {
|
||||
System.out.println("请选择操作:");
|
||||
List<Tool> tools = toolRegistry.getEnabledTools();
|
||||
for (int i = 0; i < tools.size(); i++) {
|
||||
System.out.println((i + 1) + ". " + tools.get(i).getName());
|
||||
}
|
||||
System.out.println(EXIT_CODE + ". 退出系统");
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理用户选择,工具隔离
|
||||
* 单个工具异常不影响平台和其他工具
|
||||
*/
|
||||
private void handleChoice(int choice, Scanner scanner) {
|
||||
List<Tool> tools = toolRegistry.getEnabledTools();
|
||||
int index = choice - 1;
|
||||
|
||||
if (index >= 0 && index < tools.size()) {
|
||||
Tool tool = tools.get(index);
|
||||
try {
|
||||
tool.execute(scanner);
|
||||
} catch (Exception e) {
|
||||
log.error("工具执行失败: {} [{}]", tool.getName(), tool.getId(), e);
|
||||
System.out.println("工具执行失败: " + e.getMessage());
|
||||
}
|
||||
} else {
|
||||
ConsoleHelper.printInvalidOption();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,89 +0,0 @@
|
||||
package com.example.workutils.system.tool;
|
||||
|
||||
import com.example.workutils.system.ConsoleHelper;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import java.util.Scanner;
|
||||
|
||||
/**
|
||||
* 工具基类
|
||||
* 提供共享的菜单循环模板方法,消除各Menu中的重复代码
|
||||
* 子类只需实现handleChoice()定义具体交互逻辑
|
||||
*
|
||||
* 控制台I/O方法委托给ConsoleHelper,日志方法保留在此类
|
||||
*/
|
||||
@Slf4j
|
||||
public abstract class AbstractTool implements Tool {
|
||||
|
||||
/**
|
||||
* 模板方法:标准菜单交互循环
|
||||
* displayMenu → readChoice → if 0 return → handleChoice → repeat
|
||||
*/
|
||||
@Override
|
||||
public void execute(Scanner scanner) {
|
||||
while (true) {
|
||||
ConsoleHelper.printMenuTitle(getName());
|
||||
ConsoleHelper.displayMenu(getMenuOptions());
|
||||
|
||||
int choice = ConsoleHelper.readChoice(scanner);
|
||||
scanner.nextLine();
|
||||
|
||||
if (choice == 0) {
|
||||
info("返回上级菜单");
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
handleChoice(choice, scanner);
|
||||
} catch (Exception e) {
|
||||
error(getName() + "执行失败", e);
|
||||
ConsoleHelper.printError(e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理子菜单选择,子类实现具体switch-case逻辑
|
||||
*/
|
||||
protected abstract void handleChoice(int choice, Scanner scanner) throws Exception;
|
||||
|
||||
// ============ 日志方法 ============
|
||||
|
||||
protected void info(String message) {
|
||||
log.info(message);
|
||||
}
|
||||
|
||||
protected void info(String message, Object... args) {
|
||||
log.info(message, args);
|
||||
}
|
||||
|
||||
protected void error(String message) {
|
||||
log.error(message);
|
||||
}
|
||||
|
||||
protected void error(String message, Exception e) {
|
||||
log.error(message, e);
|
||||
}
|
||||
|
||||
// ============ 控制台I/O方法(委托给ConsoleHelper,子类可直接调用) ============
|
||||
|
||||
protected void printMenuTitle(String title) {
|
||||
ConsoleHelper.printMenuTitle(title);
|
||||
}
|
||||
|
||||
protected void displayMenu(String[] options) {
|
||||
ConsoleHelper.displayMenu(options);
|
||||
}
|
||||
|
||||
protected void printSuccess(String operation) {
|
||||
ConsoleHelper.printSuccess(operation);
|
||||
}
|
||||
|
||||
protected void printError(String message) {
|
||||
ConsoleHelper.printError(message);
|
||||
}
|
||||
|
||||
protected void printInvalidOption() {
|
||||
ConsoleHelper.printInvalidOption();
|
||||
}
|
||||
}
|
||||
+55
-23
@@ -1,5 +1,6 @@
|
||||
package com.example.workutils.system.tool;
|
||||
|
||||
import com.example.workutils.system.ConsoleHelper;
|
||||
import com.example.workutils.system.config.WorkUtilsProperties;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Component;
|
||||
@@ -10,11 +11,14 @@ import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* 工具注册中心
|
||||
* 自动发现Spring容器中的Tool Bean,按配置过滤启用/禁用
|
||||
* 自动发现 Spring 容器中的 Tool Bean,按配置过滤启用/禁用
|
||||
* 同时负责主菜单循环(从 MenuRunner 合并)
|
||||
*/
|
||||
@Slf4j
|
||||
@Component
|
||||
public class ToolRegistry {
|
||||
public class Registry {
|
||||
|
||||
private static final int EXIT_CODE = 0;
|
||||
|
||||
private final List<Tool> allTools;
|
||||
private final WorkUtilsProperties properties;
|
||||
@@ -22,11 +26,7 @@ public class ToolRegistry {
|
||||
private Map<String, Tool> toolByIdMap;
|
||||
private Map<String, Tool> toolByCommandMap;
|
||||
|
||||
/**
|
||||
* Spring自动注入所有Tool Bean
|
||||
* 新增工具只需创建@Component类实现Tool接口,无需修改此类
|
||||
*/
|
||||
public ToolRegistry(List<Tool> tools, WorkUtilsProperties properties) {
|
||||
public Registry(List<Tool> tools, WorkUtilsProperties properties) {
|
||||
this.allTools = tools;
|
||||
this.properties = properties;
|
||||
}
|
||||
@@ -52,7 +52,6 @@ public class ToolRegistry {
|
||||
log.info("跳过已禁用工具: {} [{}]", tool.getName(), tool.getId());
|
||||
}
|
||||
} catch (Exception e) {
|
||||
// 工具隔离:单个工具初始化异常不影响平台和其他工具
|
||||
log.error("工具初始化失败: {} [{}]", tool.getName(), tool.getId(), e);
|
||||
}
|
||||
}
|
||||
@@ -60,33 +59,66 @@ public class ToolRegistry {
|
||||
log.info("工具注册完成: {}/{} 已启用", enabledTools.size(), allTools.size());
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取所有已启用工具
|
||||
*/
|
||||
// ==================== 主菜单(从 MenuRunner 合并) ====================
|
||||
|
||||
public void runMainMenu(Scanner scanner) {
|
||||
log.info("启动主菜单");
|
||||
while (true) {
|
||||
ConsoleHelper.printMenuTitle("主菜单");
|
||||
displayMainMenu();
|
||||
|
||||
int choice = ConsoleHelper.readChoice(scanner);
|
||||
scanner.nextLine();
|
||||
|
||||
if (choice == EXIT_CODE) {
|
||||
log.info("用户退出系统");
|
||||
System.out.println("感谢使用,再见!");
|
||||
break;
|
||||
}
|
||||
|
||||
dispatchTool(choice, scanner);
|
||||
}
|
||||
}
|
||||
|
||||
private void displayMainMenu() {
|
||||
System.out.println("请选择操作:");
|
||||
for (int i = 0; i < enabledTools.size(); i++) {
|
||||
System.out.println((i + 1) + ". " + enabledTools.get(i).getName());
|
||||
}
|
||||
System.out.println(EXIT_CODE + ". 退出系统");
|
||||
}
|
||||
|
||||
private void dispatchTool(int choice, Scanner scanner) {
|
||||
int index = choice - 1;
|
||||
if (index >= 0 && index < enabledTools.size()) {
|
||||
Tool tool = enabledTools.get(index);
|
||||
try {
|
||||
tool.execute(scanner);
|
||||
} catch (Exception e) {
|
||||
log.error("工具执行失败: {} [{}]", tool.getName(), tool.getId(), e);
|
||||
System.out.println("工具执行失败: " + e.getMessage());
|
||||
}
|
||||
} else {
|
||||
ConsoleHelper.printInvalidOption();
|
||||
}
|
||||
}
|
||||
|
||||
// ==================== 查找方法 ====================
|
||||
|
||||
public List<Tool> getEnabledTools() {
|
||||
return Collections.unmodifiableList(enabledTools);
|
||||
}
|
||||
|
||||
/**
|
||||
* 按ID查找工具
|
||||
*/
|
||||
public Optional<Tool> getToolById(String id) {
|
||||
return Optional.ofNullable(toolByIdMap.get(id));
|
||||
}
|
||||
|
||||
/**
|
||||
* 按命令行命令名查找工具
|
||||
*/
|
||||
public Optional<Tool> getToolByCommand(String command) {
|
||||
return Optional.ofNullable(toolByCommandMap.get(command));
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据配置解析启用的工具ID集合
|
||||
* 优先级: enabled白名单 > disabled黑名单 > 全部启用
|
||||
*
|
||||
* @return null表示全部启用,否则为启用的ID集合
|
||||
*/
|
||||
// ==================== 启用/禁用解析 ====================
|
||||
|
||||
private Set<String> resolveEnabledIds() {
|
||||
WorkUtilsProperties.ToolsConfig toolsConfig = properties.getTools();
|
||||
if (toolsConfig == null) {
|
||||
@@ -1,53 +1,90 @@
|
||||
package com.example.workutils.system.tool;
|
||||
|
||||
import com.example.workutils.system.ConsoleHelper;
|
||||
|
||||
import java.util.Scanner;
|
||||
|
||||
/**
|
||||
* 工具策略接口
|
||||
* 所有可插拔工具实现此接口,Spring自动发现Tool Bean
|
||||
* 所有可插拔工具实现此接口,Spring 自动发现 Tool Bean
|
||||
* <p>
|
||||
* 提供交互式菜单(execute)和命令行(executeCommand)两种执行模式。
|
||||
* 交互模式由默认 execute() 模板方法驱动,子类实现 handleChoice() 定义选择逻辑。
|
||||
*/
|
||||
public interface Tool {
|
||||
|
||||
/**
|
||||
* 工具唯一标识(用于配置启用/禁用)
|
||||
* 示例: "scan", "mybatis", "batch", "git-health", "mybatis-generator"
|
||||
*/
|
||||
/** 工具唯一标识(如 "scan", "mybatis") */
|
||||
String getId();
|
||||
|
||||
/**
|
||||
* 菜单显示名称
|
||||
* 示例: "关键词扫描", "MyBatis导出"
|
||||
*/
|
||||
/** 菜单显示名称(如 "关键词扫描", "MyBatis SQL导出") */
|
||||
String getName();
|
||||
|
||||
/**
|
||||
* 子菜单选项
|
||||
* 返回空数组表示无子菜单
|
||||
*/
|
||||
/** 子菜单选项,返回空数组表示无子菜单 */
|
||||
String[] getMenuOptions();
|
||||
|
||||
/**
|
||||
* 命令行模式下的命令名,如 "sql", "scan", "batch"
|
||||
* 返回空字符串表示不支持命令行模式
|
||||
*/
|
||||
/** 命令行命令名(如 "sql", "scan"),返回空字符串表示不支持命令行模式 */
|
||||
default String getCommandName() {
|
||||
return "";
|
||||
}
|
||||
|
||||
/**
|
||||
* 执行工具的交互会话
|
||||
*
|
||||
* @param scanner 控制台输入
|
||||
*/
|
||||
void execute(Scanner scanner);
|
||||
// ==================== 交互模式(模板方法) ====================
|
||||
|
||||
/**
|
||||
* 命令行模式执行(无交互)
|
||||
* 默认实现打印不支持提示
|
||||
*
|
||||
* @param args 命令行参数(不含命令名本身)
|
||||
* 交互式菜单循环(默认实现,从 AbstractTool 合并而来)
|
||||
* displayMenu → readChoice → if 0 return → handleChoice → repeat
|
||||
*/
|
||||
default void execute(Scanner scanner) {
|
||||
while (true) {
|
||||
ConsoleHelper.printMenuTitle(getName());
|
||||
ConsoleHelper.displayMenu(getMenuOptions());
|
||||
|
||||
int choice = ConsoleHelper.readChoice(scanner);
|
||||
scanner.nextLine();
|
||||
|
||||
if (choice == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
handleChoice(choice, scanner);
|
||||
} catch (Exception e) {
|
||||
ConsoleHelper.printError(e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** 处理子菜单选择,子类实现具体分发逻辑 */
|
||||
default void handleChoice(int choice, Scanner scanner) throws Exception {
|
||||
}
|
||||
|
||||
// ==================== 命令行模式 ====================
|
||||
|
||||
/**
|
||||
* 命令行模式执行(无交互),默认打印不支持提示
|
||||
*/
|
||||
default void executeCommand(String... args) throws Exception {
|
||||
System.out.println("工具 [" + getName() + "] 不支持命令行模式");
|
||||
}
|
||||
|
||||
// ==================== 控制台输出辅助方法 ====================
|
||||
|
||||
default void printMenuTitle(String title) {
|
||||
ConsoleHelper.printMenuTitle(title);
|
||||
}
|
||||
|
||||
default void displayMenu(String[] options) {
|
||||
ConsoleHelper.displayMenu(options);
|
||||
}
|
||||
|
||||
default void printSuccess(String operation) {
|
||||
ConsoleHelper.printSuccess(operation);
|
||||
}
|
||||
|
||||
default void printError(String message) {
|
||||
ConsoleHelper.printError(message);
|
||||
}
|
||||
|
||||
default void printInvalidOption() {
|
||||
ConsoleHelper.printInvalidOption();
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user