更新時間:2022-11-14 來源:黑馬程序員 瀏覽量:
1 概述
1.1 介紹
在項(xiàng)目開發(fā)過程中,有很多業(yè)務(wù)模塊的代碼是具有一定規(guī)律性的,例如controller控制器、service接口、service實(shí)現(xiàn)類、mapper接口、model實(shí)體類等等,這部分代碼可以使用代碼生成器生成,我們就可以將更多的時間放在業(yè)務(wù)邏輯上。
傳統(tǒng)的開發(fā)步驟:
創(chuàng)建數(shù)據(jù)庫和表
根據(jù)表設(shè)計實(shí)體類
編寫mapper接口
編寫service接口和實(shí)現(xiàn)類
編寫controller控制器
編寫前端頁面
前后端聯(lián)調(diào)
基于代碼生成器開發(fā)步驟:
創(chuàng)建數(shù)據(jù)庫和表
使用代碼生成器生成實(shí)體類、mapper、service、controller、前端頁面
將生成好的代碼拷貝到項(xiàng)目中并做調(diào)整
前后端聯(lián)調(diào)
我們只需要知道數(shù)據(jù)庫和表相關(guān)信息,就可以結(jié)合模版生成各個模塊的代碼,減少了很多重復(fù)工作,也減少出錯概率,提高效率。
1.2 實(shí)現(xiàn)思路

(1)需要對數(shù)據(jù)庫表解析獲取到元數(shù)據(jù),包含表字段名稱、字段類型等等。
(2)將通用的代碼編寫成模版文件,部分?jǐn)?shù)據(jù)需使用占位符替換。
(3)將元數(shù)據(jù)和模版文件結(jié)合,使用一些模版引擎工具(例如freemarker)即可生成源代碼文件。
2 Freemarker
2.1 介紹
FreeMarker 是一款 模板引擎: 即一種基于模板和要改變的數(shù)據(jù), 并用來生成輸出文本(HTML網(wǎng)頁,電子郵件,配置文件,源代碼等)的通用工具。 它不是面向最終用戶的,而是一個Java類庫,是一款程序員可以嵌入他們所開發(fā)產(chǎn)品的組件。
模板編寫為FreeMarker Template Language (FTL)。它是簡單的,專用的語言, 在模板中,你可以專注于如何展現(xiàn)數(shù)據(jù), 而在模板之外可以專注于要展示什么數(shù)據(jù)。

2.2 應(yīng)用場景
(1)動態(tài)頁面
freemarker可以作為springmvc一種視圖格式,像jsp一樣被瀏覽器訪問。
(2)頁面靜態(tài)化
對于一些內(nèi)容比較多,更新頻率很小,訪問又很頻繁的頁面,可以使用freemarker靜態(tài)化,減少DB的壓力,提高頁面打開速度。
(3)代碼生成器
根據(jù)配置生成頁面和代碼,減少重復(fù)工作,提高開發(fā)效率。
2.3 快速入門
(1)創(chuàng)建freemarker-demo模塊,并導(dǎo)入相關(guān)依賴
<?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>com.itheima</groupId> <artifactId>freemarker-demo</artifactId> <version>1.0-SNAPSHOT</version> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.3.1.RELEASE</version> </parent> <properties> <maven.compiler.source>8</maven.compiler.source> <maven.compiler.target>8</maven.compiler.target> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> </dependency> <!-- freemarker --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-freemarker</artifactId> </dependency> <!-- lombok --> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> </dependency> </dependencies> </project>
(2)application.yml相關(guān)配置
server: port: 8881 #服務(wù)端口 spring: application: name: freemarker-demo #指定服務(wù)名 freemarker: cache: false #關(guān)閉模板緩存,方便測試 settings: template_update_delay: 0 #檢查模板更新延遲時間,設(shè)置為0表示立即檢查,如果時間大于0會有緩存不方便進(jìn)行模板測試 suffix: .ftl #指定Freemarker模板文件的后綴名
(3)創(chuàng)建啟動類
package com.heima.freemarker;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class FreemarkerDemotApplication {
public static void main(String[] args) {
SpringApplication.run(FreemarkerDemotApplication.class,args);
}
}(4)創(chuàng)建Student模型類
package com.itheima.freemarker.entity;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.Date;
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Student {
private Integer id;
private String name;//姓名
private Integer age;//年齡
private Date birthday;//生日
private Float money;//錢包
}(5)創(chuàng)建StudentController
package com.itheima.freemarker.controller;
import com.itheima.freemarker.entity.Student;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import java.util.Date;
@Controller
@RequestMapping("student")
public class StudentController {
@GetMapping("index")
public String index(Model model){
//1.純文本形式的參數(shù)
model.addAttribute("name", "Freemarker");
//2.實(shí)體類相關(guān)的參數(shù)
Student student = new Student();
student.setName("黑馬");
student.setAge(18);
model.addAttribute("stu", student);
return "01-index";
}
}(6)在resources/templates下創(chuàng)建01-index.ftl模版文件
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>首頁</title>
</head>
<body>
<b>普通文本 String 展示:</b><br/>
Hello ${name} <br>
<hr>
<b>對象Student中的數(shù)據(jù)展示:</b><br/>
姓名:${stu.name}<br/>
年齡:${stu.age}
<hr>
</body>
</html> (7)測試
瀏覽器訪問 http://localhost:8881/student/index
效果如下

2.4 模版
2.4.1 基礎(chǔ)語法種類
(1)注釋,即<#-- -->,介于其之間的內(nèi)容會被freemarker忽略
<#--我是一個freemarker注釋-->
(2)插值(Interpolation):即 **`${..}`** 部分,freemarker會用真實(shí)的值代替**`${..}`**
Hello ${name}(3)FTL指令:和HTML標(biāo)記類似,名字前加#予以區(qū)分,F(xiàn)reemarker會解析標(biāo)簽中的表達(dá)式或邏輯。
<# >FTL指令</#>
(4)文本,僅文本信息,這些不是freemarker的注釋、插值、FTL指令的內(nèi)容會被freemarker忽略解析,直接輸出內(nèi)容。
<#--freemarker中的普通文本--> 我是一個普通的文本
2.4.2 if指令
if 指令即判斷指令,是常用的FTL指令,freemarker在解析時遇到if會進(jìn)行判斷,條件為真則輸出if中間的內(nèi)容,否則跳過內(nèi)容不再輸出。
格式如下
<#if condition> .... <#elseif condition2> ... <#elseif condition3> ... <#else> ... </#if>
需求:根據(jù)年齡輸出所處的年齡段
> 童年:0歲—6歲(周歲,下同)
> 少年:7歲—17歲
> 青年:18歲—40歲
> 中年:41—65歲
> 老年:66歲以后
實(shí)例代碼:
(1)在01-index.ftl添加如下代碼
<#if stu.age <= 6> 童年 <#elseif stu.age <= 17> 少年 <#elseif stu.age <= 40> 青年 <#elseif stu.age <= 65> 中年 <#else> 老年 </#if>
(2)測試
瀏覽器訪問http://localhost:8881/student/index
效果如下

2.4.3 list指令
list指令時一個迭代輸出指令,用于迭代輸出數(shù)據(jù)模型中的集合
格式如下
<#list items as item>
${item_index + 1}------${item}-----<#if item_has_next>,</#if>
</#list>
迭代集合對象時,包括兩個特殊的循環(huán)變量:
(1)item_index:當(dāng)前變量的索引值。
(2)item_has_next:是否存在下一個對象
> item_index 和 item_has_nex 中的item為<#list items as item> 中as后面的臨時變量
需求:遍歷學(xué)生集合,輸出序號,學(xué)生id,姓名,所處的年齡段,是否最后一條數(shù)據(jù)
(1)在StudentController中增加方法
@GetMapping("list")
public String list(Model model) throws ParseException {
List<Student> list = new ArrayList<>();
list.add(new Student(1001,"張飛",15, null, 1000.11F));
list.add(new Student(1002,"劉備",28, null, 5000.3F));
list.add(new Student(1003,"關(guān)羽",45, null, 9000.63F));
list.add(new Student(1004,"諸葛亮",62, null, 10000.99F));
list.add(new Student(1005,"成吉思汗",75, null, 16000.66F));
model.addAttribute("stus",list);
return "02-list";
}(2)在resources/templates目錄下創(chuàng)建02-list.ftl模版
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>列表頁面</title>
<style>
table{
border-spacing: 0;/*把單元格間隙設(shè)置為0*/
border-collapse: collapse;/*設(shè)置單元格的邊框合并為1*/
}
td{
border:1px solid #ACBED1;
text-align: center;
}
</style>
</head>
<body>
<table>
<tr>
<td>序號</td>
<td>id</td>
<td>姓名</td>
<td>所處的年齡段</td>
<td>生日</td>
<td>錢包</td>
<td>是否最后一條數(shù)據(jù)</td>
</tr>
<#list stus as stu >
<tr>
<td>${stu_index + 1}</td>
<td>${stu.id}</td>
<td>${stu.name}</td>
<td>
<#if stu.age <= 6>
童年
<#elseif stu.age <= 17>
少年
<#elseif stu.age <= 40>
青年
<#elseif stu.age <= 65>
中年
<#else>
老年
</#if>
</td>
<td></td>
<td>${stu.money}</td>
<td>
<#if stu_has_next>
否
<#else>
是
</#if>
</td>
</tr>
</#list>
</table>
<hr>
</body>
</html> (2)測試
瀏覽器訪問http://localhost:8881/student/list
效果如下

2.4.4 include指令
include指令的作用類似于JSP的包含指令,用于包含指定頁,include指令的語法格式如下
<#include filename [options]></#include>
(1)filename:該參數(shù)指定被包含的模板文件
(2)options:該參數(shù)可以省略,指定包含時的選項(xiàng),包含encoding和parse兩個選項(xiàng),encoding
指定包含頁面時所使用的解碼集,而parse指定被包含是否作為FTL文件來解析。如果省略了parse選項(xiàng)值,則該選項(xiàng)值默認(rèn)是true
需求:"早上好,尊敬的 某某 用戶!" 這句話在很多頁面都有用到,請合理設(shè)計!
(1)在resources/templates目錄下創(chuàng)建00-head.ftl模版,內(nèi)容如下
早上好,尊敬的 ${name} 用戶!(2)在resources/templates目錄下創(chuàng)建03-include.ftl模版,使用include引入00-head.ftl模版,內(nèi)容如下
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>詳情頁</title> </head> <body> <#include "00-head.ftl" /> <br> 歡迎來到黑馬程序員。 </body> </html>
(3)在StudentController中增加方法
@GetMapping("include")
public String include(Model model) throws ParseException {
model.addAttribute("name", "黑馬");
return "03-include";
} (4)測試
瀏覽器訪問http://localhost:8881/student/include
效果如下

