第二章 代码生成
前言
本笔记主要用途是学习up 主程序员鱼皮的项目:代码生成器时的一些学习心得。
代码地址:https://github.com/Liucc-123/yuzi-generator.git
项目教程:https://www.codefather.cn/course/1790980795074654209
本节重点
本节属于项目的第一阶段:开发本地代码生成器。重点内容包括:
- 项目初始化。
- 静态文件生成。
- 动态文件代码生成。
- FreeMarker 模板引擎入门及实战。
- 动静结合 - ACM 示例项目模板代码生成。
一、项目初始化
- 初始化根目录
-
使用 IDEA创建一个干净的文件夹
yuzi-generator
作为整个项目的根目录。 -
使用 Git 管理项目,建议在项目根目录中初始化 Git 仓库。
-
- 忽略无用提交
-
使用
.gitignore
文件忽略项目中不需要提交的文件(如IDE自动生成的工程文件)。 -
推荐使用IDE插件(如
.ignore
插件)生成.gitignore
文件,并手动添加需要忽略的目录和文件。 -
忽略文件常见配置项设置
### Custom template .idea target yuzi-generator.iml .DS_Store ### 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* replay_pid* ### JetBrains template # Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider # Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 # User-specific stuff .idea/**/workspace.xml .idea/**/tasks.xml .idea/**/usage.statistics.xml .idea/**/dictionaries .idea/**/shelf # AWS User-specific .idea/**/aws.xml # Generated files .idea/**/contentModel.xml # Sensitive or high-churn files .idea/**/dataSources/ .idea/**/dataSources.ids .idea/**/dataSources.local.xml .idea/**/sqlDataSources.xml .idea/**/dynamic.xml .idea/**/uiDesigner.xml .idea/**/dbnavigator.xml # Gradle .idea/**/gradle.xml .idea/**/libraries # Gradle and Maven with auto-import # When using Gradle or Maven with auto-import, you should exclude module files, # since they will be recreated, and may cause churn. Uncomment if using # auto-import. # .idea/artifacts # .idea/compiler.xml # .idea/jarRepositories.xml # .idea/modules.xml # .idea/*.iml # .idea/modules # *.iml # *.ipr # CMake cmake-build-*/ # Mongo Explorer plugin .idea/**/mongoSettings.xml # File-based project format *.iws # IntelliJ out/ # mpeltonen/sbt-idea plugin .idea_modules/ # JIRA plugin atlassian-ide-plugin.xml # Cursive Clojure plugin .idea/replstate.xml # SonarLint plugin .idea/sonarlint/ # Crashlytics plugin (for Android Studio and IntelliJ) com_crashlytics_export_strings.xml crashlytics.properties crashlytics-build.properties fabric.properties # Editor-based Rest Client .idea/httpRequests # Android studio 3.1+ serialized cache file .idea/caches/build_file_checksums.ser
-
如果文件已被Git跟踪,需执行
git rm -rf --cached .
命令取消跟踪。
-
- 创建 Demo 示例代码工程
- 新建
yuzi-generator-demo-projects
目录,存放所有示例代码。 - 下载并复制 ACM 示例模板代码到该目录下(可通过云盘下载)。
- 新建
- 创建本地代码生成器项目
-
在项目根目录下新建
yuzi-generator-basic
项目,使用Maven管理项目。 -
JDK选择1.8,取消Git仓库勾选(因为外层已托管)。
-
在项目的
pom.xml
文件中引入 Hutool、Apache Commons Collections、Lombok 和 JUnit 等依赖。<dependencies> <!-- https://doc.hutool.cn/ --> <dependency> <groupId>cn.hutool</groupId> <artifactId>hutool-all</artifactId> <version>5.8.16</version> </dependency> <!-- https://mvnrepository.com/artifact/org.apache.commons/commons-collections4 --> <dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-collections4</artifactId> <version>4.4</version> </dependency> <!-- https://projectlombok.org/ --> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <version>1.18.30</version> <scope>provided</scope> </dependency> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.13.2</version> <scope>test</scope> </dependency> </dependencies>
-
二、实现流程
目标:制作本地代码生成器,根据用户输入生成不同的 ACM 示例代码模板。
- 需求拆解
- 将需求拆解为“生成静态文件”和“生成动态文件”两个步骤。
- 静态文件:直接复制,不做改动(如
README.md
)。 - 动态文件:基于模板文件和用户输入生成代码(如
MainTemplate.java
)。
- 实现步骤
- 生成静态文件(通过 Main 方法运行)。
- 生成动态文件(通过 Main 方法运行)。
- 同时生成静态和动态文件,得到完整代码。
- 开发命令行工具,接受用户输入并生成代码。
- 将工具封装为 jar 包和脚本,供用户调用。
三、静态文件生成
静态文件是指直接复制、不做任何改动的文件。
-
现成的工具库复制目录
-
使用 Hutool 的
FileUtil.copy
方法,一行代码实现目录复制。 -
示例代码:
public static void copyFilesByHutool(String inputPath, String outputPath) { FileUtil.copy(inputPath, outputPath, false); }
-
-
递归遍历
-
手动编写递归算法,逐个复制目录和文件。
-
示例代码:
public static void copyFilesByRecursive(String inputPath, String outputPath) { File inputFile = new File(inputPath); File outputFile = new File(outputPath); try { copyFileByRecursive(inputFile, outputFile); } catch (Exception e) { System.err.println("文件复制失败"); e.printStackTrace(
-