1. 新增基础模块 databus,rule,html2pdf

(cherry picked from commit f1bbb8b305)
This commit is contained in:
chenbowen
2025-09-03 08:55:30 +08:00
committed by chenbowen
parent 89e2bb43f9
commit 5e1c311fff
40 changed files with 2027 additions and 477 deletions

View File

@@ -0,0 +1,167 @@
package cn.iocoder.yudao.framework.test.core.ut;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.HashMap;
import java.util.Map;
import java.util.Scanner;
import static cn.iocoder.yudao.framework.test.core.ut.GeneratorUtils.camelToKebabCase;
import static cn.iocoder.yudao.framework.test.core.ut.GeneratorUtils.toPascalCase;
/**
* 基础代码生成器,提供公共的生成逻辑
*
* @author ZT
*/
public abstract class BaseGenerator {
protected static final String BASE_PACKAGE = "cn.iocoder.yudao";
protected static final TemplateEngine templateEngine = new TemplateEngine();
/**
* 获取用户输入的基础信息
*
* @param prompt 提示信息
* @return 包含用户输入信息的Map
*/
protected static Map<String, Object> getUserInput(String prompt) {
Scanner scanner = new Scanner(System.in);
Map<String, Object> input = new HashMap<>();
System.out.print(prompt);
input.put("names", scanner.nextLine());
System.out.print("请输入作者名称例如yudao: ");
input.put("author", scanner.nextLine());
System.out.print("请输入起始端口号例如8080: ");
input.put("startPort", Integer.parseInt(scanner.nextLine()));
scanner.close();
return input;
}
/**
* 检查目录是否已存在
*
* @param dir 目录路径
* @param name 名称
* @return 如果目录已存在返回true
*/
protected static boolean checkDirectoryExists(Path dir, String name) {
if (Files.exists(dir)) {
System.err.println("警告:'" + name + "' 已存在于 " + dir + ",跳过创建");
return true;
}
return false;
}
/**
* 创建基础模板变量
*
* @param name 名称
* @param author 作者
* @param port 端口
* @return 模板变量Map
*/
protected Map<String, Object> createBaseVariables(String name, String author, int port) {
String dashName = camelToKebabCase(name);
String capitalizedName = toPascalCase(dashName);
Map<String, Object> variables = new HashMap<>();
variables.put("originalName", name);
variables.put("dashName", dashName);
variables.put("packageName", dashName.replace("-", ""));
variables.put("packagePathName", dashName.toLowerCase().replace('-', '/'));
variables.put("capitalizedName", capitalizedName);
variables.put("baseName", dashName.toLowerCase());
variables.put("basePackage", BASE_PACKAGE);
variables.put("author", author);
variables.put("port", port);
return variables;
}
/**
* 渲染配置文件模板
*
* @param resourcesDir 资源目录
* @param templatePrefix 模板前缀
* @param variables 模板变量
* @throws IOException IO异常
*/
protected static void renderConfigFiles(Path resourcesDir, String templatePrefix, Map<String, Object> variables) throws IOException {
templateEngine.renderToFile(templatePrefix + "/application.yml.vm",
resourcesDir.resolve("application.yml"), variables);
templateEngine.renderToFile(templatePrefix + "/application-dev.yml.vm",
resourcesDir.resolve("application-dev.yml"), variables);
templateEngine.renderToFile(templatePrefix + "/application-local.yml.vm",
resourcesDir.resolve("application-local.yml"), variables);
}
/**
* 获取项目根路径
*
* @return 项目根路径
*/
protected static Path getProjectRoot() {
return Paths.get("").toAbsolutePath();
}
/**
* 输出完成信息
*
* @param names 名称数组
* @param itemType 模块类型(如 "模块" 或 "服务器"
* @param modulePattern XML模块模式
*/
protected static void printCompletionInfo(String[] names, String itemType, String modulePattern) {
System.out.println("\n所有" + itemType + "创建完成!");
System.out.println("请手动将以下" + itemType + "添加到根 pom.xml 的 <modules> 标签中:");
for (String name : names) {
name = name.trim();
if (!name.isEmpty()) {
String dashName = camelToKebabCase(name);
System.out.println("<module>" + modulePattern.replace("{name}", dashName) + "</module>");
}
}
}
/**
* 批量创建项目
*
* @param names 名称数组
* @param author 作者
* @param startPort 起始端口
* @param itemType 项目类型描述
* @throws IOException IO异常
*/
public void batchCreate(String[] names, String author, int startPort, String itemType) throws IOException {
Path projectRoot = getProjectRoot();
for (int i = 0; i < names.length; i++) {
String name = names[i].trim();
if (name.isEmpty()) {
continue;
}
int port = startPort + i;
System.out.println("\n=== 开始创建" + itemType + ": " + name + " (端口: " + port + ") ===");
createSingle(projectRoot, name, author, port);
}
}
/**
* 创建单个项目的抽象方法,由子类实现
*
* @param projectRoot 项目根路径
* @param name 名称
* @param author 作者
* @param port 端口
* @throws IOException IO异常
*/
protected abstract void createSingle(Path projectRoot, String name, String author, int port) throws IOException;
}

