代码优化提交
This commit is contained in:
@@ -41,19 +41,18 @@ public class WorkUtilsApplication implements CommandLineRunner {
|
||||
}
|
||||
|
||||
/**
|
||||
* 命令行模式:通过 PluginManager 按命令名分发到对应 Plugin
|
||||
* 命令行模式:通过 PluginManager 按命令名分发到对应 Tool
|
||||
* 启动类不依赖任何具体业务 Service
|
||||
*/
|
||||
private void processCommand(String... args) throws Exception {
|
||||
String command = args[0].toLowerCase();
|
||||
|
||||
Optional<Plugin> pluginOpt = pluginManager.getPluginByCommand(command);
|
||||
if (pluginOpt.isPresent()) {
|
||||
Plugin plugin = pluginOpt.get();
|
||||
Optional<Plugin> toolOpt = pluginManager.getPluginByCommand(command);
|
||||
if (toolOpt.isPresent()) {
|
||||
Plugin plugin = toolOpt.get();
|
||||
try {
|
||||
// args[0]是命令名,从args[1]开始传给plugin
|
||||
String[] pluginArgs = args.length > 1 ? Arrays.copyOfRange(args, 1, args.length) : new String[0];
|
||||
plugin.executeCommand(pluginArgs);
|
||||
String[] toolArgs = args.length > 1 ? Arrays.copyOfRange(args, 1, args.length) : new String[0];
|
||||
plugin.executeCommand(toolArgs);
|
||||
} catch (Exception e) {
|
||||
log.error("命令执行失败: {} [{}]", plugin.getName(), plugin.getId(), e);
|
||||
System.err.println("命令执行失败: " + e.getMessage());
|
||||
|
||||
+3
-2
@@ -13,13 +13,14 @@ import java.util.List;
|
||||
import java.util.Scanner;
|
||||
|
||||
/**
|
||||
* 批量处理插件(实现 Plugin 接口)
|
||||
* 批量处理插件(实现 Tool 接口)
|
||||
* 仅负责菜单展示和用户交互,业务逻辑委托给各Service
|
||||
|
||||
*/
|
||||
@Slf4j
|
||||
@Component
|
||||
@RequiredArgsConstructor
|
||||
public class BatchTool implements Plugin {
|
||||
public class BatchPlugin implements Plugin {
|
||||
|
||||
@FunctionalInterface
|
||||
public interface ExceptionRunnable {
|
||||
+3
-3
@@ -2,8 +2,8 @@ package com.example.workutils.biz.git;
|
||||
|
||||
import com.example.workutils.biz.git.service.GitService;
|
||||
import com.example.workutils.biz.git.service.internal.GitCommandExecutor;
|
||||
import com.example.workutils.system.plugin.Plugin;
|
||||
import com.example.workutils.system.plugin.PluginDescriptor;
|
||||
import com.example.workutils.system.plugin.Plugin;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Component;
|
||||
@@ -14,12 +14,12 @@ import java.util.Scanner;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* Git仓库健康检测插件(实现 Plugin 接口)
|
||||
* Git仓库健康检测插件(实现 Tool 接口)
|
||||
*/
|
||||
@Slf4j
|
||||
@Component
|
||||
@RequiredArgsConstructor
|
||||
public class GitTool implements Plugin {
|
||||
public class GitPlugin implements Plugin {
|
||||
|
||||
private static final PluginDescriptor DESCRIPTOR = PluginDescriptor.builder()
|
||||
.id("git-health")
|
||||
@@ -3,7 +3,7 @@ package com.example.workutils.biz.git.service;
|
||||
import com.example.workutils.biz.git.service.internal.GitCommandExecutor;
|
||||
import com.example.workutils.biz.git.service.internal.strategy.GitStrategyFactory;
|
||||
import com.example.workutils.biz.git.service.model.GitCommand;
|
||||
import com.example.workutils.system.support.FileOperationService;
|
||||
import com.example.workutils.system.support.FileOperationHelper;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
@@ -26,7 +26,7 @@ public class GitServiceImpl implements GitService {
|
||||
private final GitStrategyFactory strategyFactory;
|
||||
|
||||
@Autowired
|
||||
private FileOperationService fileOperationService;
|
||||
private FileOperationHelper fileOperationHelper;
|
||||
|
||||
private static final String DEFAULT_BRANCH = "master";
|
||||
|
||||
@@ -52,10 +52,10 @@ public class GitServiceImpl implements GitService {
|
||||
@Override
|
||||
public List<GitCommandExecutor.RepoHealthResult> checkCorruptedRepos(Scanner scanner) {
|
||||
List<GitCommandExecutor.RepoHealthResult> corruptedRepos = new ArrayList<>();
|
||||
List<FileOperationService.ProjectPathInfo> projects;
|
||||
List<FileOperationHelper.ProjectPathInfo> projects;
|
||||
|
||||
try {
|
||||
projects = fileOperationService.getProjectPathsWithStatus();
|
||||
projects = fileOperationHelper.getProjectPathsWithStatus();
|
||||
} catch (IOException e) {
|
||||
log.error("读取项目路径配置文件失败", e);
|
||||
return corruptedRepos;
|
||||
@@ -68,7 +68,7 @@ public class GitServiceImpl implements GitService {
|
||||
int totalCount = projects.size();
|
||||
boolean isAborted = false;
|
||||
|
||||
for (FileOperationService.ProjectPathInfo project : projects) {
|
||||
for (FileOperationHelper.ProjectPathInfo project : projects) {
|
||||
String repoPath = project.getPath();
|
||||
String repoName = extractProjectName(repoPath);
|
||||
|
||||
@@ -80,7 +80,7 @@ public class GitServiceImpl implements GitService {
|
||||
|
||||
if (healthResult.isHealthy()) {
|
||||
try {
|
||||
fileOperationService.updateProjectStatus(repoPath, FileOperationService.ProjectStatus.NORMAL);
|
||||
fileOperationHelper.updateProjectStatus(repoPath, FileOperationHelper.ProjectStatus.NORMAL);
|
||||
System.out.printf("[%d/%d] %s - 正常%n", checkedCount, totalCount, repoName);
|
||||
} catch (IOException e) {
|
||||
log.warn("更新配置文件失败: {}", repoPath, e);
|
||||
@@ -88,7 +88,7 @@ public class GitServiceImpl implements GitService {
|
||||
} else {
|
||||
corruptedRepos.add(healthResult);
|
||||
try {
|
||||
fileOperationService.updateProjectStatus(repoPath, FileOperationService.ProjectStatus.CORRUPTED);
|
||||
fileOperationHelper.updateProjectStatus(repoPath, FileOperationHelper.ProjectStatus.CORRUPTED);
|
||||
System.out.printf("[%d/%d] %s - 损坏: %s%n", checkedCount, totalCount, repoName, healthResult.getCorruptionReason());
|
||||
} catch (IOException e) {
|
||||
log.warn("更新配置文件失败: {}", repoPath, e);
|
||||
@@ -143,7 +143,7 @@ public class GitServiceImpl implements GitService {
|
||||
if (result.isSuccess()) {
|
||||
log.info("仓库修复成功: {}", repoPath);
|
||||
try {
|
||||
fileOperationService.updateProjectStatus(repoPath, FileOperationService.ProjectStatus.NORMAL);
|
||||
fileOperationHelper.updateProjectStatus(repoPath, FileOperationHelper.ProjectStatus.NORMAL);
|
||||
} catch (IOException e) {
|
||||
log.warn("更新配置文件失败: {}", repoPath, e);
|
||||
}
|
||||
@@ -157,9 +157,9 @@ public class GitServiceImpl implements GitService {
|
||||
@Override
|
||||
public List<String> listCorruptedRepos() {
|
||||
try {
|
||||
return fileOperationService.getProjectPathsWithStatus().stream()
|
||||
.filter(p -> p.getStatus() == FileOperationService.ProjectStatus.CORRUPTED)
|
||||
.map(FileOperationService.ProjectPathInfo::getPath)
|
||||
return fileOperationHelper.getProjectPathsWithStatus().stream()
|
||||
.filter(p -> p.getStatus() == FileOperationHelper.ProjectStatus.CORRUPTED)
|
||||
.map(FileOperationHelper.ProjectPathInfo::getPath)
|
||||
.collect(Collectors.toList());
|
||||
} catch (IOException e) {
|
||||
log.error("读取损坏仓库列表失败", e);
|
||||
|
||||
+3
-3
@@ -1,8 +1,8 @@
|
||||
package com.example.workutils.biz.mybatisexport;
|
||||
|
||||
import com.example.workutils.biz.mybatisexport.service.MyBatisExportService;
|
||||
import com.example.workutils.system.plugin.Plugin;
|
||||
import com.example.workutils.system.plugin.PluginDescriptor;
|
||||
import com.example.workutils.system.plugin.Plugin;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Component;
|
||||
@@ -11,12 +11,12 @@ import java.util.Arrays;
|
||||
import java.util.Scanner;
|
||||
|
||||
/**
|
||||
* MyBatis SQL导出插件(实现 Plugin 接口)
|
||||
* MyBatis SQL导出插件(实现 Tool 接口)
|
||||
*/
|
||||
@Slf4j
|
||||
@Component
|
||||
@RequiredArgsConstructor
|
||||
public class MyBatisExportTool implements Plugin {
|
||||
public class MyBatisExportPlugin implements Plugin {
|
||||
|
||||
private static final PluginDescriptor DESCRIPTOR = PluginDescriptor.builder()
|
||||
.id("mybatisexport")
|
||||
+6
-6
@@ -2,7 +2,7 @@ package com.example.workutils.biz.mybatisexport.service;
|
||||
|
||||
import com.example.workutils.biz.mybatisexport.service.model.MybatisTag;
|
||||
import com.example.workutils.biz.scanner.service.config.ScanConfig;
|
||||
import com.example.workutils.system.support.FileOperationService;
|
||||
import com.example.workutils.system.support.FileOperationHelper;
|
||||
import com.example.workutils.system.support.OutputService;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
@@ -25,7 +25,7 @@ import java.util.regex.Pattern;
|
||||
public class MyBatisExportService {
|
||||
|
||||
@Autowired
|
||||
private FileOperationService fileOperationService;
|
||||
private FileOperationHelper fileOperationHelper;
|
||||
|
||||
@Autowired
|
||||
private OutputService outputService;
|
||||
@@ -78,7 +78,7 @@ public class MyBatisExportService {
|
||||
|
||||
private void exportWithFilter(String fileNamePrefix, SqlFilter filter,
|
||||
ProcessStrategy processStrategy) throws Exception {
|
||||
List<String> projectPaths = fileOperationService.getProjectPaths();
|
||||
List<String> projectPaths = fileOperationHelper.getProjectPaths();
|
||||
if (projectPaths.isEmpty()) {
|
||||
log.warn("未找到项目路径");
|
||||
return;
|
||||
@@ -108,10 +108,10 @@ public class MyBatisExportService {
|
||||
private List<String[]> processProject(String projectPath, SqlFilter filter,
|
||||
ProcessStrategy processStrategy) throws Exception {
|
||||
List<String[]> records = new ArrayList<>();
|
||||
String projectName = fileOperationService.extractProjectName(projectPath);
|
||||
String projectName = fileOperationHelper.extractProjectName(projectPath);
|
||||
|
||||
ScanConfig config = ScanConfig.forXmlFiles();
|
||||
List<Path> xmlFiles = fileOperationService.scanFiles(projectPath, config);
|
||||
List<Path> xmlFiles = fileOperationHelper.scanFiles(projectPath, config);
|
||||
|
||||
for (Path xmlFile : xmlFiles) {
|
||||
try {
|
||||
@@ -134,7 +134,7 @@ public class MyBatisExportService {
|
||||
|
||||
private List<MybatisTag> parseXmlFile(Path xmlFile) throws Exception {
|
||||
List<MybatisTag> tags = new ArrayList<>();
|
||||
String content = fileOperationService.readFileContent(xmlFile);
|
||||
String content = fileOperationHelper.readFileContent(xmlFile);
|
||||
|
||||
for (String tagType : SQL_TAG_TYPES) {
|
||||
tags.addAll(parseSqlTags(content, tagType));
|
||||
|
||||
+2
-2
@@ -12,12 +12,12 @@ import java.util.List;
|
||||
import java.util.Scanner;
|
||||
|
||||
/**
|
||||
* MyBatis逆向工程插件(实现 Plugin 接口)
|
||||
* MyBatis逆向工程插件(实现 Tool 接口)
|
||||
*/
|
||||
@Slf4j
|
||||
@Component
|
||||
@RequiredArgsConstructor
|
||||
public class MyBatisGeneratorTool implements Plugin {
|
||||
public class MyBatisGeneratorPlugin implements Plugin {
|
||||
|
||||
private static final PluginDescriptor DESCRIPTOR = PluginDescriptor.builder()
|
||||
.id("mybatisgenerator")
|
||||
+3
-3
@@ -1,8 +1,8 @@
|
||||
package com.example.workutils.biz.scanner;
|
||||
|
||||
import com.example.workutils.biz.scanner.service.ScannerService;
|
||||
import com.example.workutils.system.plugin.Plugin;
|
||||
import com.example.workutils.system.plugin.PluginDescriptor;
|
||||
import com.example.workutils.system.plugin.Plugin;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Component;
|
||||
@@ -10,12 +10,12 @@ import org.springframework.stereotype.Component;
|
||||
import java.util.Scanner;
|
||||
|
||||
/**
|
||||
* 扫描工具插件(实现 Plugin 接口)
|
||||
* 扫描工具插件(实现 Tool 接口)
|
||||
*/
|
||||
@Slf4j
|
||||
@Component
|
||||
@RequiredArgsConstructor
|
||||
public class ScannerTool implements Plugin {
|
||||
public class ScannerPlugin implements Plugin {
|
||||
|
||||
private static final PluginDescriptor DESCRIPTOR = PluginDescriptor.builder()
|
||||
.id("scan")
|
||||
@@ -2,7 +2,7 @@ package com.example.workutils.biz.scanner.service;
|
||||
|
||||
import com.example.workutils.biz.scanner.service.config.ScanConfig;
|
||||
import com.example.workutils.system.config.WorkUtilsProperties;
|
||||
import com.example.workutils.system.support.FileOperationService;
|
||||
import com.example.workutils.system.support.FileOperationHelper;
|
||||
import com.example.workutils.system.support.OutputService;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
@@ -24,14 +24,14 @@ public class ScannerService {
|
||||
|
||||
private final ExecutorService executorService = Executors.newFixedThreadPool(10);
|
||||
@Autowired
|
||||
private FileOperationService fileOperationService;
|
||||
private FileOperationHelper fileOperationHelper;
|
||||
@Autowired
|
||||
private OutputService outputService;
|
||||
@Autowired
|
||||
private WorkUtilsProperties properties;
|
||||
|
||||
public ScanResult scanAllProjects(ScanType scanType, String pattern) throws Exception {
|
||||
List<String> projectPaths = fileOperationService.getProjectPaths();
|
||||
List<String> projectPaths = fileOperationHelper.getProjectPaths();
|
||||
if (projectPaths.isEmpty()) {
|
||||
log.warn("No project paths found");
|
||||
return new ScanResult();
|
||||
@@ -63,10 +63,10 @@ public class ScannerService {
|
||||
|
||||
private ProjectScanResult scanProject(String projectPath, ScanType scanType, String pattern) throws Exception {
|
||||
ProjectScanResult projectResult = new ProjectScanResult(projectPath, new ArrayList<>());
|
||||
String projectName = fileOperationService.extractProjectName(projectPath);
|
||||
String projectName = fileOperationHelper.extractProjectName(projectPath);
|
||||
|
||||
ScanConfig config = getConfigForScanType(scanType);
|
||||
List<Path> files = fileOperationService.scanFiles(projectPath, config);
|
||||
List<Path> files = fileOperationHelper.scanFiles(projectPath, config);
|
||||
|
||||
for (Path file : files) {
|
||||
try {
|
||||
@@ -90,7 +90,7 @@ public class ScannerService {
|
||||
List<MatchResult> matches = new ArrayList<>();
|
||||
List<String> lines;
|
||||
try {
|
||||
lines = fileOperationService.readLinesFromFile(file);
|
||||
lines = fileOperationHelper.readLinesFromFile(file);
|
||||
} catch (Exception e) {
|
||||
log.warn("Failed to read file: {}, skipping this file", file, e);
|
||||
return matches;
|
||||
@@ -185,7 +185,7 @@ public class ScannerService {
|
||||
}
|
||||
}
|
||||
|
||||
fileOperationService.ensureDirectoryExists(properties.getTodayExportPath());
|
||||
fileOperationHelper.ensureDirectoryExists(properties.getTodayExportPath());
|
||||
outputService.writeRecordsToCsv(records, outputFileName);
|
||||
log.info("Scan results exported to: {}", outputFileName);
|
||||
}
|
||||
|
||||
@@ -1,24 +1,77 @@
|
||||
package com.example.workutils.system.plugin;
|
||||
|
||||
import com.example.workutils.system.tool.Tool;
|
||||
import com.example.workutils.system.support.ConsoleHelper;
|
||||
|
||||
import java.util.Scanner;
|
||||
|
||||
/**
|
||||
* 插件接口 —— 所有 biz 模块的顶级契约
|
||||
* 工具接口 —— 所有 biz 模块的顶级契约
|
||||
* <p>
|
||||
* 继承 {@link Tool},在其基础上增加插件生命周期管理:
|
||||
* 提供:
|
||||
* <ul>
|
||||
* <li>{@link #getDescriptor()} — 提供插件元数据(id/name/version/description/dependencies)</li>
|
||||
* <li>{@link #onLoad(PluginContext)} — 插件加载时回调,注入运行时上下文</li>
|
||||
* <li>{@link #onUnload()} — 插件卸载时回调,清理资源</li>
|
||||
* <li>插件元数据 — {@link #getDescriptor()} 声明 id/name/version/description</li>
|
||||
* <li>生命周期 — {@link #onLoad(PluginContext)} / {@link #onUnload()}</li>
|
||||
* <li>交互模式 — {@link #execute(Scanner)} 模板方法驱动,子类实现 {@link #handleChoice(int, Scanner)}</li>
|
||||
* <li>命令行模式 — {@link #getCommandName()} + {@link #executeCommand(String...)}</li>
|
||||
* </ul>
|
||||
* <p>
|
||||
* getId()/getName() 默认委托给 PluginDescriptor,实现类只需提供 getDescriptor()。
|
||||
*/
|
||||
public interface Plugin extends Tool {
|
||||
public interface Plugin {
|
||||
|
||||
/** 插件描述符(元数据) */
|
||||
PluginDescriptor getDescriptor();
|
||||
|
||||
/** 工具唯一标识,默认委托给 PluginDescriptor */
|
||||
default String getId() {
|
||||
return getDescriptor().getId();
|
||||
}
|
||||
|
||||
/** 菜单显示名称,默认委托给 PluginDescriptor */
|
||||
default String getName() {
|
||||
return getDescriptor().getName();
|
||||
}
|
||||
|
||||
/** 子菜单选项,返回空数组表示无子菜单 */
|
||||
String[] getMenuOptions();
|
||||
|
||||
/** 命令行命令名(如 "sql", "scan"),返回空字符串表示不支持命令行模式 */
|
||||
default String getCommandName() {
|
||||
return "";
|
||||
}
|
||||
|
||||
// ==================== 交互模式(模板方法) ====================
|
||||
|
||||
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() + "] 不支持命令行模式");
|
||||
}
|
||||
|
||||
// ==================== 生命周期回调 ====================
|
||||
|
||||
/** 插件加载回调,PluginManager 在注册时调用 */
|
||||
default void onLoad(PluginContext context) {
|
||||
}
|
||||
@@ -27,15 +80,25 @@ public interface Plugin extends Tool {
|
||||
default void onUnload() {
|
||||
}
|
||||
|
||||
// ==================== 默认委托 ====================
|
||||
// ==================== 控制台输出辅助方法 ====================
|
||||
|
||||
@Override
|
||||
default String getId() {
|
||||
return getDescriptor().getId();
|
||||
default void printMenuTitle(String title) {
|
||||
ConsoleHelper.printMenuTitle(title);
|
||||
}
|
||||
|
||||
@Override
|
||||
default String getName() {
|
||||
return getDescriptor().getName();
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@ import java.util.List;
|
||||
/**
|
||||
* 插件描述符(不可变元数据)
|
||||
* <p>
|
||||
* 每个 Plugin 通过 {@link Plugin#getDescriptor()} 返回此描述符,
|
||||
* 每个插件通过 {@link Plugin#getDescriptor()} 返回此描述符,
|
||||
* PluginManager 据此识别、管理、展示插件。
|
||||
*/
|
||||
public class PluginDescriptor {
|
||||
|
||||
@@ -11,7 +11,7 @@ import java.util.*;
|
||||
/**
|
||||
* 插件管理器 —— 插件生命周期管理 + 注册中心 + 主菜单
|
||||
* <p>
|
||||
* 替换旧版 {@code ToolRegistry},统一管理所有 {@link Plugin} 的:
|
||||
* 统一管理所有 {@link Plugin} 实例的:
|
||||
* <ul>
|
||||
* <li>生命周期 — load / unload / enable / disable</li>
|
||||
* <li>注册发现 — 按 id / command 查找</li>
|
||||
|
||||
+1
-1
@@ -21,7 +21,7 @@ import java.util.stream.Stream;
|
||||
*/
|
||||
@Service
|
||||
@Slf4j
|
||||
public class FileOperationService {
|
||||
public class FileOperationHelper {
|
||||
|
||||
@Autowired
|
||||
private WorkUtilsProperties properties;
|
||||
+9
-9
@@ -22,10 +22,10 @@ import java.util.List;
|
||||
*/
|
||||
@Service
|
||||
@Slf4j
|
||||
public class OutputService {
|
||||
public class OutputHelper {
|
||||
|
||||
@Autowired
|
||||
private FileOperationService fileOperationService;
|
||||
private FileOperationHelper fileOperationHelper;
|
||||
|
||||
@Autowired
|
||||
private WorkUtilsProperties properties;
|
||||
@@ -39,7 +39,7 @@ public class OutputService {
|
||||
} else {
|
||||
filePath = properties.resolveExportPath(outputPath);
|
||||
}
|
||||
fileOperationService.ensureDirectoryExists(filePath.getParent());
|
||||
fileOperationHelper.ensureDirectoryExists(filePath.getParent());
|
||||
|
||||
try (CSVWriter writer = new CSVWriter(new FileWriter(filePath.toFile()))) {
|
||||
if (headers.length > 0) {
|
||||
@@ -62,9 +62,9 @@ public class OutputService {
|
||||
|
||||
public void appendToCsv(String[] record, String outputPath, String... headers) throws IOException {
|
||||
Path filePath = properties.resolveExportPath(outputPath);
|
||||
fileOperationService.ensureDirectoryExists(filePath.getParent());
|
||||
fileOperationHelper.ensureDirectoryExists(filePath.getParent());
|
||||
|
||||
boolean fileExists = fileOperationService.fileExists(filePath);
|
||||
boolean fileExists = fileOperationHelper.fileExists(filePath);
|
||||
boolean shouldWriteHeaders = !fileExists && headers.length > 0;
|
||||
|
||||
try (CSVWriter writer = new CSVWriter(new FileWriter(filePath.toFile(), true))) {
|
||||
@@ -82,21 +82,21 @@ public class OutputService {
|
||||
|
||||
public <T> void writeToExcel(List<T> data, String outputPath, Class<T> modelClass) throws IOException {
|
||||
Path filePath = properties.resolveExportPath(outputPath);
|
||||
fileOperationService.ensureDirectoryExists(filePath.getParent());
|
||||
fileOperationHelper.ensureDirectoryExists(filePath.getParent());
|
||||
EasyExcel.write(filePath.toFile(), modelClass).sheet().doWrite(data);
|
||||
log.info("Excel文件写入成功: {}", filePath);
|
||||
}
|
||||
|
||||
public <T> void writeToExcel(List<T> data, String outputPath, String sheetName, Class<T> modelClass) throws IOException {
|
||||
Path filePath = properties.resolveExportPath(outputPath);
|
||||
fileOperationService.ensureDirectoryExists(filePath.getParent());
|
||||
fileOperationHelper.ensureDirectoryExists(filePath.getParent());
|
||||
EasyExcel.write(filePath.toFile(), modelClass).sheet(sheetName).doWrite(data);
|
||||
log.info("Excel文件写入成功: {}", filePath);
|
||||
}
|
||||
|
||||
public <T> void writeToExcelWithMultipleSheets(List<ExcelSheetData<T>> sheetsData, String outputPath) throws IOException {
|
||||
Path filePath = properties.resolveExportPath(outputPath);
|
||||
fileOperationService.ensureDirectoryExists(filePath.getParent());
|
||||
fileOperationHelper.ensureDirectoryExists(filePath.getParent());
|
||||
|
||||
try (ExcelWriter excelWriter = EasyExcel.write(filePath.toFile()).build()) {
|
||||
for (ExcelSheetData<T> sheetData : sheetsData) {
|
||||
@@ -113,7 +113,7 @@ public class OutputService {
|
||||
// ==================== 文件名生成相关方法 ====================
|
||||
|
||||
public String generateOutputFileName(String prefix, String extension) {
|
||||
return fileOperationService.generateFileName(prefix, extension);
|
||||
return fileOperationHelper.generateFileName(prefix, extension);
|
||||
}
|
||||
|
||||
// ==================== 内部数据类 ====================
|
||||
@@ -1,83 +0,0 @@
|
||||
package com.example.workutils.system.tool;
|
||||
|
||||
import com.example.workutils.system.support.ConsoleHelper;
|
||||
|
||||
import java.util.Scanner;
|
||||
|
||||
/**
|
||||
* 工具策略接口
|
||||
* 所有可插拔工具实现此接口,Spring 自动发现 Tool Bean
|
||||
* <p>
|
||||
* 提供交互式菜单(execute)和命令行(executeCommand)两种执行模式。
|
||||
* 交互模式由默认 execute() 模板方法驱动,子类实现 handleChoice() 定义选择逻辑。
|
||||
*/
|
||||
public interface Tool {
|
||||
|
||||
/** 工具唯一标识(如 "scan", "mybatis") */
|
||||
String getId();
|
||||
|
||||
/** 菜单显示名称(如 "关键词扫描", "MyBatis SQL导出") */
|
||||
String getName();
|
||||
|
||||
/** 子菜单选项,返回空数组表示无子菜单 */
|
||||
String[] getMenuOptions();
|
||||
|
||||
/** 命令行命令名(如 "sql", "scan"),返回空字符串表示不支持命令行模式 */
|
||||
default String getCommandName() {
|
||||
return "";
|
||||
}
|
||||
|
||||
// ==================== 交互模式(模板方法) ====================
|
||||
|
||||
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