時間:2023-03-15來源:系統城裝機大師作者:佚名
假如某個新開發的功能,要新增10張表,按照這個時間計算,至少要100分鐘,仔細想想,其實你會發現大部分的時間都浪費在這些簡單而又重復的編程圈子中去了。
那有沒有一個辦法,將這些簡單的CURD
代碼,全部都標準化、公共化呢?這樣我們的可以省下很多時間來投入業務場景的開發。
答案是肯定的,有!
我記得早期我最先接觸的是MybatisGenertor
工具包,通過這個工具包,我們可以省去大部分的mybaits
中xml
文件的curd
編寫工作。
還有我們所熟悉的JPA
,里面有一套公共的持久層動態代理類,它可以自動根據名稱生成SQL
語句,能為開發省下不少的事情。
但是我這個人比較懶,我想搞一個工具,從controller
、service
、entity
、dao
層,全部的crud
代碼,包括單元測試類,通過工具自動生成好。
像這樣的工具,現在網上也有不少,例如我們所熟悉的Mybatis-plus
插件,它就可以做到這一點,也是非常好用。
但是有的公司就不喜歡它,原因也很簡單,里面的很多公共方法封裝的過于深入,而且很多crud
的sql
全部都是動態生成,你根本看不到。
總之啊就是一句,不在自己掌控之內的,很多程序員總是帶著各種疑慮~~
當然,還有一個明顯的疑慮,就是對微服務的開發,不能全面支持,比如你項目采用的是SpringBoot +Dubbo
組合來開發,這個時候生成的controller
,完全沒啥用處,而且還很雞肋。
因此在這種情況下,你得基于當前的項目軟件開發規則,自己開發一套代碼生成器,以滿足快速開發的需要。
下面我就簡單的介紹一下,如何自行開發一套代碼生成器,過程如下!
其實開發一套代碼生成器,真沒大家想象中的那么復雜,其中用的最重要一項技術,就是利用模板來生成代碼,例如我們經常使用的模板引擎freemarker
,它就可以幫助我們實現這一點。
1 2 3 4 5 |
< dependency > < groupId >org.freemarker</ groupId > < artifactId >freemarker</ artifactId > < version >2.3.23</ version > </ dependency > |
下面我們以動態創建實體類為例,編寫一個實體類的模板entity.java.ftl
,其中${}
里面定義的是動態變量。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 |
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
編寫一個測試類!
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 |
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( "文件創建成功" ); } } |
運行程序,輸出的文件結果如下!
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 |
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
層,截圖中所有的代碼全部都是采用代碼生成器生成的,直接通過單元測試就可以運行,開發的時候非???!
由于開發的代碼生成器工具,代碼有點過多,因此不便于通過文章分享給大家,有需要的朋友,可以訪問如下鏈接獲?。篽ttps://github.com/justdojava/springboot-example-generator
代碼生成器,對于擅長以業務開發為主的程序員來說,絕對是一個巨大的福利,它能很明顯的減輕開發人員的工作量,并且提升開發效率,能騰出更多的時間專注業務開發。
實際上,目前網上已經有很多的成熟、穩定的代碼生成器,mybatis-plus
就是其中一個使用非常廣泛的代碼生成器,對于以單體web
開發為主的項目,它完全滿足要求。
當然,如果當下你沒有合適的代碼生成器,不妨自己試試開發一款屬于自己的代碼生成器,同樣也可以加倍提升開發效率。
2023-03-18
threeJs實現波紋擴散及光標浮動效果詳解2023-03-15
Keil uVision5 5.38官方下載、安裝及注冊超詳細圖文教程2023-03-11
Jmeter如何將每次測試的結果保存到文件中