提交 f5789d4d 编写于 作者: 黄勇

【I】代码重构

上级 2ad839cb
Smart Generator
注意:目前只能生成 MySQL 数据库脚本。
使用方法
1. 修改 src/main/resources/db.xls 文件,填写表结构文档。
2. 修改 src/main/resources/config.properties 文件,指定输出路径与包名。
3. 运行 com.smart.generator.Generator 类的 main() 方法,生成相关的代码。
\ No newline at end of file
......@@ -113,10 +113,6 @@
<filters>
<filter>
<artifact>*:*</artifact>
<includes>
<include>**/*.class</include>
<include>**/*.properties</include>
</includes>
<excludes>
<exclude>com/smart/**/*.class</exclude>
<exclude>log4j.properties</exclude>
......
package com.smart.generator;
import com.smart.framework.util.FileUtil;
import com.smart.framework.util.StringUtil;
import com.smart.generator.bean.Column;
import com.smart.generator.bean.Table;
import com.smart.generator.builder.Builder;
import com.smart.generator.builder.EntityBuilder;
import com.smart.generator.builder.SQLBuilder;
import java.io.File;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import jxl.Sheet;
import jxl.Workbook;
import org.apache.log4j.Logger;
public class Generator {
private static final Logger logger = Logger.getLogger(Generator.class);
private static final Properties config = FileUtil.loadPropFile("config.properties");
public static void main(String[] args) throws Exception {
Generator generator = new Generator();
generator.generate();
}
public void generate() {
// TODO 重构
String inputPath = "D:\\Workspace\\smart\\smart-generator\\db.xls";
String outputPath = "D:\\Workspace\\smart\\smart-generator\\gen";
String packageName = "com.smart.sample.entity";
Map<Table, List<Column>> tableMap = createTableMap(inputPath);
Builder sqlBuilder = new SQLBuilder(outputPath, tableMap);
sqlBuilder.build();
Builder entityBuilder = new EntityBuilder(outputPath, tableMap, packageName);
entityBuilder.build();
}
private Map<Table, List<Column>> createTableMap(String inputPath) {
Map<Table, List<Column>> tableMap = new LinkedHashMap<Table, List<Column>>();
try {
File file = new File(inputPath);
Workbook workbook = Workbook.getWorkbook(file);
for (int i = 1; i < workbook.getNumberOfSheets(); i++) {
Sheet sheet = workbook.getSheet(i);
String tableName = sheet.getName().toLowerCase();
String tablePK = "";
List<Column> columnList = new ArrayList<Column>();
for (int row = 1; row < sheet.getRows(); row++) {
String name = sheet.getCell(0, row).getContents().trim();
String type = sheet.getCell(1, row).getContents().trim();
String length = sheet.getCell(2, row).getContents().trim();
String precision = sheet.getCell(3, row).getContents().trim();
String notnull = sheet.getCell(4, row).getContents().trim();
String pk = sheet.getCell(5, row).getContents().trim();
String comment = sheet.getCell(6, row).getContents().trim();
columnList.add(new Column(name, type, length, precision, notnull, pk, comment));
if (StringUtil.isNotEmpty(pk)) {
tablePK = name;
}
}
tableMap.put(new Table(tableName, tablePK), columnList);
}
workbook.close();
} catch (Exception e) {
logger.error("创建 Table 数据出错!", e);
throw new RuntimeException(e);
}
return tableMap;
}
}
......@@ -4,6 +4,8 @@ import com.smart.framework.util.ArrayUtil;
import com.smart.framework.util.StringUtil;
import com.smart.generator.util.VelocityUtil;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.Properties;
import org.apache.log4j.Logger;
......@@ -73,16 +75,26 @@ public abstract class Command {
public void postGenerate() {
}
protected final String getAppName(String appPath) {
return getConfigProperty(appPath, "app");
}
protected final String getAppPackage(String appPath) {
String appPackage;
return getConfigProperty(appPath, "package");
}
private String getConfigProperty(String appPath, String property) {
String appName;
try {
Properties config = new Properties();
config.load(new FileInputStream(appPath + "/src/main/resources/config.properties"));
appPackage = config.getProperty("package");
} catch (Exception e) {
throw new RuntimeException("无法获取应用包名!");
appName = config.getProperty(property);
} catch (FileNotFoundException e) {
throw new RuntimeException("无法找到 config.properties 文件!");
} catch (IOException e) {
throw new RuntimeException("加载 config.properties 文件出错!");
}
return appPackage;
return appName;
}
protected final String getCamelhumpName(String name) {
......@@ -96,4 +108,19 @@ public abstract class Command {
}
return name;
}
protected final String getDisplayName(String name) {
String displayName = "";
name = name.trim().toLowerCase();
if (name.contains("-")) {
String[] words = StringUtil.splitString(name, "-");
for (String word : words) {
displayName += StringUtil.firstToUpper(word) + " ";
}
displayName = displayName.trim();
} else {
displayName = StringUtil.firstToUpper(name);
}
return displayName;
}
}
package com.smart.generator.command;
package com.smart.generator.command.impl;
import com.smart.generator.command.Command;
import com.smart.generator.util.VelocityUtil;
import java.util.HashMap;
import java.util.Map;
......@@ -45,7 +46,7 @@ public class CreateActionCommand extends Command {
// 生成文件
String vmPath = "create-action/action.java.vm";
String filePath = appPath + "/src/main/java/" + packageName + "/action/" + actionNameCamelhump + ".java";
String filePath = appPath + "/src/main/java/" + packageName + "/action/" + actionNameCamelhump + "Action.java";
VelocityUtil.mergeTemplateIntoFile(vmPath, dataMap, filePath);
}
}
package com.smart.generator.command;
package com.smart.generator.command.impl;
import com.smart.framework.util.FileUtil;
import com.smart.framework.util.StringUtil;
import com.smart.generator.command.Command;
import com.smart.generator.util.VelocityUtil;
import java.util.HashMap;
import java.util.Map;
......@@ -102,6 +103,7 @@ public class CreateAppCommand extends Command {
private void generateConfigFileForMain(String dbName) {
// 创建数据
Map<String, Object> dataMap = new HashMap<String, Object>();
dataMap.put("app_name", appName);
dataMap.put("app_package", appPackage);
dataMap.put("db_name", dbName);
......@@ -114,6 +116,7 @@ public class CreateAppCommand extends Command {
private void generateConfigFileForTest(String dbName) {
// 创建数据
Map<String, Object> dataMap = new HashMap<String, Object>();
dataMap.put("app_name", appName);
dataMap.put("app_package", appPackage);
dataMap.put("db_name", dbName + "_test");
......
package com.smart.generator.command.impl;
import com.smart.generator.command.Command;
public class CreateCRUDCommand extends Command {
private String appPath;
private String crudName;
@Override
public int getParamsLength() {
return 2;
}
@Override
public void initVariables(String... params) {
// 获取命令参数
appPath = params[0];
crudName = params[1];
}
@Override
public void generateFiles() {
// 创建 Entity
generateEntity();
// 创建 Service
generateService();
// 创建 Action
generateAction();
// 创建 Page
generatePage();
}
private void generateEntity() {
Command command = new CreateEntityCommand();
command.initVariables(appPath, crudName);
command.generateFiles();
}
private void generateService() {
Command command = new CreateServiceCommand();
command.initVariables(appPath, crudName);
command.generateFiles();
}
private void generateAction() {
Command command = new CreateActionCommand();
command.initVariables(appPath, crudName);
command.generateFiles();
}
private void generatePage() {
String[] pageNames = {
crudName,
crudName + "-create",
crudName + "-edit",
crudName + "-view",
};
Command command;
for (String pageName : pageNames) {
command = new CreatePageCommand();
command.initVariables(appPath, pageName);
command.generateFiles();
}
}
}
package com.smart.generator.command;
package com.smart.generator.command.impl;
import com.smart.generator.command.Command;
import com.smart.generator.util.VelocityUtil;
import java.util.HashMap;
import java.util.Map;
......
package com.smart.generator.command;
package com.smart.generator.command.impl;
import com.smart.generator.command.Command;
import com.smart.generator.util.VelocityUtil;
import java.util.HashMap;
import java.util.Map;
......@@ -28,17 +29,22 @@ public class CreatePageCommand extends Command {
}
private void generatePage() {
// // 定义相关变量
// String pageNameUnderline = getUnderlineName(pageName);
//
// // 创建数据
// Map<String, Object> dataMap = new HashMap<String, Object>();
// dataMap.put("app_name_d", appNameDisplay);
// dataMap.put("page_name_d", pageNameDisplay);
//
// // 生成文件
// String vmPath = "create-page/entity.java.vm";
// String filePath = appPath + "/src/main/webapp/www/page/" + pageNameUnderline + ".html";
// VelocityUtil.mergeTemplateIntoFile(vmPath, dataMap, filePath);
// 获取应用名称
String appName = getAppName(appPath);
// 定义相关变量
String appNameDisplay = getDisplayName(appName);
String pageNameDisplay = getDisplayName(pageName);
String pageNameUnderline = getUnderlineName(pageName);
// 创建数据
Map<String, Object> dataMap = new HashMap<String, Object>();
dataMap.put("app_name_d", appNameDisplay);
dataMap.put("page_name_d", pageNameDisplay);
// 生成文件
String vmPath = "create-page/page.html.vm";
String filePath = appPath + "/src/main/webapp/www/page/" + pageNameUnderline + ".html";
VelocityUtil.mergeTemplateIntoFile(vmPath, dataMap, filePath);
}
}
package com.smart.generator.command;
package com.smart.generator.command.impl;
import com.smart.generator.command.Command;
import com.smart.generator.util.VelocityUtil;
import java.util.HashMap;
import java.util.Map;
......@@ -44,14 +45,14 @@ public class CreateServiceCommand extends Command {
private void generateServiceInterface(String packageName, String serviceNameCamelhump, Map<String, Object> dataMap) {
// 生成 Service 接口
String vmPath = "create-service/service.java.vm";
String filePath = appPath + "/src/main/java/" + packageName + "/service/" + serviceNameCamelhump + ".java";
String filePath = appPath + "/src/main/java/" + packageName + "/service/" + serviceNameCamelhump + "Service.java";
VelocityUtil.mergeTemplateIntoFile(vmPath, dataMap, filePath);
}
private void generateServiceImplement(String packageName, String serviceNameCamelhump, Map<String, Object> dataMap) {
// 生成 Service 实现
String vmPath = "create-service/service.impl.java.vm";
String filePath = appPath + "/src/main/java/" + packageName + "/service/impl/" + serviceNameCamelhump + "Impl.java";
String filePath = appPath + "/src/main/java/" + packageName + "/service/impl/" + serviceNameCamelhump + "ServiceImpl.java";
VelocityUtil.mergeTemplateIntoFile(vmPath, dataMap, filePath);
}
}
package com.smart.generator.command.impl;
import com.smart.framework.util.StringUtil;
import com.smart.generator.bean.Column;
import com.smart.generator.bean.Table;
import com.smart.generator.command.impl.builder.Builder;
import com.smart.generator.command.impl.builder.impl.EntityBuilder;
import com.smart.generator.command.impl.builder.impl.SQLBuilder;
import com.smart.generator.command.Command;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import jxl.Sheet;
import jxl.Workbook;
import jxl.read.biff.BiffException;
import org.apache.log4j.Logger;
public class LoadDictCommand extends Command {
private static final Logger logger = Logger.getLogger(LoadDictCommand.class);
private String appPath;
private String dictPath;
@Override
public int getParamsLength() {
// 返回参数个数
return 2;
}
@Override
public void initVariables(String... params) {
// 获取命令参数
appPath = params[0];
dictPath = params[1];
}
@Override
public void generateFiles() {
// 获取应用信息
String appName = getAppName(appPath);
String appPackage = getAppPackage(appPath);
// 获取 Excel 表格数据
Map<Table, List<Column>> tableMap = createTableMap(dictPath);
// 生成 SQL
generateSQL(tableMap, appName);
// 生成 Enttiy
generateEntity(tableMap, appPackage);
}
private void generateSQL(Map<Table, List<Column>> tableMap, String appName) {
// 获取相关数据
String outputPath = appPath + "/doc";
// 生成代码
Builder sqlBuilder = new SQLBuilder(outputPath, tableMap, appName);
sqlBuilder.build();
}
private void generateEntity(Map<Table, List<Column>> tableMap, String appPackage) {
// 获取相关数据
String outputPath = appPath + "/src/main/java/" + appPackage.replace('.', '/') + "/entity";
String packageName = appPackage + ".entity";
// 生成代码
Builder entityBuilder = new EntityBuilder(outputPath, tableMap, packageName);
entityBuilder.build();
}
private Map<Table, List<Column>> createTableMap(String inputPath) {
// 定义一个 Table Map,用于建立表与列的一对多映射关系
Map<Table, List<Column>> tableMap = new LinkedHashMap<Table, List<Column>>();
// 定义 Workbook,表示整个 Excel 文件
Workbook workbook = null;
try {
// 获取 Workbook
workbook = Workbook.getWorkbook(new File(inputPath));
// 处理 Workbook
handleWorkbook(workbook, tableMap);
} catch (IOException e) {
logger.error("读取 Excel 出错!", e);
throw new RuntimeException(e);
} catch (BiffException e) {
logger.error("解析 Excel 出错!", e);
throw new RuntimeException(e);
} finally {
// 释放资源
if (workbook != null) {
workbook.close();
}
}
return tableMap;
}
private void handleWorkbook(Workbook workbook, Map<Table, List<Column>> tableMap) {
// 读取 Workbook(从第二个开始)
for (int i = 1; i < workbook.getNumberOfSheets(); i++) {
// 获取 Sheet
Sheet sheet = workbook.getSheet(i);
// 处理 Sheet
handleSheet(sheet, tableMap);
}
}
private void handleSheet(Sheet sheet, Map<Table, List<Column>> tableMap) {
// 获取表名
String tableName = sheet.getName().toLowerCase();
// 定义表主键
String tablePK = "";
// 定义一个 Column List,用于封装 Sheet 数据
List<Column> columnList = new ArrayList<Column>();
// 读取 Sheet(从第二行开始)
for (int row = 1; row < sheet.getRows(); row++) {
// 获取 Cell 数据
String name = getData(sheet, 0, row);
String type = getData(sheet, 1, row);
String length = getData(sheet, 2, row);
String precision = getData(sheet, 3, row);
String notnull = getData(sheet, 4, row);
String pk = getData(sheet, 5, row);
String comment = getData(sheet, 6, row);
// 将 Cell 数据封装为 Column,并添加到 Column List 中
columnList.add(new Column(name, type, length, precision, notnull, pk, comment));
// 初始化表主键
if (StringUtil.isNotEmpty(pk)) {
tablePK = name;
}
}
// 将 Sheet 数据封装为 Table,并添加到 Table Map 中
tableMap.put(new Table(tableName, tablePK), columnList);
}
private String getData(Sheet sheet, int column, int row) {
// 获取 Cell 数据,去除了前后空格
return sheet.getCell(column, row).getContents().trim();
}
}
package com.smart.generator.builder;
package com.smart.generator.command.impl.builder;
import com.smart.generator.bean.Column;
import com.smart.generator.bean.Table;
......@@ -15,12 +15,5 @@ public abstract class Builder {
this.tableMap = tableMap;
}
public final void build() {
createFile();
generateCode();
}
public abstract void createFile();
public abstract void generateCode();
public abstract void build();
}
package com.smart.generator.builder;
package com.smart.generator.command.impl.builder.impl;
import com.smart.framework.util.FileUtil;
import com.smart.framework.util.StringUtil;
import com.smart.generator.bean.Column;
import com.smart.generator.bean.Field;
import com.smart.generator.bean.Table;
import com.smart.generator.command.impl.builder.Builder;
import com.smart.generator.util.VelocityUtil;
import java.util.ArrayList;
import java.util.Arrays;
......@@ -44,7 +45,6 @@ public class EntityBuilder extends Builder {
typeMap.put("text", "String");
}
private String javaPath = outputPath + "/java";
private String packageName;
public EntityBuilder(String outputPath, Map<Table, List<Column>> tableMap, String packageName) {
......@@ -53,30 +53,33 @@ public class EntityBuilder extends Builder {
}
@Override
public void createFile() {
FileUtil.createFile(javaPath);
}
public void build() {
FileUtil.createFile(outputPath);
@Override
public void generateCode() {
for (Map.Entry<Table, List<Column>> entry : tableMap.entrySet()) {
// 定义相关变量
Table table = entry.getKey();
String tableName = table.getName();
String entityName = StringUtil.firstToUpper(StringUtil.toCamelhump(tableName));
List<Column> columnList = entry.getValue();
List<Field> fieldList = transformFieldList(columnList);
// 创建数据
Map<String, Object> dataMap = new HashMap<String, Object>();
dataMap.put("packageName", packageName);
dataMap.put("entityName", entityName);
dataMap.put("fieldList", fieldList);
dataMap.put("StringUtil", new StringUtil());
VelocityUtil.mergeTemplateIntoFile("vm/init-app/entity.java.vm", dataMap, javaPath + "/" + entityName + ".java");
// 生成文件
String vmPath = "load-dict/entity.java.vm";
String filePath = outputPath + "/" + entityName + ".java";
VelocityUtil.mergeTemplateIntoFile(vmPath, dataMap, filePath);
}
}
private List<Field> transformFieldList(List<Column> columnList) {
// 将 Column List 转换为 Field List
List<Field> fieldList = new ArrayList<Field>(columnList.size());
for (Column column : columnList) {
String fieldName = this.transformFieldName(column.getName());
......@@ -88,6 +91,7 @@ public class EntityBuilder extends Builder {
}
private String transformFieldName(String columnName) {
// 将 Column Name 转换为 Field Name
String fieldName;
if (keywordList.contains(columnName)) {
fieldName = columnName + "_";
......@@ -98,6 +102,7 @@ public class EntityBuilder extends Builder {
}
private String transformFieldType(String columnType) {
// 将 Column Type 转换为 Field Type
String fieldType;
if (typeMap.containsKey(columnType)) {
fieldType = typeMap.get(columnType);
......
package com.smart.generator.builder;
package com.smart.generator.command.impl.builder.impl;
import com.smart.framework.util.FileUtil;
import com.smart.generator.bean.Column;
import com.smart.generator.bean.Table;
import com.smart.generator.command.impl.builder.Builder;
import com.smart.generator.util.VelocityUtil;
import java.util.HashMap;
import java.util.List;
......@@ -10,22 +11,22 @@ import java.util.Map;
public class SQLBuilder extends Builder {
private String sqlPath = outputPath + "/sql";
private String appName;
public SQLBuilder(String outputPath, Map<Table, List<Column>> tableMap) {
public SQLBuilder(String outputPath, Map<Table, List<Column>> tableMap, String appName) {
super(outputPath, tableMap);
this.appName = appName;
}
@Override
public void createFile() {
FileUtil.createFile(sqlPath);
}
public void build() {
FileUtil.createFile(outputPath);
@Override
public void generateCode() {
Map<String, Object> dataMap = new HashMap<String, Object>();
dataMap.put("tableMap", tableMap);
VelocityUtil.mergeTemplateIntoFile("vm/init-app/table.sql.vm", dataMap, sqlPath + "/schema.sql");
String vmPath = "load-dict/table.sql.vm";
String filePath = outputPath + "/" + appName + ".sql";
VelocityUtil.mergeTemplateIntoFile(vmPath, dataMap, filePath);
}
}
package com.smart.generator.test;
import com.smart.generator.command.CreateActionCommand;
import com.smart.generator.command.CreateAppCommand;
import com.smart.generator.command.CreateEntityCommand;
import com.smart.generator.command.CreateServiceCommand;
import com.smart.generator.command.impl.CreateActionCommand;
import com.smart.generator.command.impl.CreateAppCommand;
import com.smart.generator.command.impl.CreateCRUDCommand;
import com.smart.generator.command.impl.CreateEntityCommand;
import com.smart.generator.command.impl.CreatePageCommand;
import com.smart.generator.command.impl.CreateServiceCommand;
import com.smart.generator.command.Invoker;
import com.smart.generator.command.impl.LoadDictCommand;
import org.junit.Test;
public class CommandTest {
@Test
public void createAppTest() {
public void createAppCommandTest() {
Invoker invoker = new Invoker();
invoker.setCommand(new CreateAppCommand()); // smart create-app
......@@ -18,7 +21,6 @@ public class CommandTest {
"C:\\Smart", // Current Path
"demo", // App Name
"com.smart", // App Group
"demo", // App Artifact = <App Name>
"com.smart.demo" // App Package = <App Group> + <App Artifact>
};
......@@ -29,9 +31,9 @@ public class CommandTest {
}
@Test
public void createEntityTest() {
public void createEntityCommandTest() {
Invoker invoker = new Invoker();
invoker.setCommand(new CreateEntityCommand()); // smart create-entity
invoker.setCommand(new CreateEntityCommand()); // smart create-entity <entity-name>
String[] params = {
"C:\\Smart\\demo", // Current Path
......@@ -45,9 +47,9 @@ public class CommandTest {
}
@Test
public void createServiceTest() {
public void createServiceCommandTest() {
Invoker invoker = new Invoker();
invoker.setCommand(new CreateServiceCommand()); // smart create-service
invoker.setCommand(new CreateServiceCommand()); // smart create-service <service-name>
String[] params = {
"C:\\Smart\\demo", // Current Path
......@@ -61,9 +63,9 @@ public class CommandTest {
}
@Test
public void createActionTest() {
public void createActionCommandTest() {
Invoker invoker = new Invoker();
invoker.setCommand(new CreateActionCommand()); // smart create-action
invoker.setCommand(new CreateActionCommand()); // smart create-action <action-name>
String[] params = {
"C:\\Smart\\demo", // Current Path
......@@ -75,4 +77,52 @@ public class CommandTest {
System.err.println("执行命令出错!");
}
}
@Test
public void createPageCommandTest() {
Invoker invoker = new Invoker();
invoker.setCommand(new CreatePageCommand()); // smart create-page <page-name>
String[] params = {
"C:\\Smart\\demo", // Current Path
"product", // Page Name
};
boolean result = invoker.execCommand(params);
if (!result) {
System.err.println("执行命令出错!");
}
}
@Test
public void createCRUDCommandTest() {
Invoker invoker = new Invoker();
invoker.setCommand(new CreateCRUDCommand()); // smart create-crud <crud-name>
String[] params = {
"C:\\Smart\\demo", // Current Path
"product", // Page Name
};
boolean result = invoker.execCommand(params);
if (!result) {
System.err.println("执行命令出错!");
}
}
@Test
public void loadDictCommandTest() {
Invoker invoker = new Invoker();
invoker.setCommand(new LoadDictCommand()); // smart load-dict <dict-path>
String[] params = {
"C:\\Smart\\demo", // Current Path
"C:\\Smart\\db.xls", // Dict Path
};
boolean result = invoker.execCommand(params);
if (!result) {
System.err.println("执行命令出错!");
}
}
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册