java 框架-模板引擎FreeMarker

https://www.cnblogs.com/itdragon/p/7750903.htmlhtml

FreeMarker是一個很值得去學習的模版引擎。它是基於模板文件生成其餘文本的通用工具。本章內容經過如何使用FreeMarker生成Html web 頁面 和 代碼自動生成工具來快速瞭解FreeMarker。java

1 簡介

FreeMarker是一款用java語言編寫的模版引擎,它雖然不是web應用框架,但它很合適做爲web應用框架的一個組件。git

特色:程序員

1. 輕量級模版引擎,不須要Servlet環境就能夠很輕鬆的嵌入到應用程序中web

2. 能生成各類文本,如html,xml,java,等spring

3. 入門簡單,它是用java編寫的,不少語法和java類似apache

工做原理:(借用網上的圖片)mvc

2 FreeMarker 程序

這裏經過模擬簡單的代碼自動生產工具來感覺第一個FreeMarker程序。app

項目目錄結構框架

項目建立流程

第一步:建立一個maven項目導入 FreeMarker jar 包

第二步:建立目錄templates,並建立一個 FreeMarker模版文件 hello.ftl

第三步:建立一個運行FreeMarker模版引擎的 FreeMarkerDemo.java 文件

第四步:運行main方法後刷新項目

pom.xml 文件 ,maven 項目核心文件,管理 jar 包。

複製代碼
1 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 2     xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
 3     <modelVersion>4.0.0</modelVersion>
 4     <groupId>com.freemark</groupId>
 5     <artifactId>freemarkerStudy</artifactId>
 6     <version>0.0.1-SNAPSHOT</version>
 7     <packaging>war</packaging>
 8 
 9     <dependencies>
10         <dependency>
11             <groupId>org.freemarker</groupId>
12             <artifactId>freemarker</artifactId>
13             <version>2.3.20</version>
14         </dependency>
15     </dependencies>
16     
17 </project>
複製代碼

hello.ftl  FreeMarker基本語法: ${xxx} xxx 至關於佔位符,java後臺給xxx賦值後,再經過${}輸出

複製代碼
1 package ${classPath};
2 
3 public class ${className} {
4     
5     public static void main(String[] args) {
6         System.out.println("${helloWorld}");
7     }
8 
9 }
複製代碼

FreeMarkerDemo.java 核心方法,使用 FreeMarker 模版引擎。

複製代碼
1 package com.freemark.hello;
 2 
 3 import java.io.BufferedWriter;
 4 import java.io.File;
 5 import java.io.FileOutputStream;
 6 import java.io.OutputStreamWriter;
 7 import java.io.Writer;
 8 import java.util.HashMap;
 9 import java.util.Map;
10 
11 import freemarker.template.Configuration;
12 import freemarker.template.Template;
13 
14 /**
15  * 最多見的問題: 
16  *     java.io.FileNotFoundException: xxx does not exist. 解決方法:要有耐心
17  *     FreeMarker jar 最新的版本(2.3.23)提示 Configuration 方法被棄用
18  * 代碼自動生產基本原理:
19  *     數據填充 freeMarker 佔位符
20  */
21 public class FreemarkerDemo {
22     
23     private static final String TEMPLATE_PATH = "src/main/java/com/freemark/hello/templates";
24     private static final String CLASS_PATH = "src/main/java/com/freemark/hello";
25     
26     public static void main(String[] args) {
27         // step1 建立freeMarker配置實例
28         Configuration configuration = new Configuration();
29         Writer out = null;
30         try {
31             // step2 獲取模版路徑
32             configuration.setDirectoryForTemplateLoading(new File(TEMPLATE_PATH));
33             // step3 建立數據模型
34             Map<String, Object> dataMap = new HashMap<String, Object>();
35             dataMap.put("classPath", "com.freemark.hello");
36             dataMap.put("className", "AutoCodeDemo");
37             dataMap.put("helloWorld", "經過簡單的 <代碼自動生產程序> 演示 FreeMarker的HelloWorld!");
38             // step4 加載模版文件
39             Template template = configuration.getTemplate("hello.ftl");
40             // step5 生成數據
41             File docFile = new File(CLASS_PATH + "\\" + "AutoCodeDemo.java");
42             out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(docFile)));
43             // step6 輸出文件
44             template.process(dataMap, out);
45             System.out.println("^^^^^^^^^^^^^^^^^^^^^^^^AutoCodeDemo.java 文件建立成功 !");
46         } catch (Exception e) {
47             e.printStackTrace();
48         } finally {
49             try {
50                 if (null != out) {
51                     out.flush();
52                 }
53             } catch (Exception e2) {
54                 e2.printStackTrace();
55             }
56         }
57     }
58 
59 }
複製代碼

