非框架類總綱
友情鏈接:Velocity-后傳
http://www.reibang.com/p/056525422f2e
前言
說(shuō)到Java 開(kāi)發(fā)中模板引擎,常見(jiàn)有三:Thymeleaf 焙矛、Velocity形纺、Freemarker
當(dāng)然市面上有很多文章關(guān)于三者的區(qū)別,個(gè)人認(rèn)為
Thymeleaf :Springboot 官方支持条篷,全棧 html 非常方便,若是前后端分離 vue 就完全不適用
Freemarker:很多老項(xiàng)目用看過(guò)大量使用,不支持多級(jí)編譯(這是硬傷,同時(shí)也是有效的保護(hù)了代碼)凡橱,現(xiàn)在很多開(kāi)源框架主流用它做代碼生成器模板(elAdmin就是一款)
Velocity:類似的jsp語(yǔ)法揽趾,能多級(jí)編譯台汇,但文件名必須為vm,現(xiàn)在很多開(kāi)源框架主流用它做代碼生成器模板(人人fast就 是一款)
文章參考三者區(qū)別:
https://blog.csdn.net/mrleeapple/article/details/89883807
https://blog.csdn.net/qq_41720208/article/details/80891393
https://www.cnblogs.com/ywb-articles/p/10627398.html
1但骨、velocity 簡(jiǎn)介
1励七、velocity 介紹
Velocity是一個(gè)基于Java的模板引擎,可以通過(guò)特定的語(yǔ)法獲取在java對(duì)象的數(shù)據(jù) , 填充到模板中奔缠,從而實(shí)現(xiàn)界面和java代碼的分離 !
2掠抬、為什么學(xué)習(xí)velocity(應(yīng)用場(chǎng)景)
- Web應(yīng)用程序 : 作為為應(yīng)用程序的視圖, 展示數(shù)據(jù)。
- 源代碼生成 : Velocity可用于基于模板生成Java源代碼
- 自動(dòng)電子郵件 : 網(wǎng)站注冊(cè) , 認(rèn)證等的電子郵件模板
- 網(wǎng)頁(yè)靜態(tài)化 : 基于velocity模板 , 生成靜態(tài)網(wǎng)頁(yè)
3校哎、velocity 組成原理
Velocity主要分為app两波、context、runtime和一些輔助util幾個(gè)部分闷哆。
- app模塊 : 主要封裝了一些接口 , 暴露給使用者使用腰奋。主要有兩個(gè)類,分別是Velocity(單例)和VelocityEngine抱怔。
- Context模塊 : 主要封裝了模板渲染需要的變量
- Runtime模塊 : 整個(gè)Velocity的核心模塊劣坊,Runtime模塊會(huì)將加載的模板解析成語(yǔ)法樹,Velocity調(diào)用mergeTemplate方法時(shí)會(huì)渲染整棵樹屈留,并輸出最終的渲染結(jié)果局冰。
- RuntimeInstance類為整個(gè)Velocity渲染提供了一個(gè)單例模式测蘑,拿到了這個(gè)實(shí)例就可以完成渲染過(guò)程了。
2康二、velocity引擎快速入門
1碳胳、創(chuàng)建工程、引入坐標(biāo)沫勿、插件配置
<dependencies>
<dependency>
<groupId>org.apache.velocity</groupId>
<artifactId>velocity-engine-core</artifactId>
<version>2.2</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
</dependencies>
<!--插件配置-->
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
<encoding>utf-8</encoding>
</configuration>
</plugin>
</plugins>
</build>
2挨约、編寫模板
在項(xiàng)目resources
目錄下創(chuàng)建模板文件
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
hello , ${name} !
</body>
</html>
3、加載模板产雹、合并輸出結(jié)果
@Test
public void test1() throws IOException {
//設(shè)置velocity資源加載器
Properties prop = new Properties ( );
prop.put ("file.resource.loader.class", "org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader");
Velocity.init (prop);
//創(chuàng)建Velocity容器
VelocityContext context = new VelocityContext ( );
context.put ("name", "阿K");
//加載模板
Template tpl = Velocity.getTemplate ("vms/01-quickstark.vm", "UTF-8");
FileWriter fw = new FileWriter ("D:\\work\\demo1.html");
//合并數(shù)據(jù)到模板
tpl.merge (context, fw);
//釋放資源
fw.close ( );
}
4诫惭、運(yùn)行原理分析
- Velocity解決了如何在后臺(tái)程序和網(wǎng)頁(yè)之間傳遞數(shù)據(jù)的問(wèn)題,后臺(tái)代碼和視圖之間相互獨(dú)立洽故,一方的修改不影響另一方 .
- 他們之間是通過(guò)環(huán)境變量(Context)來(lái)實(shí)現(xiàn)的贝攒,網(wǎng)頁(yè)制作一方和后臺(tái)程序一方相互約定好對(duì)所傳遞變量的命名約定,比如上個(gè)程序例子中的site, name變量时甚,它們?cè)诰W(wǎng)頁(yè)上就是$name ,$site 隘弊。
-
只要雙方約定好了變量名字,那么雙方就可以獨(dú)立工作了荒适。無(wú)論頁(yè)面如何變化梨熙,只要變量名不變,那么后臺(tái)程序就無(wú)需改動(dòng)刀诬,前臺(tái)網(wǎng)頁(yè)也可以任意由網(wǎng)頁(yè)制作人員修改咽扇。這就是Velocity的工作原理。
3陕壹、vtl 模板語(yǔ)法
1质欲、vtl介紹
Velocity Template Language (VTL) , 是Velocity 中提供的一種模版語(yǔ)言 , 旨在提供最簡(jiǎn)單和最干凈的方法來(lái)將動(dòng)態(tài)內(nèi)容合并到網(wǎng)頁(yè)中。簡(jiǎn)單來(lái)說(shuō)VTL可以將程序中的動(dòng)態(tài)數(shù)展示到網(wǎng)頁(yè)中
VTL的語(yǔ)句分為4大類:注釋 , 非解析內(nèi)容 ** , 引用和指令**糠馆。
2嘶伟、注釋
2-1. 行注釋
## 行注釋內(nèi)容
2-2. 塊注釋
#*
塊注釋內(nèi)容1
塊注釋內(nèi)容2
*#
2-3. 文檔注釋
#**
文檔注釋內(nèi)容1
文檔注釋內(nèi)容2
*#
2-4. 案例
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
## 我是行注釋
#*
* 我是塊注釋
* 呵呵呵
* *#
#**
* 我是文檔注釋
*
* *#
hello , ${name} !
</body>
</html>
3、非解析內(nèi)容
所謂非解析內(nèi)容也就是不會(huì)被引擎解析的內(nèi)容又碌。
3-1. 語(yǔ)法
#[[
非解析內(nèi)容1
非解析內(nèi)容2
]]#
3-2. 示例
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
hello , ${name} !
<h1>非解析內(nèi)容</h1>
#[[
直接輸出的內(nèi)容1
直接輸出的內(nèi)容2
${name}
]]#
</body>
</html>
4九昧、變量語(yǔ)法
引用語(yǔ)句就是對(duì)引擎上下文對(duì)象中的屬性進(jìn)行操作。語(yǔ)法方面分為常規(guī)語(yǔ)法(`$屬性`)和正規(guī)語(yǔ)法(${屬性})毕匀。
4-1. 語(yǔ)法
$變量名, 若上下文中沒(méi)有對(duì)應(yīng)的變量铸鹰,則輸出字符串"$變量名"
${變量名},若上下文中沒(méi)有對(duì)應(yīng)的變量,則輸出字符串"${變量名}"
$!變量名, 若上下文中沒(méi)有對(duì)應(yīng)的變量皂岔,則輸出空字符串""
$!{變量名}, 若上下文中沒(méi)有對(duì)應(yīng)的變量蹋笼,則輸出空字符串""
4-2. 示例
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h1>引用變量</h1>
常規(guī)語(yǔ)法 : $name
正規(guī)語(yǔ)法 : ${name}
## 如果獲取的變量不存在, 表達(dá)式會(huì)原樣展示 , 如果不想展示 , 可以使用 $!變量名
## 以下寫法的含義代表么如果有變量, 那么獲取變量值展示, 沒(méi)有變量展示""
常規(guī)語(yǔ)法 : $!name
正規(guī)語(yǔ)法 : $!{name}
</body>
</html>
5、屬性語(yǔ)法
5-1. 語(yǔ)法
$變量名.屬性, 若上下文中沒(méi)有對(duì)應(yīng)的變量,則輸出字符串"$變量名.屬性"
${變量名.屬性} 若上下文中沒(méi)有對(duì)應(yīng)的變量姓建,則輸出字符串"${變量名.屬性}"
$!變量名.屬性 若上下文中沒(méi)有對(duì)應(yīng)的變量诞仓,則輸出字符串""
$!{變量名.屬性} 若上下文中沒(méi)有對(duì)應(yīng)的變量缤苫,則輸出字符串""
5-2. 示例
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h1>引用屬性</h1>
常規(guī)語(yǔ)法 : $user.username --- $user.password
正規(guī)語(yǔ)法 : ${user.username} --- ${user.password}
正規(guī)語(yǔ)法 : ${user.email} --- ${user.email}
正規(guī)語(yǔ)法 : $!{user.email} --- $!{user.email}
</body>
</html>
6速兔、方法語(yǔ)法
方法引用實(shí)際就是指方法調(diào)用操作,關(guān)注點(diǎn)返回值和參數(shù) , 方法的返回值將輸出到最終結(jié)果中
6-1. 語(yǔ)法
$變量名.方法([入?yún)?[, 入?yún)?]*]?), 常規(guī)寫法
${變量名.方法([入?yún)?[, 入?yún)?]*]?)}, 正規(guī)寫法
$!變量名.方法([入?yún)?[, 入?yún)?]*]?), 常規(guī)寫法
$!{變量名.方法([入?yún)?[, 入?yún)?]*]?)}, 正規(guī)寫法
6-2. 示例
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h1>引用屬性</h1>
$str.split(" ")
${str.split(" ")}
$time.getTime()
${time.getTime()}
</body>
</html>
7活玲、常用指令
流程控制
#set
#if/#elseif/#else
#foreach
#break
#stop
引入外部的模板
#parse
#include
#evaluate
#define
宏指令
7.1 #set
7-1-0. 作用:在頁(yè)面中聲明定義變量
7-1-1. 語(yǔ)法: #set($變量 = 值)
7-1-2. 示例
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h1>set指令</h1>
#set($str = "hello world")
#set($int = 1)
#set($arr = [1,2])
#set($boolean = true)
#set($map = {"key1":"value1", "key2":"value2"})
## 在字符串中也可以引用之前定義過(guò)的變量
#set($str2 = "$str , how are you !")
#set($str3 = '$str , how are you !')
<h1>獲取set指令定義的變量</h1>
${str}
${int}
${arr}
${boolean}
${map.key1}--${map.key2}
${str2}
${str3}
</body>
</html>
7.2 #if/#elseif/#else
7-2-0. 作用:進(jìn)行邏輯判斷
7-2-1. 語(yǔ)法:
#if(判斷條件)
.........
#elseif(判斷條件)
.........
#else
.........
#end
7-2-2. 示例
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h1>if/elseif/else指令</h1>
#set($language="PHP")
#if($language.equals("JAVA"))
java開(kāi)發(fā)工程師
#elseif($language.equals("PHP"))
php開(kāi)發(fā)工程師
#else
開(kāi)發(fā)工程師
#end
</body>
</html>
7.3 #foreach
7-3-0. 作用:遍歷循環(huán)數(shù)組或者集合
7-3-1. 語(yǔ)法:
#foreach($item in $items)
..........
[#break]
#end
- $items : 需要遍歷的對(duì)象或者集合
- 如果items的類型為map集合, 那么遍歷的是map的value
- $item : 變量名稱, 代表遍歷的每一項(xiàng)
- #break : 退出循環(huán)
- 內(nèi)置屬性 :
- $foreach.index : 獲取遍歷的索引 , 從0開(kāi)始
- $foreach.count : 獲取遍歷的次數(shù) , 從1開(kāi)始
7-3-2. 示例
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h1>遍歷數(shù)組</h1>
#foreach($str in $hobbies)
${foreach.index} -- ${str} <br>
#end
<h1>變量對(duì)象集合</h1>
<table border="1px" align="center">
<tr>
<td>編號(hào)</td>
<td>用戶名</td>
<td>密碼</td>
<td>郵箱</td>
<td>年齡</td>
<td>操作</td>
</tr>
#foreach($user in $users)
<tr>
<td>${foreach.index}</td>
<td>${user.username}</td>
<td>${user.password}</td>
<td>${user.email}</td>
<td>${user.age}</td>
<td>
<a href="">編輯</a>
<a href="">刪除</a>
</td>
</tr>
#end
</table>
<h1>遍歷map集合</h1>
<h2>遍歷值</h2>
#foreach($value in $map)
$value
#end
<h2>遍歷鍵值對(duì)</h2>
#foreach($entry in $map.entrySet())
$entry.key -- $entry.value
#end
</body>
</html>
7.4 #include
7-4-0. 作用:引入外部資源 , 引入的資源不會(huì)被引擎所解析
7-4-1. 語(yǔ)法:#include(resource)
- resource可以為單引號(hào)或雙引號(hào)的字符串涣狗,也可以為$變量,內(nèi)容為外部資源路徑舒憾。
-
注意 : 路徑如果為相對(duì)路徑镀钓,則以引擎配置的文件加載器加載路徑作為參考(也就是 resource 的路徑)
7-4-2. 示例
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
#include("vms/01-quickstark.vm")
</body>
</html>
7.5 #parse
7-5-0. 作用:引入外部資源 , 引入的資源將被引擎所解析
7-5-1. 語(yǔ)法:#parse(resource)
- resource可以為單引號(hào)或雙引號(hào)的字符串,也可以為$變量镀迂,內(nèi)容為外部資源路徑丁溅。
- 注意 : 路徑如果為相對(duì)路徑,則以引擎配置的文件加載器加載路徑作為參考系
7-5-2. 示例
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
#parse("vms/01-quickstark.vm")
</body>
</html>
7.6 #define
7-6-0. 作用:定義重用模塊(不帶參數(shù))
7-6-1. 語(yǔ)法:
#define($模塊名稱)
模塊內(nèi)容
#end
7-6-2. 示例
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h1>定義模塊</h1>
#define($table)
<table border="1px" align="center">
<tr>
<td>編號(hào)</td>
<td>用戶名</td>
<td>密碼</td>
<td>年齡</td>
<td>操作</td>
</tr>
<tr>
<td>0</td>
<td>zhangsan</td>
<td>123456</td>
<td>18</td>
<td>
<a href="">編輯</a>
<a href="">刪除</a>
</td>
</tr>
<tr>
<td>1</td>
<td>lisi</td>
<td>123456</td>
<td>18</td>
<td>
<a href="">編輯</a>
<a href="">刪除</a>
</td>
</tr>
<tr>
<td>2</td>
<td>wangwu</td>
<td>123456</td>
<td>18</td>
<td>
<a href="">編輯</a>
<a href="">刪除</a>
</td>
</tr>
</table>
#end
<h1>使用模塊</h1>
$table
$table
$table
</body>
</html>
7.7 #evaluate
7-7-0. 作用:動(dòng)態(tài)計(jì)算 , 動(dòng)態(tài)計(jì)算可以讓我們?cè)谧址惺褂米兞?br>
7-7-1. 語(yǔ)法:#evalute("計(jì)算語(yǔ)句")
7-7-2. 示例
后端:這樣直接傳過(guò)去的 $code探遵,會(huì)被直接當(dāng)做字符串解析窟赏,需要使用 #evaluate才不會(huì)被直接輸出
//創(chuàng)建Velocity容器
VelocityContext context = new VelocityContext ( );
context.put ("code", "#if($language.equals(\"JAVA\"))\n" +
" java開(kāi)發(fā)工程師\n" +
"#elseif($language.equals(\"PHP\"))\n" +
" php開(kāi)發(fā)工程師\n" +
"#else\n" +
" 開(kāi)發(fā)工程師\n" +
"#end");
vms:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h1>動(dòng)態(tài)計(jì)算</h1>
#set($language= "java")
#evaluate($code)
</body>
</html>
7.8 宏指令
7-8-0. 作用:定義重用模塊(可帶參數(shù))
7-8-1. 語(yǔ)法
7.8-1-1、定義語(yǔ)法:
#macro(宏名 [$arg]?)
.....
#end
7.8-1-1箱季、調(diào)用語(yǔ)法:
#宏名([$arg]?)
7-8-2. 示例
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h1>定義宏</h1>
#macro(table $list)
<table border="1px">
<tr>
<td>編號(hào)</td>
<td>用戶名</td>
<td>密碼</td>
<td>郵箱</td>
<td>年齡</td>
<td>操作</td>
</tr>
#foreach($item in $list)
<tr>
<td>${foreach.count}</td>
<td>${item.username}</td>
<td>${item.password}</td>
<td>${item.email}</td>
<td>${item.age}</td>
<td>
<a href="">編輯</a>
<a href="">刪除</a>
</td>
</tr>
#end
</table>
#end
<h1>調(diào)用宏</h1>
#table($users)
</body>
</html>
4涯穷、.綜合案例
1、代碼生成介紹
在實(shí)際項(xiàng)目開(kāi)發(fā)過(guò)程中, 編寫基礎(chǔ)的CRUD操作代碼, 往往會(huì)花費(fèi)我們大量的時(shí)間 , 而且這些CRUD代碼的基礎(chǔ)結(jié)構(gòu)基本上是固定的 , 如果能有一個(gè)代碼生成器 , 能夠幫助我們把這些代碼生成出來(lái) , 我們就可以節(jié)省出大量的時(shí)間關(guān)注核心業(yè)務(wù)代碼的開(kāi)發(fā), 大大提高了我們的開(kāi)發(fā)效率 !
需求 : 使用velocity實(shí)現(xiàn)一個(gè)簡(jiǎn)單的代碼生成器 , 生成項(xiàng)目開(kāi)發(fā)過(guò)程中的基礎(chǔ)CRUD代碼
2藏雏、代碼生成流程分析
- 創(chuàng)建項(xiàng)目
- 導(dǎo)入依賴
- 編寫模板
- 生成代碼
3拷况、編寫模板
一般我們的項(xiàng)目開(kāi)發(fā)將項(xiàng)目分為三層 , 我們的代碼生成器就基于傳統(tǒng)的三層架構(gòu)生成代碼 , 所以我們需要為每一層的每一個(gè)類創(chuàng)建模板 , 所以需要有如下模板 :
- Controller.java.vm : 控制層模板
- Service.java.vm : 業(yè)務(wù)層接口模板
- ServiceImpl.java.vm : 業(yè)務(wù)層實(shí)現(xiàn)模板
- Dao.java.vm : 數(shù)據(jù)服務(wù)層模板(數(shù)據(jù)訪問(wèn)層基于通用Mpper實(shí)現(xiàn))
Controller.java.vm:
package ${package}.controller;
import ${package}.pojo.${className};
import ${package}.service.${className}Service;
import ${package}.utils.Result;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
import java.util.Map;
@RestController
@RequestMapping("/${classname}")
public class ${className}Controller {
@Autowired
private ${className}Service ${classname}Service ;
/**
* 查詢列表
* @return
*/
@RequestMapping("/list")
public Result list(){
List<${className}> ${classname}s = null;
try {
${classname}s = ${classname}Service.list();
return Result.ok(${classname}s);
} catch (Exception e) {
e.printStackTrace();
return Result.error("查詢數(shù)據(jù)異常");
}
}
/**
* 保存
* @param ${classname}
* @return
*/
@RequestMapping("/save")
public Result save(@RequestBody ${className} ${classname}){
try {
${classname}Service.save(${classname});
return Result.ok("新增數(shù)據(jù)成功");
} catch (Exception e) {
e.printStackTrace();
return Result.error("新增數(shù)據(jù)異常");
}
}
/**
* 更新
* @param ${classname}
* @return
*/
@RequestMapping("/update")
public Result update(@RequestBody ${className} ${classname}){
try {
${classname}Service.update(${classname});
return Result.ok("修改數(shù)據(jù)成功");
} catch (Exception e) {
e.printStackTrace();
return Result.error("修改數(shù)據(jù)異常");
}
}
/**
* 刪除
* @param ids
* @return
*/
@RequestMapping("/delete")
public Result delete(@RequestBody Integer[] ids){
try {
${classname}Service.delete(ids);
return Result.ok("刪除數(shù)據(jù)成功");
} catch (Exception e) {
e.printStackTrace();
return Result.error("刪除數(shù)據(jù)異常");
}
}
}
Service.java.vm
package ${package}.service;
import com.kk.pojo.${className};
import java.util.List;
import java.util.Map;
public interface ${className}Service {
/**
* 查詢數(shù)據(jù)列表
* @return
*/
List<${className}> list();
/**
* 保存數(shù)據(jù)
* @param ${classname}
*/
void save(${className} ${classname});
/**
* 更新數(shù)據(jù)
* @param ${classname}
*/
void update(${className} ${classname});
/**
* 刪除數(shù)據(jù)
* @param ids
*/
void delete(Integer[] ids);
}
ServiceImpl.java.vm
package ${package}.service.impl;
import ${package}.dao.${className}Dao;
import ${package}.pojo.${className};
import ${package}.service.${className}Service;
import org.springframework.beans.factory.annotation.Autowired;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Stream;
public class ${className}ServiceImpl implements ${className}Service {
@Autowired
private ${className}Dao ${classname}Dao ;
public List<${className}> list() {
return ${classname}Dao.selectAll();
}
public void save(${className} ${classname}) {
${classname}Dao.insert(${classname});
}
public void update(${className} ${classname}) {
${classname}Dao.updateByPrimaryKey(${classname});
}
public void delete(Integer[] ids) {
Stream.of(ids).forEach(${classname}Dao::deleteByPrimaryKey);
}
}
Dao.java.vm
package ${package}.dao;
import com.kk.pojo.${className};
import tk.mybatis.mapper.common.Mapper;
public interface ${className}Dao extends Mapper<${className}> {
}
4、實(shí)現(xiàn)代碼生成邏輯
package com.kk.utils;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.velocity.Template;
import org.apache.velocity.VelocityContext;
import org.apache.velocity.app.Velocity;
import java.io.File;
import java.io.IOException;
import java.io.StringWriter;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;
/**
* 代碼生成器 工具類
*/
public class GenUtils {
private static String currentTableName;
public static List<String> getTemplates() {
List<String> templates = new ArrayList<String>();
templates.add("vms/Controller.java.vm");
templates.add("vms/Service.java.vm");
templates.add("vms/ServiceImpl.java.vm");
templates.add("vms/Dao.java.vm");
return templates;
}
/**
* 生成代碼
*/
public static void generatorCode(Map<String, Object> data, List<String> templates, ZipOutputStream zip) {
//設(shè)置velocity資源加載器
Properties prop = new Properties();
prop.put("file.resource.loader.class", "org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader");
Velocity.init(prop);
//封裝模板數(shù)據(jù)
VelocityContext context = new VelocityContext(data);
//獲取模板列表
for (String template : templates) {
//渲染模板
StringWriter sw = new StringWriter();
Template tpl = Velocity.getTemplate(template, "UTF-8");
tpl.merge(context, sw);
try {
//添加到zip
zip.putNextEntry(new ZipEntry(getFileName(template, data.get("className").toString(), data.get("package").toString())));
IOUtils.write(sw.toString(), zip, "UTF-8");
IOUtils.closeQuietly(sw);
} catch (IOException e) {
e.printStackTrace();
}
}
}
/**
* 獲取文件名 , 每個(gè)文件所在包都不一樣, 在磁盤上的文件名幾路徑也各不相同
*/
public static String getFileName(String template, String className,String packageName) {
String packagePath = "main" + File.separator + "java" + File.separator;
if (StringUtils.isNotBlank(packageName)) {
packagePath += packageName.replace(".", File.separator) + File.separator;
}
if (template.contains("Dao.java.vm")) {
return packagePath + "dao" + File.separator + className + "Dao.java";
}
if (template.contains("Service.java.vm")) {
return packagePath + "service" + File.separator + className + "Service.java";
}
if (template.contains("ServiceImpl.java.vm")) {
return packagePath + "service" + File.separator + "impl" + File.separator + className + "ServiceImpl.java";
}
if (template.contains("Controller.java.vm")) {
return packagePath + "controller" + File.separator + className + "Controller.java";
}
return null;
}
}
運(yùn)行測(cè)試
public class GeneratorCodeTest {
public static void main(String[] args) throws IOException {
Map<String,Object> data = new HashMap<String,Object>();
data.put("className","Product");
data.put("classname","product");
data.put("package","com.itheima");
File file = new File("D:\\Users\\Desktop\\code.zip");
FileOutputStream outputStream = new FileOutputStream(file);
ZipOutputStream zip = new ZipOutputStream(outputStream);
GenUtils.generatorCode(data,GenUtils.getTemplates(),zip);
zip.close();
}
}