View File

@@ -3,13 +3,9 @@ package cn.iocoder.yudao.framework.test.core.ut;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.HashMap;
import java.util.Map;
import java.util.Scanner;
import static cn.iocoder.yudao.framework.test.core.ut.GeneratorUtils.camelToKebabCase;
import static cn.iocoder.yudao.framework.test.core.ut.GeneratorUtils.capitalize;
/**
* Yudao 模块代码生成器 - 使用 VM 模板
@@ -21,82 +17,49 @@ import static cn.iocoder.yudao.framework.test.core.ut.GeneratorUtils.capitalize;
*
* @author ZT
*/
public class ModuleGenerator {
private static final TemplateEngine templateEngine = new TemplateEngine();
public class ModuleGenerator extends BaseGenerator {
public static void main(String[] args) throws IOException {
ModuleGenerator generator = new ModuleGenerator();
// 1. 获取用户输入
Scanner scanner = new Scanner(System.in);
System.out.print("请输入新模块的名称支持多个模块用逗号分割例如order,userManagement,payment: ");
String moduleNames = scanner.nextLine();
System.out.print("请输入作者名称例如yudao: ");
String author = scanner.nextLine();
System.out.print("请输入起始端口号例如8080: ");
int startPort = Integer.parseInt(scanner.nextLine());
scanner.close();
Map<String, Object> input = getUserInput("请输入新模块的名称支持多个模块用逗号分割例如order,userManagement,payment: ");
String moduleNames = (String) input.get("names");
String author = (String) input.get("author");
int startPort = (Integer) input.get("startPort");
// 分割模块名
String[] modules = moduleNames.split(",");
// 2. 定义项目根路径
Path projectRoot = Paths.get("").toAbsolutePath();
// 3. 批量创建模块
for (int i = 0; i < modules.length; i++) {
String moduleName = modules[i].trim(); // 去除空格
if (moduleName.isEmpty()) {
continue;
}
// 计算当前模块的端口号:起始端口 + 当前模块索引
int modulePort = startPort + i;
System.out.println("\n=== 开始创建模块: " + moduleName + " (端口: " + modulePort + ") ===");
createSingleModule(projectRoot, moduleName, author, modulePort);
}
// 2. 批量创建模块
generator.batchCreate(modules, author, startPort, "模块");
System.out.println("\n所有模块创建完成!");
System.out.println("请手动将以下模块添加到根 pom.xml 的 <modules> 标签中:");
for (String moduleName : modules) {
moduleName = moduleName.trim();
if (!moduleName.isEmpty()) {
String dashModuleName = camelToKebabCase(moduleName);
System.out.println("<module>yudao-module-" + dashModuleName + "</module>");
}
}
// 3. 输出完成信息
printCompletionInfo(modules, "模块", "yudao-module-{name}");
}
private static void createSingleModule(Path projectRoot, String moduleName, String author, int port) throws IOException {
@Override
protected void createSingle(Path projectRoot, String moduleName, String author, int port) throws IOException {
// 将小驼峰转换为短横线分割的模块名
String dashModuleName = camelToKebabCase(moduleName);
// packageName 应该是去掉短横线的版本,用于 Java 包名
String packageName = dashModuleName.replace("-", "");
String capitalizedModuleName = capitalize(packageName);
// 定义新模块路径
Path newModuleDir = projectRoot.resolve("yudao-module-" + dashModuleName);
if (Files.exists(newModuleDir)) {
System.err.println("警告:模块 '" + dashModuleName + "' 已存在于 " + newModuleDir + ",跳过创建");
if (checkDirectoryExists(newModuleDir, dashModuleName)) {
return;
}
System.out.println("将在以下位置创建新模块: " + newModuleDir);
// 准备模板变量
Map<String, Object> variables = new HashMap<>();
Map<String, Object> variables = createBaseVariables(moduleName, author, port);
variables.put("moduleName", moduleName);
variables.put("dashModuleName", dashModuleName);
variables.put("packageName", packageName);
variables.put("capitalizedModuleName", capitalizedModuleName);
variables.put("baseName", dashModuleName.toLowerCase()); // 使用 dashModuleName 的小写版本
variables.put("applicationClassName", capitalizedModuleName + "ServerApplication");
variables.put("basePackage", "cn.iocoder.yudao");
variables.put("author", author);
variables.put("port", port);
variables.put("moduleDescription", capitalizedModuleName + " 模块");
variables.put("capitalizedModuleName", variables.get("capitalizedName"));
variables.put("moduleDescription", variables.get("capitalizedName") + " 模块");
variables.put("applicationClassName", variables.get("capitalizedName") + "ServerApplication");
// 创建模块结构
createModuleStructure(newModuleDir, variables);
@@ -104,11 +67,11 @@ public class ModuleGenerator {
System.out.println("模块 '" + dashModuleName + "' 创建成功!");
}
private static void createModuleStructure(Path moduleDir, Map<String, Object> variables) throws IOException {
private void createModuleStructure(Path moduleDir, Map<String, Object> variables) throws IOException {
String dashModuleName = (String) variables.get("dashModuleName");
String packageName = (String) variables.get("packageName");
String basePackage = (String) variables.get("basePackage");
String capitalizedModuleName = (String) variables.get("capitalizedModuleName");
String capitalizedModuleName = (String) variables.get("capitalizedName");
String applicationClassName = (String) variables.get("applicationClassName");
String baseName = (String) variables.get("baseName");
@@ -151,7 +114,7 @@ public class ModuleGenerator {
Files.createDirectories(serverJavaDir);
// Controller 目录
Path controllerDir = serverJavaDir.resolve("controller/admin").resolve(baseName);
Path controllerDir = serverJavaDir.resolve("controller/admin").resolve(packageName);
Files.createDirectories(controllerDir);
// Security 配置目录

View File

@@ -3,12 +3,8 @@ package cn.iocoder.yudao.framework.test.core.ut;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.HashMap;
import java.util.Map;
import java.util.Scanner;
import static cn.iocoder.yudao.framework.test.core.ut.GeneratorUtils.capitalize;
import static cn.iocoder.yudao.framework.test.core.ut.GeneratorUtils.toPascalCase;
/**
@@ -21,86 +17,57 @@ import static cn.iocoder.yudao.framework.test.core.ut.GeneratorUtils.toPascalCas
*
* @author ZT
*/
public class ServerGenerator {
public class ServerGenerator extends BaseGenerator {
private static final String BASE_PACKAGE_PREFIX = "cn.iocoder.yudao.";
private static final TemplateEngine templateEngine = new TemplateEngine();
public static void main(String[] args) throws IOException {
ServerGenerator generator = new ServerGenerator();
// 1. 获取用户输入
Scanner scanner = new Scanner(System.in);
System.out.print("请输入新 Server 的基础名称支持多个服务器用逗号分割例如demo,admin,api: ");
String baseNames = scanner.nextLine();
System.out.print("请输入作者名称例如yudao: ");
String author = scanner.nextLine();
System.out.print("请输入起始端口号例如8080: ");
int startPort = Integer.parseInt(scanner.nextLine());
scanner.close();
Map<String, Object> input = getUserInput("请输入新 Server 的基础名称支持多个服务器用逗号分割例如demo,admin,api: ");
String baseNames = (String) input.get("names");
String author = (String) input.get("author");
int startPort = (Integer) input.get("startPort");
// 分割服务名
String[] servers = baseNames.split(",");
// 2. 定义项目根路径
Path projectRoot = Paths.get("").toAbsolutePath();
// 3. 批量创建服务器
for (int i = 0; i < servers.length; i++) {
String baseName = servers[i].trim(); // 去除空格
if (baseName.isEmpty()) {
continue;
}
String serverName = baseName + "-server";
// 计算当前服务器的端口号:起始端口 + 当前服务器索引
int serverPort = startPort + i;
System.out.println("\n=== 开始创建 Server: " + serverName + " (端口: " + serverPort + ") ===");
createSingleServer(projectRoot, serverName, baseName, author, serverPort);
}
// 2. 批量创建服务器
generator.batchCreate(servers, author, startPort, "服务器");
System.out.println("\n所有服务器创建完成!");
System.out.println("请手动将以下模块添加到根 pom.xml 的 <modules> 标签中:");
for (String baseName : servers) {
baseName = baseName.trim();
if (!baseName.isEmpty()) {
String serverName = baseName + "-server";
System.out.println("<module>" + serverName + "</module>");
}
}
// 3. 输出完成信息
printCompletionInfo(servers, "服务器", "{name}-server");
}
private static void createSingleServer(Path projectRoot, String serverName, String baseName, String author, int port) throws IOException {
String packageName = serverName.replace("-", "");
String capitalizedName = toPascalCase(serverName);
String capitalizedBaseName = capitalize(baseName);
@Override
protected void createSingle(Path projectRoot, String baseName, String author, int port) throws IOException {
String serverName = baseName + "-server";
// 定义新 Server 路径
Path newServerDir = projectRoot.resolve(serverName);
if (Files.exists(newServerDir)) {
System.err.println("警告Server '" + serverName + "' 已存在于 '" + newServerDir + "',跳过创建。");
if (checkDirectoryExists(newServerDir, serverName)) {
return;
}
System.out.println("将在以下位置创建新 Server: " + newServerDir);
// 准备模板变量
Map<String, Object> variables = new HashMap<>();
Map<String, Object> variables = createBaseVariables(baseName, author, port);
variables.put("serverName", serverName);
variables.put("baseName", baseName);
variables.put("capitalizedBaseName", capitalizedBaseName);
variables.put("packageName", packageName);
variables.put("applicationClassName", capitalizedName + "Application");
variables.put("basePackage", BASE_PACKAGE_PREFIX.substring(0, BASE_PACKAGE_PREFIX.length() - 1)); // 去掉末尾的点
variables.put("author", author);
variables.put("port", port);
variables.put("serverDescription", capitalizedBaseName + " 服务器");
variables.put("capitalizedBaseName", variables.get("capitalizedName"));
variables.put("serverDescription", variables.get("capitalizedName") + " 服务器");
variables.put("applicationClassName", toPascalCase(serverName) + "Application");
// 创建目录结构和文件
createServerStructure(newServerDir, variables);
System.out.println("Server '" + serverName + "' 创建成功!");
}
private static void createServerStructure(Path serverDir, Map<String, Object> variables) throws IOException {
private void createServerStructure(Path serverDir, Map<String, Object> variables) throws IOException {
String packageName = (String) variables.get("packageName");
String basePackage = (String) variables.get("basePackage");
String baseName = (String) variables.get("baseName");
@@ -116,7 +83,7 @@ public class ServerGenerator {
Files.createDirectories(javaSourceDir);
// 创建控制器目录
Path controllerDir = javaSourceDir.resolve("controller").resolve(baseName);
Path controllerDir = javaSourceDir.resolve("controller").resolve(packageName);
Files.createDirectories(controllerDir);
// 创建资源目录
@@ -138,18 +105,11 @@ public class ServerGenerator {
controllerDir.resolve(controllerClassName + ".java"), variables);
// 4. 配置文件
templateEngine.renderToFile("generator/server/application.yml.vm",
resourcesDir.resolve("application.yml"), variables);
templateEngine.renderToFile("generator/server/application-dev.yml.vm",
resourcesDir.resolve("application-dev.yml"), variables);
templateEngine.renderToFile("generator/server/application-local.yml.vm",
resourcesDir.resolve("application-local.yml"), variables);
renderConfigFiles(resourcesDir, "generator/server", variables);
// 5. Dockerfile
templateEngine.renderToFile("generator/server/Dockerfile.vm",
serverDir.resolve("Dockerfile"), variables);
System.out.println("Server '" + variables.get("serverName") + "' 创建成功!");
}
}

View File

@@ -1,4 +1,4 @@
package ${basePackage}.module.${packageName}.controller.admin.${baseName};
package ${basePackage}.module.${packageName}.controller.admin.${packageName};
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;

View File

@@ -1,4 +1,4 @@
package ${basePackage}.${packageName}.controller.${baseName};
package ${basePackage}.${packageName}.controller.${packageName};
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;