運行程序後刷新項目,會發現多了一個AutoCodeDemo.java類。不單單是java類,xml也是能夠。筆者就是經過FreeMarker作了一個簡易的工具類,公司的一個標準管理頁面及其增刪改查等功能,以及相關的配置文件(十三個文件),一個回車就所有自動生成(偷懶ing)。

3 FreeMarker 語法

語法和java很相似,其中宏的概念可能比較陌生,先上代碼

stringFreeMarker.ftl  FreeMarker主要核心知識點

複製代碼
字符串輸出:
${"Hello ${name} !"} / ${"Hello " + name + " !"}
<#assign cname=r"特殊字符完成輸出(http:\www.baidu.com)">
${cname}

字符串截取 : 
經過下標直接獲取下標對應的字母: ${name[2]}
起點下標..結尾下標截取字符串:${name[0..5]}

算數運算:
<#-- 支持"+"、"-"、"*"、"/"、"%"運算符 -->
<#assign number1 = 10>
<#assign number2 = 5>
"+" : ${number1 + number2}
"-" : ${number1 - number2}
"*" : ${number1 * number2}
"/" : ${number1 / number2}
"%" : ${number1 % number2}

比較運算符:
<#if number1 + number2 gte 12 || number1 - number2 lt 6>
"*" : ${number1 * number2}
<#else>
"/" : ${number1 / number2}
</#if>

內建函數:
<#assign data = "abcd1234">
第一個字母大寫:${data?cap_first}
全部字母小寫:${data?lower_case}
全部字母大寫:${data?upper_case}
<#assign floatData = 12.34>
數值取整數:${floatData?int}
獲取集合的長度:${users?size}
時間格式化:${dateTime?string("yyyy-MM-dd")}

空判斷和對象集合:
<#if users??>
<#list users as user >
${user.id} - ${user.name}
</#list>
<#else>
${user!"變量爲空則給一個默認值"}
</#if>

Map集合:
<#assign mapData={"name":"程序員", "salary":15000}>
直接經過Key獲取 Value值:${mapData["name"]}
經過Key遍歷Map:
<#list mapData?keys as key>
Key: ${key} - Value: ${mapData[key]}
</#list>
經過Value遍歷Map:
<#list mapData?values as value>
Value: ${value}
</#list>

List集合:
<#assign listData=["ITDragon", "blog", "is", "cool"]>
<#list listData as value>${value} </#list>

include指令:
引入其餘文件:<#include "otherFreeMarker.ftl" />

macro宏指令:
<#macro mo>
定義無參數的宏macro--${name}
</#macro>
使用宏macro: <@mo />
<#macro moArgs a b c>
定義帶參數的宏macro-- ${a+b+c}
</#macro>
使用帶參數的宏macro: <@moArgs a=1 b=2 c=3 />

命名空間:
<#import "otherFreeMarker.ftl" as otherFtl>
${otherFtl.otherName}
<@otherFtl.addMethod a=10 b=20 />
<#assign otherName="修改otherFreeMarker.ftl中的otherName變量值"/>
${otherFtl.otherName}
<#assign otherName="修改otherFreeMarker.ftl中的otherName變量值" in otherFtl />
${otherFtl.otherName}
複製代碼

otherFreeMarker.ftl 爲了測試命名空間 和 include 指令的FreeMarker文件

其餘FreeMarker文件
<#macro addMethod a b >
result : ${a + b}
</#macro>
<#assign otherName="另一個FreeMarker的變量">

FreeMarkerDemo.java 核心方法

複製代碼
1 package com.freemark.demo;
 2 
 3 import java.util.List;
 4 import java.io.BufferedWriter;
 5 import java.io.File;
 6 import java.io.FileOutputStream;
 7 import java.io.OutputStreamWriter;
 8 import java.io.Writer;
 9 import java.util.Date;
10 import java.util.ArrayList;
11 import java.util.HashMap;
12 import java.util.Map;
13 
14 import freemarker.template.Configuration;
15 import freemarker.template.Template;
16 
17 public class FreeMarkerDemo {
18     
19     private static final String TEMPLATE_PATH = "src/main/java/com/freemark/demo/templates";
20     
21     public static void main(String[] args) {
22         // step1 建立freeMarker配置實例
23         Configuration configuration = new Configuration();
24         Writer out = null;
25         try {
26             // step2 獲取模版路徑
27             configuration.setDirectoryForTemplateLoading(new File(TEMPLATE_PATH));
28             // step3 建立數據模型
29             Map<String, Object> dataMap = new HashMap<String, Object>();
30             dataMap.put("name", "itdragon博客");
31             dataMap.put("dateTime", new Date());
32             
33             List<User> users = new ArrayList<User>();
34             users.add(new User(1, "ITDragon 博客"));
35             users.add(new User(2, "歡迎"));
36             users.add(new User(3, "You!"));
37             dataMap.put("users", users);
38             // step4 加載模版文件
39             Template template = configuration.getTemplate("stringFreeMarker.ftl");
40             // step5 生成數據
41             out = new OutputStreamWriter(System.out);
42             // step6 輸出文件
43             template.process(dataMap, out);
44         } catch (Exception e) {
45             e.printStackTrace();
46         } finally {
47             try {
48                 if (null != out) {
49                     out.flush();
50                 }
51             } catch (Exception e2) {
52                 e2.printStackTrace();
53             }
54         }
55     }
56 
57 }
複製代碼

User.java 爲了測試 FreeMarker的集合對象

複製代碼
1 package com.freemark.demo;
 2 
 3 public class User {
 4 
 5     private Integer id;
 6     private String name;
 7 
 8     public User() {
 9     }
10 
11     public User(Integer id, String name) {
12         this.id = id;
13         this.name = name;
14     }
15 
16     public Integer getId() {
17         return id;
18     }
19 
20     public void setId(Integer id) {
21         this.id = id;
22     }
23 
24     public String getName() {
25         return name;
26     }
27 
28     public void setName(String name) {
29         this.name = name;
30     }
31 
32     @Override
33     public String toString() {
34         return "User [id=" + id + ", name=" + name + "]";
35     }
36 
37 }
複製代碼

最後的打印結果

複製代碼
字符串輸出:
Hello itdragon博客 ! / Hello itdragon博客 !
特殊字符完成輸出(http:\www.baidu.com)

字符串截取 : 
經過下標直接獲取下標對應的字母: d
起點下標..結尾下標截取字符串:itdrag

算數運算:
"+" : 15
"-" : 5
"*" : 50
"/" : 2
"%" : 0

比較運算符:
"*" : 50

內建函數:
第一個字母大寫:Abcd1234
全部字母小寫:abcd1234
全部字母大寫:ABCD1234
數值取整數:12
獲取集合的長度:3
時間格式化:2017-10-29

空判斷和對象集合:
1 - ITDragon 博客
2 - 歡迎
3 - You!

Map集合:
直接經過Key獲取 Value值:程序員
經過Key遍歷Map:
Key: name - Value: 程序員
Key: salary - Value: 15,000
經過Value遍歷Map:
Value: 程序員
Value: 15,000

List集合:
ITDragon blog is cool 

include指令:
其餘FreeMarker文件

macro宏指令:
使用宏macro: 定義無參數的宏macro--itdragon博客
使用帶參數的宏macro: 定義帶參數的宏macro-- 6

命名空間:
另一個FreeMarker的變量
result : 30
另一個FreeMarker的變量
修改otherFreeMarker.ftl中的otherName變量值
複製代碼

語法詳解

數據類型

和java不一樣,FreeMarker不須要定義變量的類型,直接賦值便可。

字符串: value = "xxxx" 。若是有特殊字符 string = r"xxxx" 。單引號和雙引號是同樣的。

數值:value = 1.2。數值能夠直接等於,可是不能用科學計數法。

布爾值:true or  false。

List集合:list = [1,2,3] ; list=[1..100] 表示 1 到 100 的集合,反之亦然。

Map集合:map = {"key" : "value" , "key2" : "value2"},key 必須是字符串哦!

實體類:和EL表達式差很少,直接點出來。

字符串操做

字符串鏈接:能夠直接嵌套${"hello , ${name}"} ; 也能夠用加號${"hello , " + name}

