Commit f2142f8a by 仲光辉

蛋壳创意科技--代码生成器(简易版) at 2020-10-30 14:33 ZGH.MercyModest

parents
# Created by .ignore support plugin (hsz.mobi)
### Java template
# Compiled class file
*.class
# Log file
*.log
# BlueJ files
*.ctxt
# Mobile Tools for Java (J2ME)
.mtj.tmp/
# Package Files #
*.jar
*.war
*.nar
*.ear
*.zip
*.tar.gz
*.rar
# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
hs_err_pid*
.idea
*.iml
target
# 蛋壳创意科技-代码生成器(简易版)
## 使用方式
### 下载最新的模板代码(dankal-microservice-code-template-v1)
> [蛋壳-GitLab](http://git.dankal.cn/mercyModest/dankal-microservice-code-template-v1.git)
### 设置五大必须参数与一个行为控制参数
> - projectName :项目名称
> - basePackageName : 项目基础报名
> - projectDescription : 项目描述
> - templateProjectPath : 模板代码路径
> - projectCreatePath : 项目生成路径
> - isOverride : 项目名称已经存在的行为
### 执行 `CodeGenerator#mian` 方法
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>cn.dankal</groupId>
<artifactId>dankal-simple-code-util</artifactId>
<version>1.0-SNAPSHOT</version>
<description>蛋壳创意科技--微服务-简易代码生成器</description>
<dependencies>
<!--hutool-->
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-core</artifactId>
<version>5.4.6</version>
</dependency>
<!--lombok-->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.12</version>
</dependency>
<!--junit-test-->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13</version>
</dependency>
</dependencies>
</project>
\ No newline at end of file
package cn.dankal.code.util;
import cn.dankal.code.util.common.CodeUtil;
import cn.dankal.code.util.entity.ProjectInfo;
/**
* 代码生成器
*
* @author ZGH.MercyModest
* @version V1.0.0
* @create 2020/10/30
*/
public class CodeGenerator {
public static void main(String[] args) {
// 项目参数: 必须全部非空
// 项目名称
final String projectName = "tudgo-global-permissoon";
// 项目基础包名 etc. com.tudgo.global.permission
final String basePackageName = "com.tudgo.global.permission";
// 项目描述 etc.土地工权限管理系统
final String projectDescription = "土地工权限管理系统";
// 模板项目路径 : C:\dev\test 目前只支持一套模板[dankal-microservice-code-template-v1]
final String templateProjectPath = "C:/dev/test/dankal-microservice-code-template-v1";
// 项目生成路径 C:\dev\test
final String projectCreatePath = "C:/dev/test";
// 如果 项目目录已经存在( projectCreatePath/projectName ) 是否覆盖
final boolean isOverride = false;
//构建项目信息对象
ProjectInfo projectInfo = CodeUtil.builderProjectInfo(projectName, basePackageName, projectDescription, templateProjectPath, projectCreatePath, isOverride);
try {
// 执行模板代生成
CodeUtil.doGenerate(projectInfo);
System.out.println("代码生成成功");
} catch (Exception exception) {
System.out.printf("代码生成失败!!! errorMessage: %s", exception.getMessage());
System.exit(0);
}
}
}
package cn.dankal.code.util.builder;
import cn.dankal.code.util.entity.ProjectInfo;
/**
* 项目名称构建
*
* @author ZGH.MercyModest
* @version V1.0.0
* @create 2020/10/29
*/
public class ProjectInfoBuilder {
/**
* 构建一个 TemplateInfo 对象
*
* @return ProjectInfo
*/
public static ProjectInfo builder() {
return new ProjectInfo();
}
}
package cn.dankal.code.util.common;
import cn.dankal.code.util.builder.ProjectInfoBuilder;
import cn.dankal.code.util.entity.ProjectInfo;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.StrUtil;
import java.io.File;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Paths;
import java.util.List;
/**
* CodeUtil
*
* @author ZGH.MercyModest
* @version V1.0.0
* @create 2020/10/30
*/
public class CodeUtil {
/**
* 需要忽略不需要读取的文件(直接复制)
*/
public static final List<String> IGNORE_FILE_NAME_LIST;
/**
* 需要忽略的文件后缀:直接复制
*/
public static final List<String> IGNORE_FILE_SUFFIX;
static {
// 工具集合初始化
IGNORE_FILE_NAME_LIST = CollectionUtil.newArrayList(".gitignore");
IGNORE_FILE_SUFFIX = CollectionUtil.newArrayList(".yml");
}
/**
* 构建 项目信息对象并创建项目文件夹
*
* @param projectName 项目名称
* @param basePackageName 项目基础包名
* @param projectDescription 项目描述信息
* @param templateProjectPath 模板项目路径
* @param projectCreatePath 项目生成路径
* @param isOverride 如果项目目录已存在是否覆盖
* @return ProjectInfo
* @see ProjectInfo
*/
public static ProjectInfo builderProjectInfo(String projectName, String basePackageName, String projectDescription, String templateProjectPath, String projectCreatePath, boolean isOverride) {
// 参数校验
Assert.notBlank(projectName, () -> new IllegalArgumentException("项目名称为空"));
Assert.notBlank(basePackageName, () -> new IllegalArgumentException("项目基础包名为空"));
Assert.notBlank(projectDescription, () -> new IllegalArgumentException("请您写一句话描述当前项目"));
Assert.notBlank(projectCreatePath, () -> new IllegalArgumentException("项目生成路径为空"));
boolean contains = basePackageName.contains(".");
if (!contains) {
throw new IllegalArgumentException("请合理书写规范的Java基础包名: 只要需要二级目录. etc: cn.dankal");
}
// 项目生成路径是否合法
boolean isDirectory = FileUtil.isDirectory(projectCreatePath);
if (!isDirectory) {
throw new IllegalArgumentException("projectCreatePath 不是文件夹");
}
// 项目模板是否存在
boolean dirEmpty = FileUtil.isDirEmpty(Paths.get(templateProjectPath));
if (dirEmpty) {
throw new IllegalArgumentException("templateProjectPath 不合法 或者 templateProjectPath 为空");
}
//创建生成项目路径
String projectPath = projectCreatePath + File.separator + projectName;
File file = new File(projectPath);
if (file.exists()) {
if (!isOverride) {
// 退出提示
System.err.printf("项目目录已存在!!! 请核对您的方法入参: projectName: %s 或者将 isOverride 设置为 true 进行强行覆盖", projectName);
System.exit(0);
}
FileUtil.del(file);
}
boolean mkdir = file.mkdir();
if (!mkdir) {
throw new IllegalStateException("创建新项目目录失败");
}
return ProjectInfoBuilder.builder()
.setProjectName(projectName)
.setBasePackageName(basePackageName)
.setProjectDescription(projectDescription)
.setProjectCreatePath(projectCreatePath)
.setTemplateProjectPath(templateProjectPath)
.setProjectPath(projectPath);
}
/**
* 拷贝模板代码
* <br/>
* 适配模板: dankal-microservice-code-template-v1
*
* @param projectInfo projectInfo
* @throws IOException
* @see IOException
*/
public static void doGenerate(ProjectInfo projectInfo) throws IOException {
Assert.notNull(projectInfo, "projectInfo 为空");
// 遍历模板项目根目录
File templateProjectFile = new File(projectInfo.getTemplateProjectPath());
List<File> rootTemplateFileList = CollectionUtil.newArrayList(templateProjectFile.listFiles());
if (CollectionUtil.isEmpty(rootTemplateFileList)) {
throw new IllegalArgumentException("模板项目为空");
}
for (File file : rootTemplateFileList) {
if (file.isDirectory()) {
// 二级目录
CodeUtil.operateChildFolder(file, projectInfo);
continue;
}
// 根目录下的文件
boolean isDirectCopy = CodeUtil.IGNORE_FILE_NAME_LIST.contains(file.getName()) || CodeUtil.IGNORE_FILE_SUFFIX.contains("." + FileUtil.extName(file));
if (isDirectCopy) {
// 直接执行文件拷贝
String fileCanonicalPath = file.getCanonicalPath();
String newFilePath = projectInfo.getProjectPath() + File.separator + file.getName();
FileUtil.copy(fileCanonicalPath, newFilePath, true);
} else {
//按照模板生成新文件
CodeUtil.doFileCopy(file, projectInfo);
}
}
}
/**
* 执行文件内容替换 如果需要的话
*
* @param contentList 文件内容
* @param projectInfo ProjectInfo
*/
public static void doContentReplaceIfNecessary(List<String> contentList, ProjectInfo projectInfo) {
if (CollectionUtil.isEmpty(contentList)) {
return;
}
for (int i = 0; i < contentList.size(); i++) {
// 替换 projectName
replaceProjectNameIfNecessary(contentList, i, projectInfo);
// 替换 basePackageName
replaceBasePackageNameIfNecessary(contentList, i, projectInfo);
// 替换 projectDescription
replaceProjectDescriptionIfNecessary(contentList, i, projectInfo);
}
}
/**
* 替换 [projectName] 如果需要的话
*
* @param contentList 文件内容
* @param contentIndex 当前行内容索引
* @param projectInfo ProjectInfo
*/
private static void replaceProjectNameIfNecessary(List<String> contentList, int contentIndex, ProjectInfo projectInfo) {
String content = contentList.get(contentIndex);
if (StrUtil.isBlank(content)) {
return;
}
final String replaceStr = "[projectName]";
if (content.contains(replaceStr)) {
String projectName = projectInfo.getProjectName();
content = content.replace(replaceStr, projectName);
contentList.set(contentIndex, content);
}
}
/**
* 替换[basePackageName] 如果需要的话
*
* @param contentList 文件内容
* @param contentIndex 当前行内容索引
* @param projectInfo ProjectInfo
*/
private static void replaceBasePackageNameIfNecessary(List<String> contentList, int contentIndex, ProjectInfo projectInfo) {
String content = contentList.get(contentIndex);
if (StrUtil.isBlank(content)) {
return;
}
final String replaceStr = "[basePackageName]";
if (content.contains(replaceStr)) {
String basePackageName = projectInfo.getBasePackageName();
content = content.replace(replaceStr, basePackageName);
contentList.set(contentIndex, content);
}
}
/**
* 替换[projectDescription] 如果需要的话
*
* @param contentList 文件内容
* @param contentIndex 当前行内容索引
* @param projectInfo ProjectInfo
*/
private static void replaceProjectDescriptionIfNecessary(List<String> contentList, int contentIndex, ProjectInfo projectInfo) {
String content = contentList.get(contentIndex);
if (StrUtil.isBlank(content)) {
return;
}
final String replaceStr = "[projectDescription]";
if (content.contains(replaceStr)) {
String projectDescription = projectInfo.getProjectDescription();
content = content.replace(replaceStr, projectDescription);
contentList.set(contentIndex, content);
}
}
/**
* 文件拷贝
*
* @param srcFile 目标文件
* @param projectInfo ProjectInfo
*/
public static void doFileCopy(File srcFile, ProjectInfo projectInfo) {
List<String> contentList = FileUtil.readLines(srcFile, StandardCharsets.UTF_8);
CodeUtil.doContentReplaceIfNecessary(contentList, projectInfo);
String newFilePath = doPathOperate(srcFile, projectInfo);
//判断是否需要添加基本包名
final String javaStr = "java";
final String mainStr = "main";
// 在 main\java 的基础上加基础包名 如果需要的话
String trimStr = mainStr + File.separator + javaStr;
if (newFilePath.contains(trimStr)) {
String basePackageName = projectInfo.getBasePackageName();
basePackageName = basePackageName.replace(".", File.separator);
newFilePath = newFilePath.replace(trimStr, trimStr + File.separator + basePackageName);
}
FileUtil.writeLines(contentList, newFilePath, StandardCharsets.UTF_8);
}
/**
* 路径处理
* 将模板路径替换为项目路径
*
* @param srcFile 源文件
* @param projectInfo ProjectInfo
* @return 处理后的路径
*/
private static String doPathOperate(File srcFile, ProjectInfo projectInfo) {
try {
String srcFileCanonicalPath = srcFile.getCanonicalPath();
String projectPath = projectInfo.getProjectPath();
String templateProjectPath = projectInfo.getTemplateProjectPath();
templateProjectPath = operatePathByFileSeparatorOnWindows(templateProjectPath);
return srcFileCanonicalPath.replace(templateProjectPath, projectPath);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
/**
* 处理windows环境下的路径分隔符问
* <br/>
* 替换 : /
* <br/>
* 替换: //
*
* @param path 需要处理的路径
* @return 处理后的路径
*/
private static String operatePathByFileSeparatorOnWindows(String path) {
final String trimStr1 = "//";
final String trimStr2 = "/";
if (path.contains(trimStr1)) {
path = path.replace(trimStr1, File.separator);
} else if (path.contains(trimStr2)) {
path = path.replace(trimStr2, File.separator);
}
return path;
}
/**
* 操作子文件夹
*
* @param childFolderFile childFolderFile
* @param projectInfo ProjectInfo
*/
public static void operateChildFolder(File childFolderFile, ProjectInfo projectInfo) {
// 当前子工程根目录文件(含文件夹)
List<File> childProjectRootFileList = CollectionUtil.newArrayList(childFolderFile.listFiles());
if (CollectionUtil.isEmpty(childProjectRootFileList)) {
return;
}
for (File file : childProjectRootFileList) {
if (file.isDirectory()) {
// 文件夹
String fileName = file.getName();
final String testStr = "test";
if (testStr.equals(fileName)) {
// 如果是 test 文件夹,目前的处理是直接复制
doFolderCopy(file, projectInfo);
} else {
// 非 test 文件夹迭代处理
operateChildFolder(file, projectInfo);
}
} else {
// 文件
doFileCopy(file, projectInfo);
}
}
}
/**
* 执行文件夹的拷贝
*
* @param srcFolder 目标文件夹
* @param projectInfo ProjectInfo
*/
private static void doFolderCopy(File srcFolder, ProjectInfo projectInfo) {
try {
String newFilePath = doPathOperate(srcFolder, projectInfo);
newFilePath = newFilePath.replace(srcFolder.getName(), "");
FileUtil.copy(srcFolder.getCanonicalPath(), newFilePath, true);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
package cn.dankal.code.util.entity;
import lombok.Data;
import lombok.experimental.Accessors;
import java.io.Serializable;
/**
* 项目信息实体
*
* @author ZGH.MercyModest
* @version V1.0.0
* @create 2020/10/29
*/
@Data
@Accessors(chain = true)
public class ProjectInfo implements Serializable {
private static final long serialVersionUID = -6958602838534331817L;
/**
* 项目名称
* etc. tudgo-global-permission
*/
private String projectName;
/**
* 基本包名 (标准的Java包名)
* etc. com.tudgo.global.permission
*/
private String basePackageName;
/**
* 项目描述
* maven: <description></description>
*/
private String projectDescription;
/**
* 项目生成路径
*/
private String projectCreatePath;
/**
* 模板代码路径
*/
private String templateProjectPath;
/**
* 项目路径(系统自动赋值)
*/
private String projectPath;
}
package cn.dankal.code.util.test;
import cn.dankal.code.util.entity.ProjectInfo;
import cn.hutool.core.io.FileUtil;
import org.junit.After;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test;
import java.io.File;
/**
* 功能测试
*
* @author ZGH.MercyModest
* @version V1.0.0
* @create 2020/10/30
*/
public class FunctionTest {
/**
* 项目信息对象
*/
private ProjectInfo projectInfo;
@Before
public void beforeTests() {
// 项目名称
final String projectName = "test-in-code-util";
// 项目基础包名 etc. cn.dankal
final String basePackageName = "cn.dankal.test.code";
// 项目描述 etc.蛋壳创意科技--微服务--简易代码生成器
final String projectDescription = "蛋壳创意科技--微服务--简易代码生成器测试项目";
// 模板项目路径 : C:\dev\test 目前只支持一套模板
final String templateProjectPath = "C:/dev/test/dankal-microservice-code-template";
// 项目生成路径 C:\dev\test
final String projectCreatePath = "C:/dev/test";
//创建生成项目路径
String projectPath = projectCreatePath + File.separator + projectName;
File file = new File(projectPath);
if (file.exists()) {
FileUtil.del(file);
}
boolean mkdir = file.mkdir();
if (!mkdir) {
throw new IllegalStateException("创建新项目目录失败");
}
this.projectInfo = new ProjectInfo()
.setProjectName(projectName)
.setProjectCreatePath(projectCreatePath)
.setProjectDescription(projectDescription)
.setBasePackageName(basePackageName)
.setTemplateProjectPath(templateProjectPath)
.setProjectPath(projectPath);
}
@Test
@Ignore
public void testLoopFileByHutool() {
FileUtil.loopFiles(projectInfo.getTemplateProjectPath()).forEach(System.out::println);
}
@After
public void after() {
this.projectInfo = null;
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment