C-Velocity(模板引擎) --- A版(代碼生成器) --- 2021年5月30日 23:25:32

非框架類總綱

http://www.reibang.com/p/d0167f082cbf

友情鏈接: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代碼的分離 !


image.png
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 組成原理
image.png

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)沫勿、插件配置
image.png
 <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)建模板文件

image.png

<!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的工作原理。


    image.png

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 的路徑)


    image.png

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藏雏、代碼生成流程分析
  1. 創(chuàng)建項(xiàng)目
  2. 導(dǎo)入依賴
  3. 編寫模板
  4. 生成代碼
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();
    }
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末掘殴,一起剝皮案震驚了整個(gè)濱河市赚瘦,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌奏寨,老刑警劉巖起意,帶你破解...
    沈念sama閱讀 211,194評(píng)論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異服爷,居然都是意外死亡杜恰,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,058評(píng)論 2 385
  • 文/潘曉璐 我一進(jìn)店門仍源,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)心褐,“玉大人,你說(shuō)我怎么就攤上這事笼踩《旱” “怎么了?”我有些...
    開(kāi)封第一講書人閱讀 156,780評(píng)論 0 346
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)掘而。 經(jīng)常有香客問(wèn)我挟冠,道長(zhǎng),這世上最難降的妖魔是什么袍睡? 我笑而不...
    開(kāi)封第一講書人閱讀 56,388評(píng)論 1 283
  • 正文 為了忘掉前任知染,我火速辦了婚禮,結(jié)果婚禮上斑胜,老公的妹妹穿的比我還像新娘控淡。我一直安慰自己,他們只是感情好止潘,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,430評(píng)論 5 384
  • 文/花漫 我一把揭開(kāi)白布掺炭。 她就那樣靜靜地躺著,像睡著了一般凭戴。 火紅的嫁衣襯著肌膚如雪涧狮。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書人閱讀 49,764評(píng)論 1 290
  • 那天么夫,我揣著相機(jī)與錄音者冤,去河邊找鬼。 笑死魏割,一個(gè)胖子當(dāng)著我的面吹牛譬嚣,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播钞它,決...
    沈念sama閱讀 38,907評(píng)論 3 406
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼拜银,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了遭垛?” 一聲冷哼從身側(cè)響起尼桶,我...
    開(kāi)封第一講書人閱讀 37,679評(píng)論 0 266
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎锯仪,沒(méi)想到半個(gè)月后泵督,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,122評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡庶喜,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,459評(píng)論 2 325
  • 正文 我和宋清朗相戀三年小腊,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片久窟。...
    茶點(diǎn)故事閱讀 38,605評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡秩冈,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出斥扛,到底是詐尸還是另有隱情入问,我是刑警寧澤,帶...
    沈念sama閱讀 34,270評(píng)論 4 329
  • 正文 年R本政府宣布,位于F島的核電站芬失,受9級(jí)特大地震影響楣黍,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜棱烂,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,867評(píng)論 3 312
  • 文/蒙蒙 一租漂、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧垢啼,春花似錦窜锯、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書人閱讀 30,734評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)吞瞪。三九已至馁启,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間芍秆,已是汗流浹背惯疙。 一陣腳步聲響...
    開(kāi)封第一講書人閱讀 31,961評(píng)論 1 265
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留妖啥,地道東北人霉颠。 一個(gè)月前我還...
    沈念sama閱讀 46,297評(píng)論 2 360
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像荆虱,于是被迫代替她去往敵國(guó)和親蒿偎。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,472評(píng)論 2 348

推薦閱讀更多精彩內(nèi)容