diff --git a/pom.xml b/pom.xml index b83e812..5d12701 100644 --- a/pom.xml +++ b/pom.xml @@ -143,6 +143,13 @@ 1.2.12 + + + org.apache.logging.log4j + log4j-to-slf4j + 2.20.0 + + com.alibaba easyexcel diff --git a/src/main/java/com/example/workutils/biz/apidoc/ApiDocPlugin.java b/src/main/java/com/example/workutils/biz/apidoc/ApiDocPlugin.java index dbf7054..90f858b 100644 --- a/src/main/java/com/example/workutils/biz/apidoc/ApiDocPlugin.java +++ b/src/main/java/com/example/workutils/biz/apidoc/ApiDocPlugin.java @@ -37,9 +37,9 @@ public class ApiDocPlugin implements Plugin { .build(); private static final String[] MENU_OPTIONS = { - "1. 自定义路径导出 (输入文件或目录路径)", - "2. 全限定名导出 (仅输入类名,自动匹配项目)", - "3. 批量导出 (从配置文件读取项目列表,自动遍历所有模块)", + "1. 自定义路径导出(输入文件或目录路径)", + "2. 全限定名导出 (仅输入类名,自动匹配项目)", + "3. 批量导出 (从配置文件选择项目导出)", "0. 返回上级菜单" }; @@ -66,7 +66,7 @@ public class ApiDocPlugin implements Plugin { // ==================== 批量导出(遍历所有项目) ==================== private void exportAll(Scanner scanner) throws Exception { - System.out.println("\n=== 批量导出(从 代码仓库项目路径.txt 读取项目列表)==="); + System.out.println("\n=== 批量导出(按项目)==="); // 1) 从配置文件读取项目路径 Path configFile = properties.getProjectPathsFilePath(); @@ -87,17 +87,45 @@ public class ApiDocPlugin implements Plugin { System.out.println("配置文件中未配置任何项目路径。"); return; } - System.out.println("配置文件: " + configFile.toAbsolutePath()); - System.out.println("配置项目数: " + projectPaths.size()); + + // 2) 列出项目,让用户选择 + System.out.println("\n配置项目列表:"); + for (int i = 0; i < projectPaths.size(); i++) { + String projPath = projectPaths.get(i); + String projName = Paths.get(projPath).getFileName().toString(); + System.out.printf(" %d. %s (%s)%n", i + 1, projName, projPath); + } + System.out.println(" 0. 全部导出"); + + System.out.print("\n请选择要导出的项目 (1-" + projectPaths.size() + ",0 全部): "); + String choice = scanner.nextLine().trim(); + + // 筛选要导出的项目路径 + List selectedPaths = new ArrayList<>(); + if ("0".equals(choice)) { + selectedPaths.addAll(projectPaths); + } else { + try { + int idx = Integer.parseInt(choice) - 1; + if (idx < 0 || idx >= projectPaths.size()) { + System.out.println("无效选择。"); + return; + } + selectedPaths.add(projectPaths.get(idx)); + } catch (NumberFormatException e) { + System.out.println("无效输入。"); + return; + } + } System.out.print("导出格式 (1-HTML / 2-Markdown / 3-两者都导出,默认 3): "); String fmt = scanner.nextLine().trim(); - // 2) 扫描每个配置路径下所有模块 - Set seenSrcBases = new HashSet<>(); // 去重 + // 3) 扫描选中项目下所有模块 + Set seenSrcBases = new HashSet<>(); List modules = new ArrayList<>(); - for (String projPath : projectPaths) { + for (String projPath : selectedPaths) { Path projDir = Paths.get(projPath); if (!Files.isDirectory(projDir)) { System.out.println(" [跳过] 目录不存在: " + projPath); diff --git a/src/main/java/com/example/workutils/biz/apidoc/parser/JavaSourceParser.java b/src/main/java/com/example/workutils/biz/apidoc/parser/JavaSourceParser.java index d42fa0b..e066a41 100644 --- a/src/main/java/com/example/workutils/biz/apidoc/parser/JavaSourceParser.java +++ b/src/main/java/com/example/workutils/biz/apidoc/parser/JavaSourceParser.java @@ -489,6 +489,7 @@ public class JavaSourceParser { */ private List resolveDtoFieldsByShortName(String shortName, ClassInfo ci, Path srcBaseDir) { if (shortName == null || shortName.isEmpty()) return null; + if (isInvalidTypeName(shortName)) return null; // 含非法字符(如引号),说明被错误解析 if (isSkipType(shortName) || shortName.contains(".")) { // 已是全限定名或为基础类型,直接按 FQN 解析 return resolveDtoFields(shortName.contains(".") ? shortName : ("java.lang." + shortName), srcBaseDir); @@ -745,8 +746,20 @@ public class JavaSourceParser { */ private Path resolveDtonToPath(String fqn, Path srcBaseDir) { if (fqn == null || srcBaseDir == null) return null; - String relativePath = fqn.replace('.', '/') + ".java"; - Path direct = srcBaseDir.resolve(relativePath); + String relativePath; + try { + relativePath = fqn.replace('.', '/') + ".java"; + } catch (Exception e) { + log.debug("非法 FQN,跳过 DTO 解析: {}", fqn); + return null; + } + Path direct; + try { + direct = srcBaseDir.resolve(relativePath); + } catch (Exception e) { + log.debug("非法路径,跳过 DTO 解析: {}", relativePath); + return null; + } if (Files.isRegularFile(direct)) return direct; // 如果不在当前模块,尝试扫描父目录下所有模块的 src/main/java @@ -782,6 +795,20 @@ public class JavaSourceParser { return false; } + /** 类型名是否包含非法字符(如引号、换行等,说明被错误解析) */ + private static boolean isInvalidTypeName(String name) { + if (name == null || name.isEmpty()) return true; + for (int i = 0; i < name.length(); i++) { + char c = name.charAt(i); + // 合法的 Java 类型名字符:字母、数字、.、$、_、<、>、,、空格、?、[、] + if (Character.isLetterOrDigit(c)) continue; + if (c == '.' || c == '$' || c == '_' || c == '<' || c == '>' + || c == ',' || c == ' ' || c == '?' || c == '[' || c == ']') continue; + return true; + } + return false; + } + private int countChar(String s, char c) { int cnt = 0; for (int i = 0; i < s.length(); i++) { diff --git a/src/main/java/com/example/workutils/biz/mybatisgenerator/service/generator/MyBatisGeneratorService.java b/src/main/java/com/example/workutils/biz/mybatisgenerator/service/generator/MyBatisGeneratorService.java index 22a9607..1d01f34 100644 --- a/src/main/java/com/example/workutils/biz/mybatisgenerator/service/generator/MyBatisGeneratorService.java +++ b/src/main/java/com/example/workutils/biz/mybatisgenerator/service/generator/MyBatisGeneratorService.java @@ -133,6 +133,19 @@ public class MyBatisGeneratorService { * 内部生成方法 */ private String generateInternal(List tableNames, boolean overwrite) throws Exception { + // 确保 targetProject 目录存在,避免 "does not exist" 警告 + Properties props = getConfigurationProperties(); + for (String key : new String[]{"model_target_project", "sqlmapper_target_project", "dao_target_project"}) { + String dir = props.getProperty(key); + if (dir != null && !dir.isEmpty()) { + File targetDir = new File(dir); + if (!targetDir.exists()) { + targetDir.mkdirs(); + log.info("已创建目标目录: {}", targetDir.getAbsolutePath()); + } + } + } + File tempConfigFile = createTempConfigWithTables(tableNames); try { @@ -183,6 +196,12 @@ public class MyBatisGeneratorService { content = sb.toString(); } + // 截掉 之后的内容(防止尾随垃圾导致 XML 解析失败) + int endIdx = content.lastIndexOf(""); + if (endIdx >= 0) { + content = content.substring(0, endIdx + "".length()); + } + java.util.regex.Pattern tablePattern = java.util.regex.Pattern.compile( "]*/>|]*>.*?", java.util.regex.Pattern.DOTALL diff --git a/src/main/resources/mybatis-generator.xml b/src/main/resources/mybatis-generator.xml index 1175375..906e741 100644 --- a/src/main/resources/mybatis-generator.xml +++ b/src/main/resources/mybatis-generator.xml @@ -12,11 +12,11 @@ - + - + - + @@ -51,8 +51,4 @@ - - -https://srd17321104074@code.srdcloud.cn/bestpay-cf/cf/cf/ft-loan-core - -https://srd17321104074@code.srdcloud.cn/bestpay-cf/cf/ft-loan-core \ No newline at end of file + \ No newline at end of file