字符串截取:string[index]。index 能夠是一個值,也能夠是形如 0..2 表示下標從0開始,到下標爲2結束。一共是三個數。

比較運算符

== (等於),!= (不等於),gt(大於),gte(大於或者等於),lt(小於),lte(小於或者等於)。不建議用 >,<  可能會報錯!

通常和 if 配合使用

內建函數

FreeMarker 提供了一些內建函數來轉換輸出,其結構:變量?內建函數,這樣就能夠經過內建函數來轉換輸出變量。

1. html: 對字符串進行HTML編碼;
2. cap_first: 使字符串第一個字母大寫;
3. lower_case: 將字符串轉成小寫;
4. upper_case: 將字符串轉成大寫;
5. size: 得到集合中元素的個數;
6. int: 取得數字的整數部分。

變量空判斷

 !    指定缺失變量的默認值;通常配置變量輸出使用
??    判斷變量是否存在。通常配合if使用 <#if value??></#if>

宏指令

能夠理解爲java的封裝方法,供其餘地方使用。宏指令也稱爲自定義指令,macro指令

語法很簡單:<#macro val > 聲明macro </#macro>; 使用macro <@val />  

命名空間

能夠理解爲java的import語句,爲避免變量重複。一個重要的規則就是:路徑不該該包含大寫字母,使用下劃線_分隔詞語,myName --> my_name

語法很簡單:<#import "xxx.ftl" as val> 

 

其餘沒有說明的語法是由於和java同樣,沒什麼特別之處。因此沒有列出來。

4 FreeMarker Web

這裏是和SpringMVC整合的,SpringMVC的配置就很少說了,筆者也寫過相關的文章,同時也會提供源碼

導入相關的jar pom.xml

複製代碼
<!-- freeMarker start -->
    <dependency>
         <groupId>org.freemarker</groupId>
         <artifactId>freemarker</artifactId>
         <version>2.3.20</version>
     </dependency>
     <dependency>
          <groupId>org.springframework</groupId>
          <artifactId>spring-context-support</artifactId>
          <version>4.1.4.RELEASE</version>
      </dependency>
  </dependencies> 
  <!-- freeMarker end -->
複製代碼

springmvc的配置文件:

複製代碼
<!-- 整合Freemarker -->
    <!-- 放在InternalResourceViewResolver的前面,優先找freemarker -->  
    <bean id="freemarkerConfig" class="org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer">  
        <property name="templateLoaderPath" value="/WEB-INF/views/templates"/>  
    </bean>  
    <bean id="viewResolver" class="org.springframework.web.servlet.view.freemarker.FreeMarkerViewResolver">  
        <property name="prefix" value=""/>  
        <property name="suffix" value=".ftl"/>  
        <property name="contentType" value="text/html; charset=UTF-8"/>
    </bean>
複製代碼

Controller 層

複製代碼
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
public class HelloFreeMarkerController {
    
    @RequestMapping("/helloFreeMarker")
    public String helloFreeMarker(Model model) {
        model.addAttribute("name","ITDragon博客");  
        return "helloFreeMarker";
    }

}
複製代碼

最後是Freemarker文件

複製代碼
<html>  
<head>  
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">  
<title>FreeMarker Web</title>  
</head>  
<body>  
    <h1>Hello ${name} !</h1>  
</body>  
</html>
複製代碼

源碼地址:https://gitee.com/itdragon/springmvc

5 小結

1. 知道了FreeMarker是一塊模版引擎,能夠生產xml,html,java等文件

2. 知道了FreeMarker文件提供佔位符,java文件提供數據,經過FreeMarker模版引擎生產有數據的頁面,文中是將數據放在Map中。web應用能夠用setter/getter 方法

3. 知道了FreeMarker語法中字符串的顯示特殊字符,截取的操做。以及一些內置方法的使用

4. 重點了解FreeMarker的空判斷知識點。判斷變量是否爲空用 "??" ,若是變量爲空設置默認值。若是不注意空問題,可能會出現黃色頁面的提示哦!

5. FreeMarker的宏概念,命名空間,引入文件,給變量賦值,集合的遍歷等。

6. Freemarker 整合SpringMVC。

 

到這裏FreeMarker的入門就結束了,是否是很簡單。若是有什麼不對的地方,請指正!

相關文章
相關標籤/搜索