如何寫一個Java代碼生成器讓自己解脫

2020-08-29 碼農小胖哥

更多知識請通過文末連結了解更多



1. 前言

前幾天寫了篇關於Mybatis Plus代碼生成器的文章,不少同學私下問我這個代碼生成器是如何運作的,為什麼要用到一些模板引擎,所以今天來說明下代碼生成器的流程。

2. 代碼生成器的使用場景

我們在編碼中存在很多樣板代碼,格式較為固定,結構隨著項目的迭代也比較穩定,而且數量巨大,這種代碼寫多了也沒有什麼技術含量,在這種情況下代碼生成器可以有效提高我們的效率,其它情況並不適於使用代碼生成器。

3. 代碼生成器的製作流程

首先我們要製作模板,把樣板代碼的固定格式抽出來。然後把動態屬性綁定到模板中,就像做填空題一樣。所以在這個流程中模板引擎是最合適的。我們通過使用模板引擎的語法將數據動態地解析到靜態模板中去,然後導出為編程中對應的文件就行了。

另外模板引擎有著豐富的綁定數據的指令集,可以讓我們根據條件動態的綁定數據到模板中去。以freemarker為例:

三元表達式:

${true ? &39;: &39;}

還有我們等下要用的遍歷列表:

<list>


在Java開發中我們常用的模板引擎有FreemarkerVelocityThymeleaf ,隨著Web開發中前後端分離的流行模板引擎的使用場景正在被壓縮,但是它依然是一門有用的技術。

4. 代碼生成器演示

接下來,我們以Freemarker為例寫一個簡單的代碼生成器,來生成POJO類。需要引入Freemarker的依賴。

<dependency>    <groupId>org.freemarker</groupId>    <artifactId>freemarker</artifactId>    <version>2.3.28</version></dependency>

4.1 模板製作

POJO的結構可以分為以下幾部分:

java.lang 包無需導入。

所以將這些規則封裝到配置類中:

public class JavaProperties {    // 包名    private final String pkg;    // 類名    private final String entityName;    // 屬性集合 需要改寫 equals hash 保證名字可不重複 類型可重複    private final Set<Field> fields = new LinkedHashSet<>();    // 導入類的不重複集合    private final Set<String> imports = new LinkedHashSet<>();​​    public JavaProperties(String entityName, String pkg) {        this.entityName = entityName;        this.pkg = pkg;   }​    public void addField(Class<?> type, String fieldName) {        // 處理 java.lang        final String pattern = &34;;        String fieldType = type.getName();        if (!fieldType.startsWith(pattern)) {           // 處理導包            imports.add(fieldType);       }        Field field = new Field();        // 處理成員屬性的格式        int i = fieldType.lastIndexOf(&34;);        field.setFieldType(fieldType.substring(i + 1));        field.setFieldName(fieldName);        fields.add(field);   }​    public String getPkg() {        return pkg;   }​​    public String getEntityName() {        return entityName;   }​​    public Set<Field> getFields() {        return fields;   }​    public Set<String> getImports() {        return imports;   }​        /**     * 成員屬性封裝對象.     */    public static class Field {        // 成員屬性類型        private String fieldType;        // 成員屬性名稱        private String fieldName;​        public String getFieldType() {            return fieldType;       }​        public void setFieldType(String fieldType) {            this.fieldType = fieldType;       }​        public String getFieldName() {            return fieldName;       }​        public void setFieldName(String fieldName) {            this.fieldName = fieldName;       }                /**         * 一個類的成員屬性 一個名稱只能出現一次         * 我們可以通過覆寫equals hash 方法 然後放入Set         *         * @param o 另一個成員屬性         * @return 比較結果         */        @Override        public boolean equals(Object o) {            if (this == o) return true;            if (o == null || getClass() != o.getClass()) return false;            Field field = (Field) o;            return Objects.equals(fieldName, field.fieldName);       }​        @Override        public int hashCode() {            return Objects.hash(fieldType, fieldName);       }   }​}

接著就是靜態模板entity.ftl

package ${pkg};​<list>​/** * the ${entityName} type * @author felord.cn */public class ${entityName} {​<list>​}

這裡用到了Freemarker綁定數據的語法,比如List迭代渲染。

4.2 生成器編寫

Freemarker通過聲明配置並獲取模板對象freemarker.template,該對象的process方法可以將動態數據綁定到模板中並導出為文件,最終實現了代碼生成器,核心代碼如下:

/** * 簡單的代碼生成器. * * @param rootPath       maven 的 java 目錄 * @param templatePath   模板存放的文件夾 * @param templateName   模板的名稱 * @param javaProperties 需要渲染對象的封裝 * @throws IOException       the io exception * @throws TemplateException the template exception */public static void autoCodingJavaEntity(String rootPath,                                         String templatePath,                                         String templateName,                                         JavaProperties javaProperties) throws IOException, TemplateException {​    // freemarker 配置    Configuration configuration = new Configuration(Configuration.DEFAULT_INCOMPATIBLE_IMPROVEMENTS);​    configuration.setDefaultEncoding(&34;);    // 指定模板的路徑    configuration.setDirectoryForTemplateLoading(new File(templatePath));    // 根據模板名稱獲取路徑下的模板    Template template = configuration.getTemplate(templateName);    // 處理路徑問題    final String ext = &34;;    String javaName = javaProperties.getEntityName().concat(ext);    String packageName = javaProperties.getPkg();    String out = rootPath.concat(Stream.of(packageName.split(&34;))           .collect(Collectors.joining(&34;, &34;, &34; + javaName)));         // 定義一個輸出流來導出代碼文件    OutputStreamWriter outputStreamWriter = new OutputStreamWriter(new FileOutputStream(out));     // freemarker 引擎將動態數據綁定的模板並導出為文件    template.process(javaProperties, outputStreamWriter);​}

通過執行以下代碼即可生成一個UserEntity的POJO

// 路徑根據自己項目的特點調整String rootPath = &34;;String packageName = &34;;String templatePath = &34;;String templateName = &34;;​​JavaProperties userEntity = new JavaProperties(&34;, packageName);​userEntity.addField(String.class, &34;);userEntity.addField(LocalDate.class, &34;);userEntity.addField(LocalDateTime.class, &34;);userEntity.addField(Integer.class, &34;);userEntity.addField(Integer.class, &34;);​​autoCodingJavaEntity(rootPath, templatePath, templateName, userEntity);

生成的效果是不是跟手寫的差不多:


5. 總結

這就是大部分代碼生成器的機制,希望可以解答一些網友的疑問。多多關注:碼農小胖哥 獲取更多乾貨。


相關焦點

  • 手把手教你擼一個代碼生成器
    1.為什麼會有代碼生成器的誕生?發現現在很多開源的框架和公司內部框架都會有自帶的代碼生成器功能,為什麼它會出現在我們的框架的一部分呢?簡單的說,它是為了程式設計師偷懶的一個工具,也可以說,它也是一種敏捷開發的體現。它不會在乎項目的業務是什麼,它關注如何創建文件和一些自動寫好的方法,解決了重複勞動的難題,釋放無聊的CRUD功能的編寫。
  • java快速開發平臺功能特點之代碼生成器
    要說做代碼生成器的初衷,還是因為在做公司項目的時候,有太多的功能頁面需要處理,在前後端上面,雖然也選擇了一個基礎的SSH框架系統作為基礎,但還是耗費了大量的時間去一點點補代碼,再加上業務的需求並不是非常明確,導致後期的改動多的飛起,又特別繁瑣,當時就想,如果有一種方式能將精力集中到業務上就好了。
  • SpringBoot項目與mybatis及代碼生成器
    這個時候就需要代碼生成器出廠了,這就是批量生成血肉的機器。這裡用到的是個依賴rapid-framework的代碼生成器。下面這個是代碼生成器的目錄,generator-output就是代碼輸出目錄,template是代碼生成模板,src目錄是代碼執行部分。這個就是代碼生成模板,java_src目錄下是java代碼和xml,下圖紅藍各異是代碼調整的結果。
  • 介紹一款極為好用的java代碼生成器
    項目簡介JNPF是種專為提高開發效率而生的低代碼二次開發框架以及基於代碼生成器的java開發平臺。為簡單的增刪改查、複雜的表單、簡單的事務操作提供了完全自動化的開發平臺。項目特色在線解析拖拽式的表單設計器,快速設計使用自動生成表單代碼,清晰可讀易擴展自動生成三層架構的完整項目和代碼
  • 超實用的代碼生成器,支持c#、java多語言,保姆級教程
    特別說明:關於數據表和系統業務之間的關係,由於比較複雜,之後會再寫一篇文章做詳細說明。創建java項目依照上面的方法,創建一個java項目,配置完資料庫後,我們導出代碼,同樣導出完整的代碼導出java代碼
  • 想擺脫寫重複代碼,就部署個代碼生成器,一鍵生成前後端
    基於SpringBoot2+Freemarker的代碼生成器,用DDL SQL語句生成JPA/JdbcTemplate/Mybatis/BeetlSQL相關代碼,支持mysql/oracle/pgsql三大資料庫。以釋放雙手為目的,各大模板也在陸續補充和優化。
  • Java 能不能自己寫一個類
    最近學習了下java類加載相關的知識。然後看到網上有一道面試題是能不能自己寫個類叫java.lang.System?網上提供的答案:通常不可以,但可以採取另類方法達到這個需求。所謂的另類方法指自己寫個類加載器來加載java.lang.System達到目的。
  • 你可以試試Mybatis Plus代碼生成器
    前言對於寫Crud的老司機來說時間非常寶貴,一些樣板代碼寫不但費時費力,而且枯燥無味。經常有小夥伴問我,胖哥你怎麼天天那麼有時間去搞新東西,透露一下秘訣唄。,讓你也成為一個優秀的時間管理大師。;import java.util.List;import java.util.Optional;​​/** * 代碼生成器配置 * * @author felord * @since 10 :39 2018/9/9 */public class CodeGenerator {    private String dbUrl;    private String
  • 我們寫的Java代碼是怎麼運行起來的?
    在進行「我們寫的Java代碼是怎麼運行起來的?」這個話題之前,我們先來了解一個概念:JVM。定義描述得很清楚,其實我們只需要把它理解為一種工具,一種將java代碼翻譯給具體計算機是別的翻譯機器,類似於你跟一個老外交流,但是你不懂英語,需要一個懂英語的幫你進行翻譯,你才能理解老外的意思,這裡你就是具體的計算機了。
  • JNPF快速開發平臺自主研發的代碼生成器介紹
    ■ 項目簡介JNPF是種專為提高開發效率而生的低代碼二次開發框架以及基於代碼生成器的java開發平臺。為簡單的增刪改查、簡單的事務操作、複雜的表單提供了完全自動化的開發平臺。能大幅降低開發和溝通成本,簡化開發流程,縮短開發周期。適合中小型前後端分離的項目,尤其是網際網路創業項目和企業自用項目。
  • 程序猿私活神器,超實用代碼生成器,MVC項目全套直接生成
    生成代碼的開發環境C# 版.net core 3.0vs 2019Java 版java 1.8IDEA 2017C# 項目:生成項目將創建一個asp.net core 的項目,並生成MVC的代碼;生成代碼將不創建項目,而是直接生成MVC的代碼。
  • 實戰:一鍵生成前後端代碼,Mybatis-Plus代碼生成器讓我舒服了
    前言在日常的軟體開發中,程式設計師往往需要花費大量的時間寫CRUD,不僅枯燥效率低,而且每個人的代碼風格不統一。mybatis-Plus 代碼生成器,通過 AutoGenerator 可以快速生成 Entity、Mapper、Mapper XML、Service、Controller 等各個模塊及前端頁面的代碼,極大的提升了開發效率。
  • 代碼自動生成器 AutoCreate v2.1 發布,jfinal+beetl
    加入了http://www.oschina.net/p/mtgxxw 項目,模板生成支持 autocreate 是 資料庫連結採用Jfinal ActiveRecordPlugin,模板配置採用beetl,實現根據模板自動生成項目代碼。
  • Java通用代碼生成器光發布1.5.0 嘗鮮版 2,支持 PDF 導出功能
    項目地址:https://gitee.com/jerryshensjf/LightSBMEU第三代動詞算子式代碼生成器:光SBMEU版本代碼生成器支持前後端分離界面了簡介第三代動詞算子式代碼生成器:光SBMEU版,採用Maven, EasyUI,SpringBoot 2, MyBatis, MariaDB 技術棧歡迎大家使用由無垠式
  • Java 通用代碼生成器光 2.0.0 Insight(內省) 發布嘗鮮版 4,代碼...
    讓代碼生成器成為大家開發Java程序的一項優勢簡介第三代動詞算子式代碼生成器:光SBMEU版,採用Maven, EasyUI,SpringBoot 2, MyBatis, MariaDB 技術棧歡迎大家使用由無垠式,和平之翼和光三代動詞算子式代碼生成器組成的動詞算子式代碼生成器陣列,在我的碼雲站點https://gitee.com/jerryshensjf
  • Java 通用代碼生成器光 2.0.0 Insight(內省) 發布 Beta2 版,代碼...
    讓代碼生成器成為大家開發Java程序的一項優勢簡介第三代動詞算子式代碼生成器:光SBMEU版,採用Maven, EasyUI,SpringBoot 2, MyBatis, MariaDB 技術棧歡迎大家使用由無垠式,和平之翼和光三代動詞算子式代碼生成器組成的動詞算子式代碼生成器陣列,在我的碼雲站點https://gitee.com/jerryshensjf
  • Java 通用代碼生成器光 1.5.0 Kama( 頓悟)發布嘗鮮版 8,支持克隆...
    Java通用代碼生成器光1.5.0 Kama(頓悟)發布嘗鮮版8,支持克隆動詞,即將進入Beta測試Java通用代碼生成器光1.5.0 Kama
  • Java 通用代碼生成器光 1.5.0 Kama(頓悟)發布嘗鮮版 6,功能增強
    ,是目前最完善的支持SpringBoot代碼生成器。項目地址:https://gitee.com/jerryshensjf/LightSBMEU二進位發布包地址:https://gitee.com/jerryshensjf/LightSBMEU/attach_files第三代動詞算子式代碼生成器:光SBMEU版本代碼生成器支持前後端分離界面了簡介第三代動詞算子式代碼生成器:光SBMEU版,採用Maven, EasyUI
  • 安裝並激活寫Java代碼的神器——MyEclipse10
    安裝並激活寫java代碼神器——馮修遠人生就像一場修行,任重而道遠。大家好,我是馮修遠,一位專注於IT教育行業及編程技術和網絡營銷的人士。都說:"工欲善其事,必先利其器"。今天主要是針對Java0基礎的小白,想教大家安裝一個寫Java代碼非常好用的工具——MyEclipse 10。如果您還不知道如何搭建Java環境,您可以先移步看一下這篇文章——Java0基礎教程——java的安裝。如果您的Java環境已經搭建好了,我將從以下三步帶您了解如何安裝並激活MyEclipse 10。
  • 光之翼 Java 通用代碼生成器 1.0.0 嘗鮮版公布,便攜易用,功能強大
    光之翼Java通用代碼生成器1.0.0嘗鮮版公布,便攜易用,功能強大光之翼Java通用代碼生成器1.0.0嘗鮮版公布,便攜易用,功能強大。