<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
在實際的軟體專案開發過程中,我可以很負責任的跟大家說,如果你真的實際寫程式碼的時間超過5年,你對增刪改查這類簡單的功能需求開發,可以說已經完全寫吐了,至少我就是這種型別的。
但是呢,不可否認,絕大多數的軟體功能,向下追隨到最基本的單元,也基本都是單表的增、刪、改、查!
只是隨著使用者需求不斷增多,原來可能一個張單表就可以搞定的事情,現在可能需要多張表,或者多個庫才能搞定,程式碼層就像堆積木一樣,越堆越複雜。
我記得早期做專案的時候,專案每新加一張單表,我都需要在程式碼層,按照MVC
框架的思想,重新編寫一套CURD
的程式碼,寫完所有的基礎的增刪改查,至少需要20分鐘,手快的情況下,最快也要10分鐘。
假如某個新開發的功能,要新增10張表,按照這個時間計算,至少要100分鐘,仔細想想,其實你會發現大部分的時間都浪費在這些簡單而又重複的程式設計圈子中去了。
那有沒有一個辦法,將這些簡單的CURD
程式碼,全部都標準化、公共化呢?這樣我們的可以省下很多時間來投入業務場景的開發。
答案是肯定的,有!
我記得早期我最先接觸的是MybatisGenertor
工具包,通過這個工具包,我們可以省去大部分的mybaits
中xml
檔案的curd
編寫工作。
還有我們所熟悉的JPA
,裡面有一套公共的持久層動態代理類,它可以自動根據名稱生成SQL
語句,能為開發省下不少的事情。
但是我這個人比較懶,我想搞一個工具,從controller
、service
、entity
、dao
層,全部的crud
程式碼,包括單元測試類,通過工具自動生成好。
像這樣的工具,現在網上也有不少,例如我們所熟悉的Mybatis-plus
外掛,它就可以做到這一點,也是非常好用。
但是有的公司就不喜歡它,原因也很簡單,裡面的很多公共方法封裝的過於深入,而且很多crud
的sql
全部都是動態生成,你根本看不到。
總之啊就是一句,不在自己掌控之內的,很多程式設計師總是帶著各種疑慮~~
當然,還有一個明顯的疑慮,就是對微服務的開發,不能全面支援,比如你專案採用的是SpringBoot +Dubbo
組合來開發,這個時候生成的controller
,完全沒啥用處,而且還很雞肋。
因此在這種情況下,你得基於當前的專案軟體開發規則,自己開發一套程式碼生成器,以滿足快速開發的需要。
下面我就簡單的介紹一下,如何自行開發一套程式碼生成器,過程如下!
其實開發一套程式碼生成器,真沒大家想象中的那麼複雜,其中用的最重要一項技術,就是利用模板來生成程式碼,例如我們經常使用的模板引擎freemarker
,它就可以幫助我們實現這一點。
<dependency> <groupId>org.freemarker</groupId> <artifactId>freemarker</artifactId> <version>2.3.23</version> </dependency>
下面我們以動態建立實體類為例,編寫一個實體類的模板entity.java.ftl
,其中${}
裡面定義的是動態變數。
package ${package}; import java.io.Serializable; /** * <p> * ${tableComment} * </p> * * @author ${author} * @since ${date} */ public class ${entityClass} implements Serializable { private static final long serialVersionUID = 1L; <#--屬性遍歷--> <#list columns as pro> /** * ${pro.comment} */ private ${pro.propertyType} ${pro.propertyName}; </#list> <#--屬性get||set方法--> <#list columns as pro> public ${pro.propertyType} get${pro.propertyName?cap_first}() { return this.${pro.propertyName}; } public ${entityClass} set${pro.propertyName?cap_first}(${pro.propertyType} ${pro.propertyName}) { this.${pro.propertyName} = ${pro.propertyName}; return this; } </#list> }
最後我們基於freemarker
編寫一個測試類!
public class CodeGeneratorDemo { public static void main(String[] args) throws IOException, TemplateException { Map<String, Object> objectMap = new HashMap<>(); //定義包路徑 objectMap.put("package", "com.example.test"); //定義實體類 objectMap.put("entityClass", "Student"); //定義實體類屬性 List<Map<String, Object>> columns = new ArrayList<>(); //姓名欄位 Map<String, Object> column1 = new HashMap<>(); column1.put("propertyType", "String"); column1.put("propertyName", "name"); column1.put("comment", "姓名"); columns.add(column1); //年齡欄位 Map<String, Object> column2 = new HashMap<>(); column2.put("propertyType", "Integer"); column2.put("propertyName", "age"); column2.put("comment", "年齡"); columns.add(column2); //定義類的屬性 objectMap.put("columns", columns); //定義作者 objectMap.put("author", "張三"); //定義建立時間 objectMap.put("date", new SimpleDateFormat("yyyy-MM-dd").format(new Date())); //定義類描述 objectMap.put("tableComment", "學生資訊"); //生產目的碼 Configuration configuration = new Configuration(Configuration.VERSION_2_3_23); configuration.setDefaultEncoding(Charset.forName("UTF-8").name()); configuration.setClassForTemplateLoading(CodeGeneratorDemo.class, "/"); Template template = configuration.getTemplate("/templates/entity.java.ftl"); FileOutputStream fileOutputStream = new FileOutputStream(new File("../src/main/java/com/example/generator/Student.java")); template.process(objectMap, new OutputStreamWriter(fileOutputStream, Charset.forName("UTF-8").name())); fileOutputStream.close(); System.out.println("檔案建立成功"); } }
執行程式,輸出的檔案結果如下!
package com.example.test; import java.io.Serializable; /** * <p> * 學生資訊 * </p> * * @author 張三 * @since 2021-08-22 */ public class Student implements Serializable { private static final long serialVersionUID = 1L; /** * 姓名 */ private String name; /** * 年齡 */ private Integer age; public String getName() { return this.name; } public Student setName(String name) { this.name = name; return this; } public Integer getAge() { return this.age; } public Student setAge(Integer age) { this.age = age; return this; } }
與預期的效果一致,成功生成!
以上就是生成程式碼最核心的部分,首先編寫一套模板,把需要填充的資訊全部定義成動態變數,然後在程式碼中,通過map資料格式,使用freemarker
進行填充!
例如小編我就是採用這種方式,首先把要通過工具生成的程式碼,全部通過模板方式定義好。
然後通過連線資料庫的方式,把需要自動生成的表結構查詢出來,封裝成資料渲染引數,最後傳入到freemarker
中去,非常簡單、快速的生成與自己預期想要的程式碼,所有單表的crud
全部一步到位!
下面這個就是小編,基於當前專案客製化開發的一款程式碼生成器,專案採用SpringBoot + Dubbo
框架開發,沒有Controller
層,截圖中所有的程式碼全部都是採用程式碼生成器生成的,直接通過單元測試就可以執行,開發的時候非常快!
由於開發的程式碼生成器工具,程式碼有點過多,因此不便於通過文章分享給大家,有需要的朋友,可以存取如下連結獲取:https://github.com/justdojava/springboot-example-generator
程式碼生成器,對於擅長以業務開發為主的程式設計師來說,絕對是一個巨大的福利,它能很明顯的減輕開發人員的工作量,並且提升開發效率,能騰出更多的時間專注業務開發。
實際上,目前網上已經有很多的成熟、穩定的程式碼生成器,mybatis-plus
就是其中一個使用非常廣泛的程式碼生成器,對於以單體web
開發為主的專案,它完全滿足要求。
當然,如果當下你沒有合適的程式碼生成器,不妨自己試試開發一款屬於自己的程式碼生成器,同樣也可以加倍提升開發效率。
以上就是SpringBoot整合freemarker實現程式碼生成器的詳細內容,更多關於SpringBoot freemarker程式碼生成器的資料請關注it145.com其它相關文章!
相關文章
<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
综合看Anker超能充系列的性价比很高,并且与不仅和iPhone12/苹果<em>Mac</em>Book很配,而且适合多设备充电需求的日常使用或差旅场景,不管是安卓还是Switch同样也能用得上它,希望这次分享能给准备购入充电器的小伙伴们有所
2021-06-01 09:31:42
除了L4WUDU与吴亦凡已经多次共事,成为了明面上的厂牌成员,吴亦凡还曾带领20XXCLUB全队参加2020年的一场音乐节,这也是20XXCLUB首次全员合照,王嗣尧Turbo、陈彦希Regi、<em>Mac</em> Ova Seas、林渝植等人全部出场。然而让
2021-06-01 09:31:34
目前应用IPFS的机构:1 谷歌<em>浏览器</em>支持IPFS分布式协议 2 万维网 (历史档案博物馆)数据库 3 火狐<em>浏览器</em>支持 IPFS分布式协议 4 EOS 等数字货币数据存储 5 美国国会图书馆,历史资料永久保存在 IPFS 6 加
2021-06-01 09:31:24
开拓者的车机是兼容苹果和<em>安卓</em>,虽然我不怎么用,但确实兼顾了我家人的很多需求:副驾的门板还配有解锁开关,有的时候老婆开车,下车的时候偶尔会忘记解锁,我在副驾驶可以自己开门:第二排设计很好,不仅配置了一个很大的
2021-06-01 09:30:48
不仅是<em>安卓</em>手机,苹果手机的降价力度也是前所未有了,iPhone12也“跳水价”了,发布价是6799元,如今已经跌至5308元,降价幅度超过1400元,最新定价确认了。iPhone12是苹果首款5G手机,同时也是全球首款5nm芯片的智能机,它
2021-06-01 09:30:45