2.4.5 assign指令
它用于為該模板頁面創(chuàng)建或替換一個頂層變量
<#assign name = "zhangsan" />
2.4.6 運(yùn)算符
(1)算數(shù)運(yùn)算符
FreeMarker表達(dá)式中完全支持算術(shù)運(yùn)算,FreeMarker支持的算術(shù)運(yùn)算符包括:
- 加法: `+`
- 減法: `-`
- 乘法: `*`
- 除法: `/`
- 求模 (求余): `%`
(2)比較運(yùn)算符
- `=`或者`==`:判斷兩個值是否相等.
- `!=`:判斷兩個值是否不等.
- `>`或者`gt`:判斷左邊值是否大于右邊值
- `>=`或者`gte`:判斷左邊值是否大于等于右邊值
- `<`或者`lt`:判斷左邊值是否小于右邊值
- `<=`或者`lte`:判斷左邊值是否小于等于右邊值
比較運(yùn)算符注意
- `=`和`!=`可以用于字符串、數(shù)值和日期來比較是否相等
- `=`和`!=`兩邊必須是相同類型的值,否則會產(chǎn)生錯誤
- 字符串 `"x"` 、`"x "` 、`"X"`比較是不等的.因?yàn)镕reeMarker是精確比較
- 其它的運(yùn)行符可以作用于數(shù)字和日期,但不能作用于字符串
- 使用`gt`等字母運(yùn)算符代替`>`會有更好的效果,因?yàn)?FreeMarker會把`>`解釋成FTL標(biāo)簽的結(jié)束字符
- 可以使用括號來避免這種情況,如:`<#if (x>y)>`
(3)邏輯運(yùn)算符
- 邏輯與:&&
- 邏輯或:||
- 邏輯非:!
邏輯運(yùn)算符只能作用于布爾值,否則將產(chǎn)生錯誤 。
2.4.7 空值處理
(1)缺失變量默認(rèn)值使用 “!”
- 使用!要以指定一個默認(rèn)值,當(dāng)變量為空時顯示默認(rèn)值
例: ${name!''}表示如果name為空顯示空字符串。
- 如果是嵌套對象則建議使用()括起來
例: ${(stu.bestFriend.name)!''}表示,如果stu或bestFriend或name為空默認(rèn)顯示空字符串。
(2)判斷某變量是否存在使用 “??”
用法為:variable??,如果該變量存在,返回true,否則返回false
例:為防止stus為空報錯可以加上判斷如下:
<#if stus??> <#list stus as stu> ...... </#list> </#if>
2.4.8 內(nèi)建函數(shù)
內(nèi)建函數(shù)語法格式: `變量+?+函數(shù)名稱`
(1)求集合的大小
`${集合名?size}`
(2)日期格式化
顯示年月日: `${today?date}`
顯示時分秒:`${today?time}`
顯示日期+時間:`${today?datetime}`
自定義格式化: `${today?string("yyyy年MM月")}`
(3)內(nèi)建函數(shù)`c`
model.addAttribute("point", 102920122);
point是數(shù)字型,使用${point}會顯示這個數(shù)字的值,每三位使用逗號分隔。
如果不想顯示為每三位分隔的數(shù)字,可以使用c函數(shù)將數(shù)字型轉(zhuǎn)成字符串輸出
`${point?c}`
(4)將json字符串轉(zhuǎn)成對象
一個例子:
其中用到了 assign標(biāo)簽,assign的作用是定義一個變量。
<#assign text="{'bank':'工商銀行','account':'10101920201920212'}" />
<#assign data=text?eval />
開戶行:${data.bank} 賬號:${data.account}```
(5)常見內(nèi)建函數(shù)匯總
?html:html字符轉(zhuǎn)義 ?cap_first: 字符串的第一個字母變?yōu)榇髮懶问? ?lower_case :字符串的小寫形式 ?upper_case :字符串的大寫形式 ?trim:去掉字符串首尾的空格 ?substring(from,to):截字符串 from是第一個字符的開始索引,to最后一個字符之后的位置索引,當(dāng)to為空時,默認(rèn)的是字符串的長度 ?lenth: 取長度 ?size: 序列中元素的個數(shù) ?int: 數(shù)字的整數(shù)部分(比如 -1.9?int 就是 -1) ?replace(param1,param2):字符串替換 param1是匹配的字符串 param2是將匹配的字符替換成指定字符
內(nèi)建函數(shù)測試demo1
(1)在StudentController新增方法:
@GetMapping("innerFunc")
public String testInnerFunc(Model model) {
//1.1 小強(qiáng)對象模型數(shù)據(jù)
Student stu1 = new Student();
stu1.setName("小強(qiáng)");
stu1.setAge(18);
stu1.setMoney(1000.86f);
stu1.setBirthday(new Date());
//1.2 小紅對象模型數(shù)據(jù)
Student stu2 = new Student();
stu2.setName("小紅");
stu2.setMoney(200.1f);
stu2.setAge(19);
//1.3 將兩個對象模型數(shù)據(jù)存放到List集合中
List<Student> stus = new ArrayList<>();
stus.add(stu1);
stus.add(stu2);
model.addAttribute("stus", stus);
// 2.1 添加日期
Date date = new Date();
model.addAttribute("today", date);
// 3.1 添加數(shù)值
model.addAttribute("point", 102920122);
return "04-innerFunc";
}(2)在resources/templates目錄下創(chuàng)建04-innerFunc.ftl模版頁面:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>inner Function</title>
</head>
<body>
<b>獲得集合大小</b><br>
集合大?。?{stus?size}
<hr>
<b>獲得日期</b><br>
顯示年月日: ${today?date} <br>
顯示時分秒:${today?time}<br>
顯示日期+時間:${today?datetime}<br>
自定義格式化: ${today?string("yyyy年MM月")}<br>
<hr>
<b>內(nèi)建函數(shù)C</b><br>
沒有C函數(shù)顯示的數(shù)值:${point} <br>
有C函數(shù)顯示的數(shù)值:${point?c}
<hr>
<b>聲明變量assign</b><br>
<#assign text="{'bank':'工商銀行','account':'10101920201920212'}" />
<#assign data=text?eval />
開戶行:${data.bank} 賬號:${data.account}
<hr>
</body>
</html> (3)測試
瀏覽器訪問http://localhost:8881/student/innerFunc
效果如下

內(nèi)建函數(shù)測試demo2
需求:遍歷學(xué)生集合,顯示集合總條數(shù),id不要逗號隔開,顯示學(xué)生的生日(只顯示年月日),錢包顯示整數(shù)并顯示單位`元`,用戶姓名做脫敏處理(如果是兩個字第二個字顯示為星號,例如張三顯示為`張*`,如果大于兩個字,中間字顯示為星號,例如成吉思汗顯示為`成*汗`,諸葛亮顯示為`諸*亮`)
(1)修改StudentController中的list方法,
@GetMapping("list")
public String list(Model model) throws ParseException {
DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
List<Student> list = new ArrayList<>();
list.add(new Student(1001,"張三",15, dateFormat.parse("2007-10-01 10:00:00"), 1000.11F));
list.add(new Student(1002,"李四",28, dateFormat.parse("1994-10-01 10:00:00"), 5000.3F));
list.add(new Student(1003,"王五",45, dateFormat.parse("1977-10-01 10:00:00"), 9000.63F));
list.add(new Student(1004,"趙六",62, dateFormat.parse("1960-10-01 10:00:00"), 10000.99F));
list.add(new Student(1005,"孫七",75, dateFormat.parse("1947-10-01 10:00:00"), 16000.66F));
model.addAttribute("stus",list);
return "02-list";
} (2)修改02-list.ftl模版
共${stus?size}條數(shù)據(jù):輸出總條數(shù)
`stu.id`后面加`?c `:id不需要逗號分割
`stu.birthday`后面加`?date`:生日只輸出年月日
`stu.money`后面加`?int`:金額取整
姓名需要使用replace和substring函數(shù)處理
完整內(nèi)容如下
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>列表頁面</title>
<style>
table{
border-spacing: 0;/*把單元格間隙設(shè)置為0*/
border-collapse: collapse;/*設(shè)置單元格的邊框合并為1*/
}
td{
border:1px solid #ACBED1;
text-align: center;
}
</style>
</head>
<body>
共${stus?size}條數(shù)據(jù)
<table>
<tr>
<td>序號</td>
<td>id</td>
<td>姓名</td>
<td>所處的年齡段</td>
<td>生日</td>
<td>錢包</td>
<td>是否最后一條數(shù)據(jù)</td>
</tr>
<#list stus as stu >
<tr>
<td>${stu_index + 1}</td>
<td>${stu.id?c}</td>
<td>
<#if stu.name?length=2>
${stu.name?replace(stu.name?substring(1), "*")}
<#else>
${stu.name?replace(stu.name?substring(1, stu.name?length-1), "*")}
</#if>
</td>
<td>
<#if stu.age <= 6>
童年
<#elseif stu.age <= 17>
少年
<#elseif stu.age <= 40>
青年
<#elseif stu.age <= 65>
中年
<#else>
老年
</#if>
</td>
<td>${stu.birthday?date}</td>
<td>${stu.money?int}元</td>
<td>
<#if stu_has_next>
否
<#else>
是
</#if>
</td>
</tr>
</#list>
</table>
<hr>
</body>
</html> (3)測試
瀏覽器訪問http://localhost:8881/student/list
效果如下

2.4.9 靜態(tài)化
(1)springboot整合freemarker靜態(tài)化文件用法
編寫springboot測試用例
package com.itheima.test;
import com.itheima.freemarker.FreemarkerDemoApplication;
import com.itheima.freemarker.entity.Student;
import freemarker.template.Configuration;
import freemarker.template.Template;
import freemarker.template.TemplateException;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
import java.io.FileWriter;
import java.io.IOException;
import java.util.*;
@SpringBootTest(classes = FreemarkerDemoApplication.class)
@RunWith(SpringRunner.class)
public class FreemarkerTest {
//注入freemarker配置類
@Autowired
private Configuration configuration;
@Test
public void test() throws IOException, TemplateException {
Template template = configuration.getTemplate("04-innerFunc.ftl");
/**
* 靜態(tài)化并輸出到文件中 參數(shù)1:數(shù)據(jù)模型 參數(shù)2:文件輸出流
*/
template.process(getData(), new FileWriter("d:/list.html"));
/**
* 靜態(tài)化并輸出到字節(jié)輸出流中
*/
//StringWriter out = new StringWriter();
//template.process(getData(), out);
//System.out.println(out.toString());
}
private Map getData(){
Map<String,Object> map = new HashMap<>();
Student stu1 = new Student();
stu1.setName("小強(qiáng)");
stu1.setAge(18);
stu1.setMoney(1000.86f);
stu1.setBirthday(new Date());
//小紅對象模型數(shù)據(jù)
Student stu2 = new Student();
stu2.setName("小紅");
stu2.setMoney(200.1f);
stu2.setAge(19);
//將兩個對象模型數(shù)據(jù)存放到List集合中
List<Student> stus = new ArrayList<>();
stus.add(stu1);
stus.add(stu2);
//向model中存放List集合數(shù)據(jù)
map.put("stus",stus);
//map數(shù)據(jù)
Map<String,Student> stuMap = new HashMap<>();
stuMap.put("stu1",stu1);
stuMap.put("stu2",stu2);
map.put("stuMap",stuMap);
//日期
map.put("today",new Date());
//長數(shù)值
map.put("point",38473897438743L);
return map;
}
}(2)freemarker原生靜態(tài)化用法
package com.itheima.freemarker.test;
import com.itheima.freemarker.entity.Student;
import freemarker.cache.FileTemplateLoader;
import freemarker.cache.NullCacheStorage;
import freemarker.template.Configuration;
import freemarker.template.Template;
import freemarker.template.TemplateException;
import freemarker.template.TemplateExceptionHandler;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.util.*;
public class FreemarkerTest {
public static void main(String[] args) throws IOException, TemplateException {
//創(chuàng)建配置類
Configuration CONFIGURATION = new Configuration(Configuration.VERSION_2_3_22);
//設(shè)置模版加載路徑
//ClassTemplateLoader方式:需要將模版放在FreemarkerTest類所在的包,加載模版時會從該包下加載
//CONFIGURATION.setTemplateLoader(new ClassTemplateLoader(FreemarkerTest.class,""));
String path = java.net.URLDecoder.decode(FreemarkerTest.class.getClassLoader().getResource("").getPath(),"utf-8");
//FileTemplateLoader方式:需要將模版放置在classpath目錄下 目錄有中文也可以
CONFIGURATION.setTemplateLoader(new FileTemplateLoader(new File(path)));
//設(shè)置編碼
CONFIGURATION.setDefaultEncoding("UTF-8");
//設(shè)置異常處理器
CONFIGURATION.setTemplateExceptionHandler(TemplateExceptionHandler.RETHROW_HANDLER);
//設(shè)置緩存方式
CONFIGURATION.setCacheStorage(NullCacheStorage.INSTANCE);
//加載模版
Template template = CONFIGURATION.getTemplate("templates/04-innerFunc.ftl");
/**
* 靜態(tài)化并輸出到文件中 參數(shù)1:數(shù)據(jù)模型 參數(shù)2:文件輸出流
*/
template.process(getModel(), new FileWriter("d:/list.html"));
/**
* 靜態(tài)化并輸出到字節(jié)輸出流中
*/
//StringWriter out = new StringWriter();
//template.process(getData(), out);
//System.out.println(out.toString());
}
public static Map getModel(){
Map map = new HashMap();
//1.1 小強(qiáng)對象模型數(shù)據(jù)
Student stu1 = new Student();
stu1.setName("小強(qiáng)");
stu1.setAge(18);
stu1.setMoney(1000.86f);
stu1.setBirthday(new Date());
//1.2 小紅對象模型數(shù)據(jù)
Student stu2 = new Student();
stu2.setName("小紅");
stu2.setMoney(200.1f);
stu2.setAge(19);
//1.3 將兩個對象模型數(shù)據(jù)存放到List集合中
List<Student> stus = new ArrayList<>();
stus.add(stu1);
stus.add(stu2);
map.put("stus", stus);
// 2.1 添加日期
Date date = new Date();
map.put("today", date);
// 3.1 添加數(shù)值
map.put("point", 102920122);
return map;
}
} 3 數(shù)據(jù)庫元數(shù)據(jù)
3.1 介紹
元數(shù)據(jù)(Metadata)是描述數(shù)據(jù)的數(shù)據(jù)。
數(shù)據(jù)庫元數(shù)據(jù)(DatabaseMetaData)就是指定義數(shù)據(jù)庫各類對象結(jié)構(gòu)的數(shù)據(jù)。
在mysql中可以通過show關(guān)鍵字獲取相關(guān)的元數(shù)據(jù)
show status; 獲取數(shù)據(jù)庫的狀態(tài) show databases; 列出所有數(shù)據(jù)庫 show tables; 列出所有表 show create database [數(shù)據(jù)庫名]; 獲取數(shù)據(jù)庫的定義 show create table [數(shù)據(jù)表名]; 獲取數(shù)據(jù)表的定義 show columns from <table_name>; 顯示表的結(jié)構(gòu) show index from <table_name>; 顯示表中有關(guān)索引和索引列的信息 show character set; 顯示可用的字符集以及其默認(rèn)整理 show collation; 顯示每個字符集的整理 show variables; 列出數(shù)據(jù)庫中的參數(shù)定義值
也可以從 information_schema庫中獲取元數(shù)據(jù),information_schema數(shù)據(jù)庫是MySQL自帶的信息數(shù)據(jù)庫,它提供了訪問數(shù)據(jù)庫元數(shù)據(jù)的方式。存著其他數(shù)據(jù)庫的信息。
select schema_name from information_schema.schemata; 列出所有的庫 select table_name FROM information_schema.tables; 列出所有的表
在代碼中可以由JDBC的Connection對象通過getMetaData方法獲取而來,主要封裝了是對數(shù)據(jù)庫本身的一些整體綜合信息,例如數(shù)據(jù)庫的產(chǎn)品名稱,數(shù)據(jù)庫的版本號,數(shù)據(jù)庫的URL,是否支持事務(wù)等等。
DatabaseMetaData的常用方法:
getDatabaseProductName:獲取數(shù)據(jù)庫的產(chǎn)品名稱 getDatabaseProductName:獲取數(shù)據(jù)庫的版本號 getUserName:獲取數(shù)據(jù)庫的用戶名 getURL:獲取數(shù)據(jù)庫連接的URL getDriverName:獲取數(shù)據(jù)庫的驅(qū)動名稱 driverVersion:獲取數(shù)據(jù)庫的驅(qū)動版本號 isReadOnly:查看數(shù)據(jù)庫是否只允許讀操作 supportsTransactions:查看數(shù)據(jù)庫是否支持事務(wù)
3.2 搭建環(huán)境
(1)導(dǎo)入mysql依賴
<dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.47</version> </dependency>
(2)創(chuàng)建測試用例
package com.itheima.test;
import org.junit.Before;
import org.junit.Test;
import java.sql.*;
import java.util.Properties;
public class DataBaseMetaDataTest {
private Connection conn;
@Before
public void init() throws Exception {
Properties pro = new Properties();
pro.setProperty("user", "root");
pro.setProperty("password", "123456");
pro.put("useInformationSchema", "true");//獲取mysql表注釋
//pro.setProperty("remarksReporting","true");//獲取oracle表注釋
conn = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/?useUnicode=true&characterEncoding=UTF8", pro);
}
} 3.3 綜合信息元數(shù)據(jù)
(1)獲取數(shù)據(jù)庫元信息綜合信息
@Test
public void testDatabaseMetaData() throws SQLException {
//獲取數(shù)據(jù)庫元數(shù)據(jù)
DatabaseMetaData dbMetaData = conn.getMetaData();
//獲取數(shù)據(jù)庫產(chǎn)品名稱
String productName = dbMetaData.getDatabaseProductName();
System.out.println(productName);
//獲取數(shù)據(jù)庫版本號
String productVersion = dbMetaData.getDatabaseProductVersion();
System.out.println(productVersion);
//獲取數(shù)據(jù)庫用戶名
String userName = dbMetaData.getUserName();
System.out.println(userName);
//獲取數(shù)據(jù)庫連接URL
String userUrl = dbMetaData.getURL();
System.out.println(userUrl);
//獲取數(shù)據(jù)庫驅(qū)動
String driverName = dbMetaData.getDriverName();
System.out.println(driverName);
//獲取數(shù)據(jù)庫驅(qū)動版本號
String driverVersion = dbMetaData.getDriverVersion();
System.out.println(driverVersion);
//查看數(shù)據(jù)庫是否允許讀操作
boolean isReadOnly = dbMetaData.isReadOnly();
System.out.println(isReadOnly);
//查看數(shù)據(jù)庫是否支持事務(wù)操作
boolean supportsTransactions = dbMetaData.supportsTransactions();
System.out.println(supportsTransactions);
}(2)獲取數(shù)據(jù)庫列表
@Test
public void testFindAllCatalogs() throws Exception {
//獲取元數(shù)據(jù)
DatabaseMetaData metaData = conn.getMetaData();
//獲取數(shù)據(jù)庫列表
ResultSet rs = metaData.getCatalogs();
//遍歷獲取所有數(shù)據(jù)庫表
while (rs.next()) {
//打印數(shù)據(jù)庫名稱
System.out.println(rs.getString(1));
}
//釋放資源
rs.close();
conn.close();
}(3)獲取某數(shù)據(jù)庫中的所有表信息
@Test
public void testFindAllTable() throws Exception {
//獲取元數(shù)據(jù)
DatabaseMetaData metaData = conn.getMetaData();
//獲取所有的數(shù)據(jù)庫表信息
ResultSet rs = metaData.getTables("庫名", "%", "%", new String[]{"TABLE"});
//拼裝table
while (rs.next()) {
//所屬數(shù)據(jù)庫
System.out.println(rs.getString(1));
//所屬schema
System.out.println(rs.getString(2));
//表名
System.out.println(rs.getString(3));
//數(shù)據(jù)庫表類型
System.out.println(rs.getString(4));
//數(shù)據(jù)庫表備注
System.out.println(rs.getString(5));
System.out.println("--------------");
}
}(4)獲取某張表所有的列信息
@Test
public void testFindAllColumns() throws Exception {
//獲取元數(shù)據(jù)
DatabaseMetaData metaData = conn.getMetaData();
//獲取所有的數(shù)據(jù)庫某張表所有列信息
ResultSet rs = metaData.getColumns("庫名", "%", "表名","%");
while(rs.next()) {
//表名
System.out.println(rs.getString("TABLE_NAME"));
//列名
System.out.println(rs.getString("COLUMN_NAME"));
//類型碼值
System.out.println(rs.getString("DATA_TYPE"));
//類型名稱
System.out.println(rs.getString("TYPE_NAME"));
//列的大小
System.out.println(rs.getString("COLUMN_SIZE"));
//小數(shù)部分位數(shù),不適用的類型會返回null
System.out.println(rs.getString("DECIMAL_DIGITS"));
//是否允許使用null
System.out.println(rs.getString("NULLABLE"));
//列的注釋信息
System.out.println(rs.getString("REMARKS"));
//默認(rèn)值
System.out.println(rs.getString("COLUMN_DEF"));
//是否自增
System.out.println(rs.getString("IS_AUTOINCREMENT"));
//表中的列的索引(從 1 開始
System.out.println(rs.getString("ORDINAL_POSITION"));
System.out.println("--------------");
}
} 3.4 參數(shù)元數(shù)據(jù)
參數(shù)元數(shù)據(jù)(ParameterMetaData):是由PreparedStatement對象通過getParameterMetaData方法獲取而
來,主要是針對PreparedStatement對象和其預(yù)編譯的SQL命令語句提供一些信息,ParameterMetaData能提供占位符參數(shù)的個數(shù),獲取指定位置占位符的SQL類型等等
以下有一些關(guān)于ParameterMetaData的常用方法:
```
getParameterCount:獲取預(yù)編譯SQL語句中占位符參數(shù)的個數(shù)
```
@Test
public void testParameterMetaData() throws Exception {
String sql = "select * from health.t_checkgroup where id=? and code=?";
PreparedStatement pstmt = conn.prepareStatement(sql);
pstmt.setString(1, "7");
pstmt.setString(2, "0003");
//獲取ParameterMetaData對象
ParameterMetaData paramMetaData = pstmt.getParameterMetaData();
//獲取參數(shù)個數(shù)
int paramCount = paramMetaData.getParameterCount();
System.out.println(paramCount);
} 3.5 結(jié)果集元數(shù)據(jù)
結(jié)果集元數(shù)據(jù)(ResultSetMetaData):是由ResultSet對象通過getMetaData方法獲取而來,主要是針對由數(shù)據(jù)庫執(zhí)行的SQL腳本命令獲取的結(jié)果集對象ResultSet中提供的一些信息,比如結(jié)果集中的列數(shù)、指定列的名稱、指定列的SQL類型等等,可以說這個是對于框架來說非常重要的一個對象。
以下有一些關(guān)于ResultSetMetaData的常用方法:
```
getColumnCount:獲取結(jié)果集中列項(xiàng)目的個數(shù)
getColumnType:獲取指定列的SQL類型對應(yīng)于Java中Types類的字段
getColumnTypeName:獲取指定列的SQL類型
getClassName:獲取指定列SQL類型對應(yīng)于Java中的類型(包名加類名
```
@Test
public void testResultSetMetaData() throws Exception {
String sql = "select * from health.t_checkgroup where id=?";
PreparedStatement pstmt = conn.prepareStatement(sql);
pstmt.setString(1, "7");
//執(zhí)行sql語句
ResultSet rs = pstmt.executeQuery();
//獲取ResultSetMetaData對象
ResultSetMetaData metaData = rs.getMetaData();
//獲取查詢字段數(shù)量
int columnCount = metaData.getColumnCount();
System.out.println("字段總數(shù)量:"+ columnCount);
for (int i = 1; i <= columnCount; i++) {
//獲取表名稱
System.out.println(metaData.getColumnName(i));
//獲取java類型
System.out.println(metaData.getColumnClassName(i));
//獲取sql類型
System.out.println(metaData.getColumnTypeName(i));
System.out.println("----------");
}
} 4 代碼生成器環(huán)境搭建
4.1 創(chuàng)建maven工程
創(chuàng)建maven工程并導(dǎo)入以下依賴
<properties> <java.version>11</java.version> <!-- 項(xiàng)目源碼及編譯輸出的編碼 --> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> <!-- 項(xiàng)目編譯JDK版本 --> <maven.compiler.source>11</maven.compiler.source> <maven.compiler.target>11</maven.compiler.target> </properties> <dependencies> <dependency> <groupId>org.freemarker</groupId> <artifactId>freemarker</artifactId> <version>2.3.23</version> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.47</version> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <version>1.18.8</version> </dependency> <dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-lang3</artifactId> <version>3.10</version> </dependency> </dependencies>
目錄結(jié)構(gòu)如下

4.2 編碼
4.2.1 常量類
package freemarker.constant;
public class TemplateConstant {
//實(shí)體類模板
public static final String entityTemplate = "templates/Entity.ftl";
//Mapper模板
public static final String mapperTemplate = "templates/Mapper.ftl";
//Mapper映射文件模版
public static final String mapperXmlTemplate = "templates/MapperXml.ftl";
//service模版
public static final String serviceTemplate = "templates/Service.ftl";
//service實(shí)現(xiàn)類模版
public static final String serviceImplTemplate = "templates/ServiceImpl.ftl";
//controller模版
public static final String controllerTemplate = "templates/Controller.ftl";
//vo模版
public static final String entityVoTemplate = "templates/EntityVo.ftl";
//dto模版
public static final String entityDtoTemplate = "templates/EntityDto.ftl";
//pom模版
public static final String pomTemplate = "templates/pom.ftl";
//application.yml模版
public static final String applicationTemplate = "templates/application.ftl";
} 4.2.2 工具類
(1)DbUtil數(shù)據(jù)庫工具類
package freemarker.util;
import freemarker.param.ColumnClass;
import freemarker.param.TableClass;
import lombok.Getter;
import lombok.Setter;
import java.sql.*;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;
/**
* 數(shù)據(jù)庫工具類
*/
@Setter
@Getter
public class DbUtil {
//數(shù)據(jù)庫連接地址
private String url = "jdbc:mysql://localhost:3306/heima_leadnews_wemedia?useSSL=false&nullCatalogMeansCurrent=true&serverTimezone=UTC";
//數(shù)據(jù)庫用戶名
private String username = "root";
//數(shù)據(jù)庫密碼
private String password = "123456";
//數(shù)據(jù)庫驅(qū)動
private String driver = "com.mysql.jdbc.Driver";
//數(shù)據(jù)庫名稱
private String dbName = null;
private Connection connection =null;
/**
* 獲取jdbc鏈接
* @return
* @throws Exception
*/
public Connection getConnection() throws Exception{
Properties pro = new Properties();
pro.setProperty("user", username);
pro.setProperty("password", password);
pro.put("useInformationSchema", "true");//獲取mysql表注釋
//pro.setProperty("remarksReporting","true");//獲取oracle表注釋
Class.forName(driver);
connection = DriverManager.getConnection(url, pro);
return connection;
}
/**
* 獲取當(dāng)前數(shù)據(jù)庫下的所有表名稱及注釋
* @return
* @throws Exception
*/
public List<TableClass> getAllTables() throws Exception {
List<TableClass> list = new ArrayList<>();
//獲取鏈接
Connection conn = getConnection();
//獲取元數(shù)據(jù)
DatabaseMetaData metaData = conn.getMetaData();
//獲取所有的數(shù)據(jù)庫表信息
ResultSet rs = metaData.getTables(dbName!=null?dbName:conn.getCatalog(), "%", "%", new String[]{"TABLE"});
while (rs.next()) {
TableClass tableClass = new TableClass();
tableClass.setTableName(rs.getString(3));
tableClass.setTableComment(rs.getString(5));
list.add(tableClass);
}
return list;
}
/**
* 獲取某張表的所有列
* @param tableName
* @return
* @throws Exception
*/
public List<ColumnClass> getAllColumns(String tableName) throws Exception {
List<ColumnClass> list = new ArrayList<>();
//獲取鏈接
Connection conn = getConnection();
//獲取元數(shù)據(jù)
DatabaseMetaData metaData = conn.getMetaData();
//獲取所有的數(shù)據(jù)庫某張表所有列信息
ResultSet rs = metaData.getColumns(dbName!=null?dbName:conn.getCatalog(), "%", tableName,"%");
while(rs.next()) {
ColumnClass columnClass = new ColumnClass();
columnClass.setColumnName(rs.getString("COLUMN_NAME"));
columnClass.setColumnType(rs.getString("TYPE_NAME"));
columnClass.setColumnComment(rs.getString("REMARKS"));
columnClass.setChangeColumnName(StrUtil.changeColumnStr(rs.getString("COLUMN_NAME")));
list.add(columnClass);
}
return list;
}
/**
* 關(guān)閉鏈接
*/
public void closeConnection(){
try {
connection.close();
} catch (SQLException e) {
e.printStackTrace();
}
};
}(2)字符串處理工具類
package freemarker.util;
/**
* 字符串處理工具類
*/
public class StrUtil {
/**
* 去掉下劃線轉(zhuǎn)駝峰 user_name -> userName
* @param str
* @return
*/
public static String changeColumnStr(String str) {
String name = str;
if (name.indexOf("_") > 0 && name.length() != name.indexOf("_") + 1) {
int lengthPlace = name.indexOf("_");
name = name.replaceFirst("_", "");
String s = name.substring(lengthPlace, lengthPlace + 1);
s = s.toUpperCase();
str = name.substring(0, lengthPlace) + s + name.substring(lengthPlace + 1);
} else {
return str;
}
return changeColumnStr(str);
}
/**
* 去掉下劃線轉(zhuǎn)駝峰 tb_user -> TbUser
* @param str
* @return
*/
public static String changeTableStr(String str) {
String s = changeColumnStr(str);
return s.substring(0,1).toUpperCase()+s.substring(1);
}
}(3)FreeMarker模版工具類
package freemarker.util;
import freemarker.cache.FileTemplateLoader;
import freemarker.cache.NullCacheStorage;
import freemarker.template.Configuration;
import freemarker.template.Template;
import freemarker.template.TemplateExceptionHandler;
import java.io.File;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
/**
* FreeMarker模版工具類
*/
public class FreeMarkerTemplateUtils {
private FreeMarkerTemplateUtils(){}
private static final Configuration CONFIGURATION = new Configuration(Configuration.VERSION_2_3_22);
static{
//ClassTemplateLoader方式:需要將模版放在FreeMarkerTemplateUtils類所在的包,加載模版時會從該包下加載
//CONFIGURATION.setTemplateLoader(new ClassTemplateLoader(FreeMarkerTemplateUtils.class,""));
try {
String path = java.net.URLDecoder.decode(FreeMarkerTemplateUtils.class.getClassLoader().getResource("").getPath(),"utf-8");
//FileTemplateLoader方式:需要將模版放置在classpath目錄下 目錄有中文也可以
CONFIGURATION.setTemplateLoader(new FileTemplateLoader(new File(path)));
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
CONFIGURATION.setDefaultEncoding("UTF-8");
CONFIGURATION.setTemplateExceptionHandler(TemplateExceptionHandler.RETHROW_HANDLER);
CONFIGURATION.setCacheStorage(NullCacheStorage.INSTANCE);
}
public static Template getTemplate(String templateName) throws IOException {
try {
return CONFIGURATION.getTemplate(templateName);
} catch (IOException e) {
throw e;
}
}
public static void clearCache() {
CONFIGURATION.clearTemplateCache();
}
} 4.2.3 實(shí)體類
(1)表實(shí)體類
package freemarker.param;
import lombok.Data;
@Data
public class TableClass {
/**
* 表名 tb_user
**/
private String tableName;
/**
* 表注釋
**/
private String tableComment;
}(2)列實(shí)體類
package freemarker.param;
import lombok.Data;
@Data
public class ColumnClass {
/**
* 數(shù)據(jù)庫字段名稱 user_name
**/
private String columnName;
/**
* 數(shù)據(jù)庫字段類型
**/
private String columnType;
/**
* 數(shù)據(jù)庫字段首字母小寫且去掉下劃線字符串 userName
**/
private String changeColumnName;
/**
* 數(shù)據(jù)庫字段注釋
**/
private String columnComment;
}(3)模版相關(guān)參數(shù)類
package freemarker.param;
import lombok.Data;
import org.apache.commons.lang3.StringUtils;
import java.text.SimpleDateFormat;
import java.util.Date;
@Data
public class TemplatePathParam {
private String currentDate = new SimpleDateFormat("yyyy/MM/dd").format(new Date());
//包名 com.itheima.user
private String packageName;
//代碼生成路徑 D:\\path
private String basePath;
//項(xiàng)目名稱 英文 比如itheima-user
private String projectName;
//作者
private String author ;
//實(shí)體類生成的絕對路徑
private String entityPath;
//vo實(shí)體類生成的絕對路徑
private String entityVoPath;
//Dto實(shí)體類生成的絕對路徑
private String entityDtoPath;
//mapper生成絕對路徑
private String mapperPath;
//mapper映射文件生成的絕對路徑
private String mapperXmlPath;
//service接口生成的絕對路徑
private String servicePath;
//service實(shí)現(xiàn)類生成的絕對路徑
private String serviceImplPath;
//controller生成的絕對路徑
private String controllerPath;
//pom文件生成的絕對路徑
private String pomPath;
//application.yml文件生成的絕對路徑
private String applicationYmlPath;
public TemplatePathParam(String packageName, String basePath, String projectName, String author) {
if(StringUtils.isBlank(packageName)
|| StringUtils.isBlank(basePath)
|| StringUtils.isBlank(author)
|| StringUtils.isBlank(projectName)){
throw new RuntimeException("參數(shù)不能為空");
}
this.packageName = packageName;
this.basePath = basePath;
this.author = author;
this.projectName = projectName;
String[] split = packageName.split("\\.");
// D:\\path\\itheima-user\\src\\main\\java\\com\\itheima\\user
String javaModelPath = basePath+"\\"+projectName+"\\src\\main\\java\\"+split[0]+"\\"+split[1]+"\\"+split[2];
String xmlModelPath = basePath+"\\"+projectName+"\\src\\main\\resources\\"+split[0]+"\\"+split[1]+"\\"+split[2];
this.setEntityPath(javaModelPath+"\\entity");
this.setMapperPath(javaModelPath+"\\mapper");
this.setMapperXmlPath(xmlModelPath+"\\mapper");
this.setServicePath(javaModelPath+"\\service");
this.setServiceImplPath(javaModelPath+"\\service\\impl");
this.setControllerPath(javaModelPath+"\\http\\controller");
this.setEntityVoPath(javaModelPath+"\\http\\vo");
this.setEntityDtoPath(javaModelPath+"\\http\\dto");
this.setEntityDtoPath(javaModelPath+"\\http\\dto");
this.setPomPath(basePath+"\\"+projectName);
this.setApplicationYmlPath(basePath+"\\"+projectName+"\\src\\main\\resources");
}
}4.2.4 代碼生成器入口類
package freemarker;
import freemarker.constant.TemplateConstant;
import freemarker.param.ColumnClass;
import freemarker.param.TableClass;
import freemarker.param.TemplatePathParam;
import freemarker.template.Template;
import freemarker.util.DbUtil;
import freemarker.util.FreeMarkerTemplateUtils;
import freemarker.util.StrUtil;
import org.apache.commons.lang3.StringUtils;
import java.io.*;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* 代碼生成器入口
*/
public class CodeGenerateUtils {
private TemplatePathParam templatePathParam = null;
public static void main(String[] args) throws Exception{
CodeGenerateUtils codeGenerateUtils = new CodeGenerateUtils();
codeGenerateUtils.generate();
System.out.println("============ 全部生成完成! =============");
}
public void generate() throws Exception{
/**
* 參數(shù)1:報名
* 參數(shù)2:生成代碼的基礎(chǔ)路徑
* 參數(shù)3:項(xiàng)目名稱
* 參數(shù)4:作者
*/
templatePathParam = new TemplatePathParam("com.itheima.wemedia",
"D:\\heima\\技術(shù)文章\\代碼",
"itheima-wemedia",
"kdm");
//數(shù)據(jù)庫相關(guān)
DbUtil dbUtil = new DbUtil();
//獲取所有表
List<TableClass> allTable = dbUtil.getAllTables();
for (TableClass tableClass : allTable) {
//表名
String table = tableClass.getTableName();
//獲取所有列
List<ColumnClass> allColumns = dbUtil.getAllColumns(table);
System.out.println("-------- 正在生成 " + table+" 表相關(guān)文件------");
//生成實(shí)體類
System.out.println("生成實(shí)體類");
generateEntityFile(tableClass, allColumns);
//生成Mapper
System.out.println("生成Mapper");
generateMapperFile(tableClass, allColumns);
//生成Mapper.xml
System.out.println("生成Mapper映射文件");
generateMapperXmlFile(tableClass, allColumns);
//生成service接口
System.out.println("生成service接口");
generateServiceFile(tableClass, allColumns);
//生成service實(shí)現(xiàn)類
System.out.println("生成service實(shí)現(xiàn)類");
generateServiceImplFile(tableClass, allColumns);
//生成Controller層文件
System.out.println("生成Controller層文件");
generateControllerFile(tableClass, allColumns);
//生成vo類
System.out.println("生成vo類");
generateEntityVoFile(tableClass, allColumns);
//生成dto類
System.out.println("生成dto類");
generateEntityDtoFile(tableClass, allColumns);
//生成pom文件
System.out.println("生成pom文件");
generatePomFile(tableClass, allColumns);
//生成application.yml文件
System.out.println("生成application.yml文件");
generateApplicationYmlFile(tableClass, allColumns);
}
dbUtil.closeConnection();
}
/**
* 生成實(shí)體文件
*/
private void generateEntityFile(TableClass tableClass, List<ColumnClass> allColumns) throws Exception{
String suffix = ".java";
String filePath = templatePathParam.getEntityPath();
String file = templatePathParam.getEntityPath() + "\\"+ StrUtil.changeTableStr(tableClass.getTableName()) + suffix;
Map<String,Object> dataMap = new HashMap<String,Object>();
dataMap.put("model_column",allColumns);
dataMap = getCommonModel(dataMap, tableClass);
generateFileByTemplate(TemplateConstant.entityTemplate, filePath, file, dataMap);
}
/**
* 生成mapper文件
*/
private void generateMapperFile(TableClass tableClass, List<ColumnClass> allColumns) throws Exception{
String suffix = "Mapper.java";
String filePath = templatePathParam.getMapperPath();
String file = templatePathParam.getMapperPath() + "\\"+ StrUtil.changeTableStr(tableClass.getTableName()) + suffix;
Map<String,Object> dataMap = new HashMap<String,Object>();
dataMap = getCommonModel(dataMap, tableClass);
generateFileByTemplate(TemplateConstant.mapperTemplate, filePath, file, dataMap);
}
/**
* 生成xml映射文件
*/
private void generateMapperXmlFile(TableClass tableClass, List<ColumnClass> allColumns) throws Exception{
String suffix = "Mapper.xml";
String filePath = templatePathParam.getMapperXmlPath();
String file = templatePathParam.getMapperXmlPath() + "\\"+ StrUtil.changeTableStr(tableClass.getTableName()) + suffix;
Map<String,Object> dataMap = new HashMap<String,Object>();
dataMap = getCommonModel(dataMap, tableClass);
generateFileByTemplate(TemplateConstant.mapperXmlTemplate, filePath, file, dataMap);
}
/**
* 生成業(yè)務(wù)接口層
*/
private void generateServiceFile(TableClass tableClass, List<ColumnClass> allColumns) throws Exception{
String suffix = "Service.java";
String filePath = templatePathParam.getServicePath();
String file = templatePathParam.getServicePath() + "\\"+ StrUtil.changeTableStr(tableClass.getTableName()) + suffix;
Map<String,Object> dataMap = new HashMap<String,Object>();
dataMap = getCommonModel(dataMap, tableClass);
generateFileByTemplate(TemplateConstant.serviceTemplate, filePath, file, dataMap);
}
/**
* 生成業(yè)務(wù)實(shí)現(xiàn)層
*/
private void generateServiceImplFile(TableClass tableClass, List<ColumnClass> allColumns) throws Exception{
String suffix = "ServiceImpl.java";
String filePath = templatePathParam.getServiceImplPath();
String file = templatePathParam.getServiceImplPath() + "\\"+ StrUtil.changeTableStr(tableClass.getTableName()) + suffix;
Map<String,Object> dataMap = new HashMap<String,Object>();
dataMap = getCommonModel(dataMap, tableClass);
generateFileByTemplate(TemplateConstant.serviceImplTemplate, filePath, file, dataMap);
}
/**
* 生成控制層
*/
private void generateControllerFile(TableClass tableClass, List<ColumnClass> allColumns) throws Exception{
String suffix = "Controller.java";
String filePath = templatePathParam.getControllerPath();
String file = templatePathParam.getControllerPath() + "\\"+ StrUtil.changeTableStr(tableClass.getTableName()) + suffix;
Map<String,Object> dataMap = new HashMap<String,Object>();
dataMap = getCommonModel(dataMap, tableClass);
generateFileByTemplate(TemplateConstant.controllerTemplate, filePath, file, dataMap);
}
/**
* 生成Vo類
*/
private void generateEntityVoFile(TableClass tableClass, List<ColumnClass> allColumns) throws Exception{
String suffix = "Vo.java";
String filePath = templatePathParam.getEntityVoPath();
String file = templatePathParam.getEntityVoPath() + "\\"+ StrUtil.changeTableStr(tableClass.getTableName()) + suffix;
Map<String,Object> dataMap = new HashMap<String,Object>();
dataMap.put("model_column",allColumns);
dataMap = getCommonModel(dataMap, tableClass);
generateFileByTemplate(TemplateConstant.entityVoTemplate, filePath, file, dataMap);
}
/**
* 生成Dto類
*/
private void generateEntityDtoFile(TableClass tableClass, List<ColumnClass> allColumns) throws Exception{
String suffix = "Dto.java";
String filePath = templatePathParam.getEntityDtoPath();
String file = templatePathParam.getEntityDtoPath() + "\\"+ StrUtil.changeTableStr(tableClass.getTableName()) + suffix;
Map<String,Object> dataMap = new HashMap<String,Object>();
dataMap.put("model_column",allColumns);
dataMap = getCommonModel(dataMap, tableClass);
generateFileByTemplate(TemplateConstant.entityDtoTemplate, filePath, file, dataMap);
}
/**
* 生成Pom文件
*/
private void generatePomFile(TableClass tableClass, List<ColumnClass> allColumns) throws Exception{
String suffix = "pom.xml";
String filePath = templatePathParam.getPomPath();
String file = templatePathParam.getPomPath() + "\\" + suffix;
Map<String,Object> dataMap = new HashMap<String,Object>();
dataMap = getCommonModel(dataMap, tableClass);
generateFileByTemplate(TemplateConstant.pomTemplate, filePath, file, dataMap);
}
/**
* 生成application.yml文件
*/
private void generateApplicationYmlFile(TableClass tableClass, List<ColumnClass> allColumns) throws Exception{
String suffix = "application.yml";
String filePath = templatePathParam.getApplicationYmlPath();
String file = templatePathParam.getApplicationYmlPath() + "\\" + suffix;
Map<String,Object> dataMap = new HashMap<String,Object>();
dataMap = getCommonModel(dataMap, tableClass);
generateFileByTemplate(TemplateConstant.applicationTemplate, filePath, file, dataMap);
}
/**
* 模版通用參數(shù)
* @param dataMap 模型map
* @param tableClass 表名和表注釋參數(shù)
* @return
*/
public Map<String,Object> getCommonModel(Map<String,Object> dataMap, TableClass tableClass){
dataMap.put("table_name", StrUtil.changeTableStr(tableClass.getTableName()));//TbUser
dataMap.put("table_name_small",StrUtil.changeColumnStr(tableClass.getTableName()));//tbUser
dataMap.put("table",tableClass.getTableName());//tb_user
dataMap.put("author",templatePathParam.getAuthor());
dataMap.put("date",templatePathParam.getCurrentDate());
dataMap.put("package_name",templatePathParam.getPackageName());
dataMap.put("project_name",templatePathParam.getProjectName());
dataMap.put("table_annotation", StringUtils.isNotBlank(tableClass.getTableComment()) ? tableClass.getTableComment() : null);
return dataMap;
}
/**
* 靜態(tài)化方法
* @param templateName 模版名稱
* @param filePathParam 文件所在目錄 絕對路徑
* @param fileParam 文件 絕對路徑
* @param dataMap 數(shù)據(jù)模型
* @throws Exception
*/
private void generateFileByTemplate(final String templateName,
String filePathParam,
String fileParam,
Map<String,Object> dataMap) throws Exception{
Template template = FreeMarkerTemplateUtils.getTemplate(templateName);
System.out.println(fileParam);
//文件夾不存在創(chuàng)建文件夾
File filePath = new File(filePathParam);
if (!filePath.exists() && !filePath.isDirectory())
{
filePath.mkdirs();
}
//文件不存在創(chuàng)建文件夾
File file = new File(fileParam);
if(!file.exists())
{
try {
file.createNewFile();
} catch (IOException e) {
e.printStackTrace();
}
}
FileOutputStream fos = new FileOutputStream(file);
Writer out = new BufferedWriter(new OutputStreamWriter(fos, "utf-8"),10240);
template.process(dataMap,out);
}
} 5 制作通用模版
在 resources/templates 目錄下創(chuàng)建模版類
5.1 實(shí)體類模版
package ${package_name}.entity;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import lombok.ToString;
import java.util.Date;
import java.math.BigDecimal;
import com.fasterxml.jackson.annotation.JsonFormat;
import java.io.Serializable;
/**
* 描述:<#if table_annotation??>${table_annotation}模型</#if>
* @author ${author}
* @date ${date}
*/
@Data
@ToString(callSuper = true)
@TableName("${table}")
public class ${table_name} implements Serializable {
<#if model_column?exists>
<#list model_column as model>
/**
* ${model.columnComment!}
*/
<#if (model.columnType = 'BIGINT' && model.columnName = 'id')>
@TableId("${model.columnName?uncap_first}")
private Long ${model.changeColumnName?uncap_first};
</#if>
<#if (model.columnType = 'BIGINT' && model.columnName != 'id')>
@TableField("${model.columnName?uncap_first}")
private Long ${model.changeColumnName?uncap_first};
</#if>
<#if (model.columnType = 'INT' || model.columnType = 'INT UNSIGNED' || model.columnType = 'TINYINT' || model.columnType = 'TINYINT UNSIGNED')>
@TableField("${model.columnName?uncap_first}")
private Integer ${model.changeColumnName?uncap_first};
</#if>
<#if (model.columnType = 'DECIMAL')>
@TableField("${model.columnName?uncap_first}")
private BigDecimal ${model.changeColumnName?uncap_first};
</#if>
<#if (model.columnType = 'VARCHAR' || model.columnType = 'TEXT' || model.columnType = 'CHAR')>
@TableField("${model.columnName?uncap_first}")
private String ${model.changeColumnName?uncap_first};
</#if>
<#if model.columnType = 'TIMESTAMP' || model.columnType = 'YEAR' || model.columnType = 'DATE' || model.columnType = 'DATETIME' >
@TableField("${model.columnName?uncap_first}")
@JsonFormat(pattern="yyyy-MM-dd HH:mm:ss", timezone="GMT+8")
private Date ${model.changeColumnName?uncap_first};
</#if>
<#if (model.columnType != 'BIGINT'
&& model.columnType != 'INT'
&& model.columnType != 'DECIMAL'
&& model.columnType != 'VARCHAR'
&& model.columnType != 'TEXT'
&& model.columnType != 'CHAR'
&& model.columnType != 'TIMESTAMP'
&& model.columnType != 'YEAR'
&& model.columnType != 'DATE'
&& model.columnType != 'DATETIME'
&& model.columnType != 'INT UNSIGNED'
&& model.columnType != 'TINYINT'
&& model.columnType != 'TINYINT UNSIGNED')>
@TableField("${model.columnName?uncap_first}")
private MISS ${model.changeColumnName?uncap_first};
</#if>
</#list>
</#if>
}5.2 Mapper模版
package ${package_name}.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import ${package_name}.entity.${table_name};
import org.apache.ibatis.annotations.Mapper;
/**
* 描述:<#if table_annotation??>${table_annotation}數(shù)據(jù)庫連接層</#if>
* @author ${author}
* @date ${date}
*/
@Mapper
public interface ${table_name}Mapper extends BaseMapper<${table_name}> {
}5.3 Mapper映射文件模版
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="${package_name}.mapper.${table_name}Mapper">
</mapper>5.4 Service接口模版
package ${package_name}.service;
import ${package_name}.entity.${table_name};
import com.baomidou.mybatisplus.extension.service.IService;
/**
* 描述:<#if table_annotation??>${table_annotation}服務(wù)實(shí)現(xiàn)層接口</#if>
* @author ${author}
* @date ${date}
*/
public interface ${table_name}Service extends IService<${table_name}>{
}5.5 Service實(shí)現(xiàn)類模版
package ${package_name}.service.impl;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import ${package_name}.entity.${table_name};
import ${package_name}.service.${table_name}Service;
import ${package_name}.mapper.${table_name}Mapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
/**
* 描述:<#if table_annotation??>${table_annotation}服務(wù)實(shí)現(xiàn)層</#if>
* @author ${author}
* @date ${date}
*/
@Slf4j
@Service
public class ${table_name}ServiceImpl extends ServiceImpl<${table_name}Mapper, ${table_name}> implements ${table_name}Service{
}5.6 Controller模版
package ${package_name}.http.controller;
import org.springframework.web.bind.annotation.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.BeanUtils;
import org.springframework.validation.annotation.Validated;
import ${package_name}.entity.${table_name};
import ${package_name}.service.${table_name}Service;
import ${package_name}.http.vo.${table_name}Vo;
import ${package_name}.http.dto.${table_name}Dto;
import java.util.List;
/**
* 描述:<#if table_annotation??>${table_annotation}控制層</#if>
* @author ${author}
* @date ${date}
*/
@RestController
@RequestMapping("/${table_name_small}")
public class ${table_name}Controller {
@Autowired
private ${table_name}Service ${table_name_small}Service;
/**
* 查詢所有
*/
@GetMapping
public List<${table_name}> list(){
return ${table_name_small}Service.list();
}
/**
* 查詢一個
*/
@GetMapping("/{id}")
public ${table_name} get(@PathVariable Long id){
return ${table_name_small}Service.getById(id);
}
/**
* 新增
*/
@PostMapping
public boolean save(@Validated @RequestBody ${table_name}Dto ${table_name_small}Dto){
${table_name} ${table_name_small} = new ${table_name}();
BeanUtils.copyProperties(${table_name_small}Dto, ${table_name_small});
return ${table_name_small}Service.save(${table_name_small});
}
/**
* 修改
*/
@PutMapping
public boolean update(@Validated @RequestBody ${table_name}Dto ${table_name_small}Dto){
${table_name} ${table_name_small} = new ${table_name}();
BeanUtils.copyProperties(${table_name_small}Dto, ${table_name_small});
return ${table_name_small}Service.updateById(${table_name_small});
}
/**
* 刪除
* @param id
* @return 是否成功
*/
@DeleteMapping("/{id}")
public boolean del(@PathVariable Long id){
return ${table_name_small}Service.removeById(id);
}
}5.7 實(shí)體類Vo模版
package ${package_name}.http.vo;
import java.io.Serializable;
import java.util.Date;
import lombok.Data;
import lombok.ToString;
import java.math.BigDecimal;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
/**
* 描述:<#if table_annotation??>${table_annotation}模型</#if>Vo類
* @author ${author}
* @date ${date}
*/
@Data
@ToString(callSuper = true)
public class ${table_name}Vo implements Serializable {
<#if model_column?exists>
<#list model_column as model>
<#if (model.columnType = 'BIGINT' && model.columnName = 'id')>
@JsonSerialize(using = ToStringSerializer.class)
private Long ${model.changeColumnName?uncap_first};
</#if>
<#if (model.columnType = 'BIGINT' && model.columnName != 'id')>
private Long ${model.changeColumnName?uncap_first};
</#if>
<#if (model.columnType = 'INT' || model.columnType = 'INT UNSIGNED' || model.columnType = 'TINYINT')>
private Integer ${model.changeColumnName?uncap_first};
</#if>
<#if (model.columnType = 'DECIMAL')>
private BigDecimal ${model.changeColumnName?uncap_first};
</#if>
<#if (model.columnType = 'VARCHAR' || model.columnType = 'TEXT' || model.columnType = 'CHAR')>
private String ${model.changeColumnName?uncap_first};
</#if>
<#if model.columnType = 'TIMESTAMP' || model.columnType = 'YEAR' || model.columnType = 'DATE' || model.columnType = 'DATETIME' >
@JsonFormat(pattern="yyyy-MM-dd HH:mm:ss", timezone="GMT+8")
private Date ${model.changeColumnName?uncap_first};
</#if>
<#if (model.columnType != 'BIGINT' && model.columnType != 'INT' && model.columnType != 'VARCHAR' && model.columnType != 'DECIMAL' && model.columnType != 'TEXT' && model.columnType != 'CHAR' && model.columnType != 'TIMESTAMP' && model.columnType != 'YEAR' && model.columnType != 'DATE' && model.columnType != 'DATETIME' && model.columnType != 'INT UNSIGNED')>
private MISS ${model.changeColumnName?uncap_first};
</#if>
</#list>
</#if>
}5.8 實(shí)體類Dto模版
package ${package_name}.http.dto;
import java.io.Serializable;
import java.util.Date;
import lombok.Data;
import lombok.ToString;
import java.math.BigDecimal;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
import com.fasterxml.jackson.annotation.JsonFormat;
/**
* 描述:<#if table_annotation??>${table_annotation}模型</#if>Dto類
* @author ${author}
* @date ${date}
*/
@Data
@ToString(callSuper = true)
public class ${table_name}Dto implements Serializable {
<#if model_column?exists>
<#list model_column as model>
<#if (model.columnType = 'BIGINT' && model.columnName = 'id')>
@JsonSerialize(using = ToStringSerializer.class)
private Long ${model.changeColumnName?uncap_first};
</#if>
<#if (model.columnType = 'BIGINT' && model.columnName != 'id')>
private Long ${model.changeColumnName?uncap_first};
</#if>
<#if (model.columnType = 'INT' || model.columnType = 'INT UNSIGNED' || model.columnType = 'TINYINT')>
private Integer ${model.changeColumnName?uncap_first};
</#if>
<#if (model.columnType = 'DECIMAL')>
private BigDecimal ${model.changeColumnName?uncap_first};
</#if>
<#if (model.columnType = 'VARCHAR' || model.columnType = 'TEXT' || model.columnType = 'CHAR')>
private String ${model.changeColumnName?uncap_first};
</#if>
<#if model.columnType = 'TIMESTAMP' || model.columnType = 'YEAR' || model.columnType = 'DATE' || model.columnType = 'DATETIME' >
@JsonFormat(pattern="yyyy-MM-dd HH:mm:ss", timezone="GMT+8")
private Date ${model.changeColumnName?uncap_first};
</#if>
<#if (model.columnType != 'BIGINT' && model.columnType != 'INT' && model.columnType != 'VARCHAR' && model.columnType != 'DECIMAL' && model.columnType != 'TEXT' && model.columnType != 'CHAR' && model.columnType != 'TIMESTAMP' && model.columnType != 'YEAR' && model.columnType != 'DATE' && model.columnType != 'DATETIME' && model.columnType != 'INT UNSIGNED')>
private MISS ${model.changeColumnName?uncap_first};
</#if>
</#list>
</#if>
}5.9 pom文件模版
<?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>${package_name}</groupId>
<artifactId>${project_name}</artifactId>
<version>1.0-SNAPSHOT</version>
<!-- 繼承Spring boot工程 -->
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.3.9.RELEASE</version>
</parent>
<properties>
<!-- 項(xiàng)目源碼及編譯輸出的編碼 -->
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<!-- 項(xiàng)目編譯JDK版本 -->
<maven.compiler.source>11</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target>
<!-- 依賴包版本管理 -->
<spring.boot.version>2.3.9.RELEASE</spring.boot.version>
<lombok.version>1.18.8</lombok.version>
<mysql.version>5.1.46</mysql.version>
<mybatis-plus.version>3.3.1</mybatis-plus.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>${r"${mybatis-plus.version}"}</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>${r"${mysql.version}"}</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>${r"${lombok.version}"}</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.10</version>
</dependency>
</dependencies>
</project>5.10 application.yml文件模版
server:
port: ${r"${port:8888}"}
spring:
application:
name: ${project_name} 6 測試
運(yùn)行代碼生成器入口類 CodeGenerateUtils
輸出日志如下
D:\app\devs\Java\jdk-11\bin\java.exe "-javaagent:D:\app\devs\JetBrains\IntelliJ IDEA 2018.2.4\lib\idea_rt.jar=60577:D:\app\devs\JetBrains\IntelliJ IDEA 2018.2.4\bin" -Dfile.encoding=UTF-8 -classpath D:\heima\技術(shù)文章\itheima-code\target\classes;D:\app\devs\apache-maven-3.3.9\maven_repository\org\freemarker\freemarker\2.3.23\freemarker-2.3.23.jar;D:\app\devs\apache-maven-3.3.9\maven_repository\mysql\mysql-connector-java\5.1.47\mysql-connector-java-5.1.47.jar;D:\app\devs\apache-maven-3.3.9\maven_repository\org\projectlombok\lombok\1.18.8\lombok-1.18.8.jar;D:\app\devs\apache-maven-3.3.9\maven_repository\org\apache\commons\commons-lang3\3.10\commons-lang3-3.10.jar freemarker.CodeGenerateUtils -------- 正在生成 undo_log 表相關(guān)文件------ 生成實(shí)體類 D:\heima\技術(shù)文章\代碼\itheima-wemedia\src\main\java\com\itheima\wemedia\entity\UndoLog.java 生成Mapper D:\heima\技術(shù)文章\代碼\itheima-wemedia\src\main\java\com\itheima\wemedia\mapper\UndoLogMapper.java 生成Mapper映射文件 D:\heima\技術(shù)文章\代碼\itheima-wemedia\src\main\resources\com\itheima\wemedia\mapper\UndoLogMapper.xml 生成service接口 D:\heima\技術(shù)文章\代碼\itheima-wemedia\src\main\java\com\itheima\wemedia\service\UndoLogService.java 生成service實(shí)現(xiàn)類 D:\heima\技術(shù)文章\代碼\itheima-wemedia\src\main\java\com\itheima\wemedia\service\impl\UndoLogServiceImpl.java 生成Controller層文件 D:\heima\技術(shù)文章\代碼\itheima-wemedia\src\main\java\com\itheima\wemedia\http\controller\UndoLogController.java 生成vo類 D:\heima\技術(shù)文章\代碼\itheima-wemedia\src\main\java\com\itheima\wemedia\http\vo\UndoLogVo.java 生成dto類 D:\heima\技術(shù)文章\代碼\itheima-wemedia\src\main\java\com\itheima\wemedia\http\dto\UndoLogDto.java 生成pom文件 D:\heima\技術(shù)文章\代碼\itheima-wemedia\pom.xml 生成application.yml文件 D:\heima\技術(shù)文章\代碼\itheima-wemedia\src\main\resources\application.yml -------- 正在生成 wm_channel 表相關(guān)文件------ 生成實(shí)體類 D:\heima\技術(shù)文章\代碼\itheima-wemedia\src\main\java\com\itheima\wemedia\entity\WmChannel.java 生成Mapper D:\heima\技術(shù)文章\代碼\itheima-wemedia\src\main\java\com\itheima\wemedia\mapper\WmChannelMapper.java 生成Mapper映射文件 D:\heima\技術(shù)文章\代碼\itheima-wemedia\src\main\resources\com\itheima\wemedia\mapper\WmChannelMapper.xml 生成service接口 D:\heima\技術(shù)文章\代碼\itheima-wemedia\src\main\java\com\itheima\wemedia\service\WmChannelService.java 生成service實(shí)現(xiàn)類 D:\heima\技術(shù)文章\代碼\itheima-wemedia\src\main\java\com\itheima\wemedia\service\impl\WmChannelServiceImpl.java 生成Controller層文件 D:\heima\技術(shù)文章\代碼\itheima-wemedia\src\main\java\com\itheima\wemedia\http\controller\WmChannelController.java 生成vo類 D:\heima\技術(shù)文章\代碼\itheima-wemedia\src\main\java\com\itheima\wemedia\http\vo\WmChannelVo.java 生成dto類 D:\heima\技術(shù)文章\代碼\itheima-wemedia\src\main\java\com\itheima\wemedia\http\dto\WmChannelDto.java 生成pom文件 D:\heima\技術(shù)文章\代碼\itheima-wemedia\pom.xml 生成application.yml文件 D:\heima\技術(shù)文章\代碼\itheima-wemedia\src\main\resources\application.yml -------- 正在生成 wm_fans_statistics 表相關(guān)文件------ 生成實(shí)體類 D:\heima\技術(shù)文章\代碼\itheima-wemedia\src\main\java\com\itheima\wemedia\entity\WmFansStatistics.java 生成Mapper D:\heima\技術(shù)文章\代碼\itheima-wemedia\src\main\java\com\itheima\wemedia\mapper\WmFansStatisticsMapper.java 生成Mapper映射文件 D:\heima\技術(shù)文章\代碼\itheima-wemedia\src\main\resources\com\itheima\wemedia\mapper\WmFansStatisticsMapper.xml 生成service接口 D:\heima\技術(shù)文章\代碼\itheima-wemedia\src\main\java\com\itheima\wemedia\service\WmFansStatisticsService.java 生成service實(shí)現(xiàn)類 D:\heima\技術(shù)文章\代碼\itheima-wemedia\src\main\java\com\itheima\wemedia\service\impl\WmFansStatisticsServiceImpl.java 生成Controller層文件 D:\heima\技術(shù)文章\代碼\itheima-wemedia\src\main\java\com\itheima\wemedia\http\controller\WmFansStatisticsController.java 生成vo類 D:\heima\技術(shù)文章\代碼\itheima-wemedia\src\main\java\com\itheima\wemedia\http\vo\WmFansStatisticsVo.java 生成dto類 D:\heima\技術(shù)文章\代碼\itheima-wemedia\src\main\java\com\itheima\wemedia\http\dto\WmFansStatisticsDto.java 生成pom文件 D:\heima\技術(shù)文章\代碼\itheima-wemedia\pom.xml 生成application.yml文件 D:\heima\技術(shù)文章\代碼\itheima-wemedia\src\main\resources\application.yml -------- 正在生成 wm_material 表相關(guān)文件------ 生成實(shí)體類 D:\heima\技術(shù)文章\代碼\itheima-wemedia\src\main\java\com\itheima\wemedia\entity\WmMaterial.java 生成Mapper D:\heima\技術(shù)文章\代碼\itheima-wemedia\src\main\java\com\itheima\wemedia\mapper\WmMaterialMapper.java 生成Mapper映射文件 D:\heima\技術(shù)文章\代碼\itheima-wemedia\src\main\resources\com\itheima\wemedia\mapper\WmMaterialMapper.xml 生成service接口 D:\heima\技術(shù)文章\代碼\itheima-wemedia\src\main\java\com\itheima\wemedia\service\WmMaterialService.java 生成service實(shí)現(xiàn)類 D:\heima\技術(shù)文章\代碼\itheima-wemedia\src\main\java\com\itheima\wemedia\service\impl\WmMaterialServiceImpl.java 生成Controller層文件 D:\heima\技術(shù)文章\代碼\itheima-wemedia\src\main\java\com\itheima\wemedia\http\controller\WmMaterialController.java 生成vo類 D:\heima\技術(shù)文章\代碼\itheima-wemedia\src\main\java\com\itheima\wemedia\http\vo\WmMaterialVo.java 生成dto類 D:\heima\技術(shù)文章\代碼\itheima-wemedia\src\main\java\com\itheima\wemedia\http\dto\WmMaterialDto.java 生成pom文件 D:\heima\技術(shù)文章\代碼\itheima-wemedia\pom.xml 生成application.yml文件 D:\heima\技術(shù)文章\代碼\itheima-wemedia\src\main\resources\application.yml -------- 正在生成 wm_news 表相關(guān)文件------ 生成實(shí)體類 D:\heima\技術(shù)文章\代碼\itheima-wemedia\src\main\java\com\itheima\wemedia\entity\WmNews.java 生成Mapper D:\heima\技術(shù)文章\代碼\itheima-wemedia\src\main\java\com\itheima\wemedia\mapper\WmNewsMapper.java 生成Mapper映射文件 D:\heima\技術(shù)文章\代碼\itheima-wemedia\src\main\resources\com\itheima\wemedia\mapper\WmNewsMapper.xml 生成service接口 D:\heima\技術(shù)文章\代碼\itheima-wemedia\src\main\java\com\itheima\wemedia\service\WmNewsService.java 生成service實(shí)現(xiàn)類 D:\heima\技術(shù)文章\代碼\itheima-wemedia\src\main\java\com\itheima\wemedia\service\impl\WmNewsServiceImpl.java 生成Controller層文件 D:\heima\技術(shù)文章\代碼\itheima-wemedia\src\main\java\com\itheima\wemedia\http\controller\WmNewsController.java 生成vo類 D:\heima\技術(shù)文章\代碼\itheima-wemedia\src\main\java\com\itheima\wemedia\http\vo\WmNewsVo.java 生成dto類 D:\heima\技術(shù)文章\代碼\itheima-wemedia\src\main\java\com\itheima\wemedia\http\dto\WmNewsDto.java 生成pom文件 D:\heima\技術(shù)文章\代碼\itheima-wemedia\pom.xml 生成application.yml文件 D:\heima\技術(shù)文章\代碼\itheima-wemedia\src\main\resources\application.yml -------- 正在生成 wm_news_material 表相關(guān)文件------ 生成實(shí)體類 D:\heima\技術(shù)文章\代碼\itheima-wemedia\src\main\java\com\itheima\wemedia\entity\WmNewsMaterial.java 生成Mapper D:\heima\技術(shù)文章\代碼\itheima-wemedia\src\main\java\com\itheima\wemedia\mapper\WmNewsMaterialMapper.java 生成Mapper映射文件 D:\heima\技術(shù)文章\代碼\itheima-wemedia\src\main\resources\com\itheima\wemedia\mapper\WmNewsMaterialMapper.xml 生成service接口 D:\heima\技術(shù)文章\代碼\itheima-wemedia\src\main\java\com\itheima\wemedia\service\WmNewsMaterialService.java 生成service實(shí)現(xiàn)類 D:\heima\技術(shù)文章\代碼\itheima-wemedia\src\main\java\com\itheima\wemedia\service\impl\WmNewsMaterialServiceImpl.java 生成Controller層文件 D:\heima\技術(shù)文章\代碼\itheima-wemedia\src\main\java\com\itheima\wemedia\http\controller\WmNewsMaterialController.java 生成vo類 D:\heima\技術(shù)文章\代碼\itheima-wemedia\src\main\java\com\itheima\wemedia\http\vo\WmNewsMaterialVo.java 生成dto類 D:\heima\技術(shù)文章\代碼\itheima-wemedia\src\main\java\com\itheima\wemedia\http\dto\WmNewsMaterialDto.java 生成pom文件 D:\heima\技術(shù)文章\代碼\itheima-wemedia\pom.xml 生成application.yml文件 D:\heima\技術(shù)文章\代碼\itheima-wemedia\src\main\resources\application.yml -------- 正在生成 wm_news_statistics 表相關(guān)文件------ 生成實(shí)體類 D:\heima\技術(shù)文章\代碼\itheima-wemedia\src\main\java\com\itheima\wemedia\entity\WmNewsStatistics.java 生成Mapper D:\heima\技術(shù)文章\代碼\itheima-wemedia\src\main\java\com\itheima\wemedia\mapper\WmNewsStatisticsMapper.java 生成Mapper映射文件 D:\heima\技術(shù)文章\代碼\itheima-wemedia\src\main\resources\com\itheima\wemedia\mapper\WmNewsStatisticsMapper.xml 生成service接口 D:\heima\技術(shù)文章\代碼\itheima-wemedia\src\main\java\com\itheima\wemedia\service\WmNewsStatisticsService.java 生成service實(shí)現(xiàn)類 D:\heima\技術(shù)文章\代碼\itheima-wemedia\src\main\java\com\itheima\wemedia\service\impl\WmNewsStatisticsServiceImpl.java 生成Controller層文件 D:\heima\技術(shù)文章\代碼\itheima-wemedia\src\main\java\com\itheima\wemedia\http\controller\WmNewsStatisticsController.java 生成vo類 D:\heima\技術(shù)文章\代碼\itheima-wemedia\src\main\java\com\itheima\wemedia\http\vo\WmNewsStatisticsVo.java 生成dto類 D:\heima\技術(shù)文章\代碼\itheima-wemedia\src\main\java\com\itheima\wemedia\http\dto\WmNewsStatisticsDto.java 生成pom文件 D:\heima\技術(shù)文章\代碼\itheima-wemedia\pom.xml 生成application.yml文件 D:\heima\技術(shù)文章\代碼\itheima-wemedia\src\main\resources\application.yml -------- 正在生成 wm_sensitive 表相關(guān)文件------ 生成實(shí)體類 D:\heima\技術(shù)文章\代碼\itheima-wemedia\src\main\java\com\itheima\wemedia\entity\WmSensitive.java 生成Mapper D:\heima\技術(shù)文章\代碼\itheima-wemedia\src\main\java\com\itheima\wemedia\mapper\WmSensitiveMapper.java 生成Mapper映射文件 D:\heima\技術(shù)文章\代碼\itheima-wemedia\src\main\resources\com\itheima\wemedia\mapper\WmSensitiveMapper.xml 生成service接口 D:\heima\技術(shù)文章\代碼\itheima-wemedia\src\main\java\com\itheima\wemedia\service\WmSensitiveService.java 生成service實(shí)現(xiàn)類 D:\heima\技術(shù)文章\代碼\itheima-wemedia\src\main\java\com\itheima\wemedia\service\impl\WmSensitiveServiceImpl.java 生成Controller層文件 D:\heima\技術(shù)文章\代碼\itheima-wemedia\src\main\java\com\itheima\wemedia\http\controller\WmSensitiveController.java 生成vo類 D:\heima\技術(shù)文章\代碼\itheima-wemedia\src\main\java\com\itheima\wemedia\http\vo\WmSensitiveVo.java 生成dto類 D:\heima\技術(shù)文章\代碼\itheima-wemedia\src\main\java\com\itheima\wemedia\http\dto\WmSensitiveDto.java 生成pom文件 D:\heima\技術(shù)文章\代碼\itheima-wemedia\pom.xml 生成application.yml文件 D:\heima\技術(shù)文章\代碼\itheima-wemedia\src\main\resources\application.yml -------- 正在生成 wm_user 表相關(guān)文件------ 生成實(shí)體類 D:\heima\技術(shù)文章\代碼\itheima-wemedia\src\main\java\com\itheima\wemedia\entity\WmUser.java 生成Mapper D:\heima\技術(shù)文章\代碼\itheima-wemedia\src\main\java\com\itheima\wemedia\mapper\WmUserMapper.java 生成Mapper映射文件 D:\heima\技術(shù)文章\代碼\itheima-wemedia\src\main\resources\com\itheima\wemedia\mapper\WmUserMapper.xml 生成service接口 D:\heima\技術(shù)文章\代碼\itheima-wemedia\src\main\java\com\itheima\wemedia\service\WmUserService.java 生成service實(shí)現(xiàn)類 D:\heima\技術(shù)文章\代碼\itheima-wemedia\src\main\java\com\itheima\wemedia\service\impl\WmUserServiceImpl.java 生成Controller層文件 D:\heima\技術(shù)文章\代碼\itheima-wemedia\src\main\java\com\itheima\wemedia\http\controller\WmUserController.java 生成vo類 D:\heima\技術(shù)文章\代碼\itheima-wemedia\src\main\java\com\itheima\wemedia\http\vo\WmUserVo.java 生成dto類 D:\heima\技術(shù)文章\代碼\itheima-wemedia\src\main\java\com\itheima\wemedia\http\dto\WmUserDto.java 生成pom文件 D:\heima\技術(shù)文章\代碼\itheima-wemedia\pom.xml 生成application.yml文件 D:\heima\技術(shù)文章\代碼\itheima-wemedia\src\main\resources\application.yml ============ 全部生成完成! ============= Process finished with exit code 0
在idea中點(diǎn)擊 File > open 打開 D:\heima\技術(shù)文章\代碼\itheima-wemedia

