FreeMarker是一款免費的Java模板引擎,是一種基於模板和數據生成文本(HMLT、電子郵件、配置文件、源代碼等)的工具,它不是面向最終用戶的,而是一款程序員使用的組件。html
FreeMarker最初設計是用來在MVC模式的Web開發中生成HTML頁面的,因此沒有綁定Servlet或任意Web相關的東西上,因此它能夠運行在非Web應用環境中。java
FreeMarker初版在1999年未就發佈了,2002年初使用JavaCC(Java Compiler Compiler是一個用Java開發的語法分析生成器)重寫了FreeMarker的核心代碼,2015年FreeMarker代碼遷移到了Apache下。git
GitHub地址:https://github.com/apache/freemarker程序員
FreeMarker模板存儲在服務器上,當有用戶訪問的時候,FreeMarker會查詢出相應的數據,替換模板中的標籤,生成最終的HTML返回給用戶,以下圖:github
基礎使用分爲3部分,這3部分組成了FreeMarker:golang
指令是FreeMarker用來識別轉換的特殊標籤,表達式是標籤裏具體的語法實現,其餘部分是一些很差分類的模板。web
使用FTL(freemarker template language)標籤來調用指令。spring
指令速覽:apache
下來咱們分別來看每一個指令對應具體使用。數組
assign 分爲變量和代碼片斷聲明兩種。
能夠是單變量聲明,或多變量聲明,下面是多變量聲明的示例:
<#assign name="adam" age=18 "sex"="man"> ${name} - ${age} - ${"sex"}
單個變量的話,只寫一個就能夠了。
<#assign code> <#list ["java","golang"] as c> ${c} </#list> </#assign> ${code}
其中 ${code}
是用來執行方法的,若是不調用話,代碼片斷不會執行。
attempt(嘗試), recover(恢復)指令相似於程序的try catch,示例以下:
<#attempt> i am ${name} <#recover> error name </#attempt>
若是有變量「name」就會正常顯示,顯示「i am xxx」,若是沒有變量就會顯示「error name」。
<#compress> 1 2 3 4 5 test only I said, test only </#compress> 1 2 3 4 5 test only I said, test only
效果以下:
對空白不敏感的格式,移除空白行仍是挺有用的功能。
<#escape x as x?html> ${firstName} ${lastName} </#escape>
上面的代碼,相似於:
${firstName?html} ${lastName?html}
Java代碼:
@RequestMapping("/") public ModelAndView index() { ModelAndView modelAndView = new ModelAndView("/index"); modelAndView.addObject("firstName", "<span style='color:red'>firstName</span>"); modelAndView.addObject("lastName", "lastName"); return modelAndView; }
最終的效果是:
單問號後面跟的是操做函數,相似於Java中的方法名,html屬於內建函數的一個,表示字符串會按照HTML標記輸出,字符替換規則以下:
<
替換爲 <
>
替換爲 >
&
替換爲 &
"
替換爲 "
HTML代碼:
<#escape x as x?html> <#noescape> ${firstName} </#noescape> ${lastName} </#escape>
Java代碼:
@RequestMapping("/") public ModelAndView index() { ModelAndView modelAndView = new ModelAndView("/index"); modelAndView.addObject("firstName", "<span style='color:red'>firstName</span>"); modelAndView.addObject("lastName", "lastName"); return modelAndView; }
最終效果:
代碼格式:
<#function name param1 param2 ... paramN> ... <#return returnValue> ... </#function>
示例代碼以下:
<#function sum x y z> <#return x+y+z> </#function> ${sum(5,5,5)}
注意:function若是沒有return是沒有意義的,至關於返回null,而function之中信息是不會打印到頁面的,示例以下:
<#function wantToPrint> 這裏的信息是顯示不了的 </#function> <#if wantToPrint()??> Message:${wantToPrint()} </#if>
「??」用於判斷值是不是null,若是爲null是不執行的。若是不判null直接使用${}打印,會報模板錯誤,效果以下:
語法以下:
<#global name=value> 或 <#global name1=value1 name2=value2 ... nameN=valueN> 或 <#global name> capture this </#global>
global使用和assign用法相似,只不過global聲明是全局的,全部的命名空間都是可見的。
語法以下:
<#if condition> ... <#elseif condition2> ... <#elseif condition3> ... ... <#else> ... </#if>
示例以下:
<#assign x=1 > <#if x==1> x is 1 <#elseif x==2> x is 2 <#else> x is not 1 </#if>
語法: <#import path as hash>
示例以下
footer.ftl 代碼以下:
<html> <head> <title>王磊的博客</title> </head> <body> this is footer.ftl <#assign copy="來自 王磊的博客"> </body> </html>
index.ftl 代碼以下:
<html> <head> <title>王磊的博客</title> </head> <body> <#import "footer.ftl" as footer> ${footer.copy} </body> </html>
最終輸出內容:
來自 王磊的博客
語法: <#include path>
示例以下
footer.ftl 代碼以下:
<html> <head> <title>王磊的博客</title> </head> <body> this is footer.ftl <#assign copy="來自 王磊的博客"> </body> </html>
index.ftl 代碼以下:
<html> <head> <title>王磊的博客</title> </head> <body> <#include "footer.ftl"> </body> </html>
最終內容以下:
this is footer.ftl
輸出1-3的數字,若是等於2跳出循環,代碼以下:
<#list 1..3 as n> ${n} <#if n==2> <#break> </#if> </#list>
注意:「1..3」等於[1,2,3]。
結果: 1 2
示例以下:
<#list 1..3> <ul> <#items as n> <li>${n}</li> </#items> </ul> </#list>
跳過最後一項
<#list 1..3 as n> ${n} <#sep>,</#sep> </#list>
最終結果:1 , 2 , 3
代碼以下:
<#list 1..3 as n> ${n} <#if !n_has_next> 最後一項 </#if> </#list>
使用「變量_has_next」判斷是否還有下一個選項,來找到最後一項,最終的結果:1 2 3 最後一項
宏:是一個變量名的代碼片斷,例如:
<#macro sayhi name> Hello, ${name} </#macro> <@sayhi "Adam" />
至關於聲明瞭一個名稱爲「sayhi」有一個參數「name」的宏,使用自定義標籤「@」調用宏。
輸出的結果: Hello, Adam
示例代碼以下:
<#assign animal="dog" > <#switch animal> <#case "pig"> This is pig <#break> <#case "dog"> This is dog <#break> <#default> This is Aaimal </#switch>
指令自動忽略空格特性
FreeMarker會忽略FTL標籤中的空白標記,因此能夠直接寫:
<#list ["老王","老李","老張"] as p> ${p} </#list>
即便是這個格式也是沒有任何問題的,FreeMarker會正常解析。
字符拼接代碼:
<#assign name="ABCDEFG"> ${"Hello, ${name}"}
結果:Hello, ABCDEFG
算術符有五種:
+
-
*
/
%
求餘(求模)示例代碼:
${100 - 10 * 20}
輸出:
-100
${1.999?int}
輸出:
1
注意:數值轉換不會進行四捨五入,會捨棄小數點以後的。
內建函數:至關於咱們Java類裏面的內置方法,很是經常使用,經常使用的內建函數有:時間內建函數、字符內建函數、數字內建函數等。
單問號:在FreeMarker中用單個問號,來調用內建函數,好比: ${"admin"?length}
查看字符串「admin」的字符長度,其中length就是字符串的內建函數。
雙引號:表示用於判斷值是否爲null,好比:
<#if admin??> Admin is not null </#if>
使用contains判斷,代碼示例:
<#if "admin"?contains("min")> min <#else > not min </#if>
輸出:
min
示例代碼:
<#assign name="Adam"> ${name?uncap_first} ${name?upper_case} ${name?cap_first} ${name?lower_case}
輸出:
adam ADAM Adam adam
更多的字符串內建函數:https://freemarker.apache.org/docs/ref_builtins_string.html
示例代碼:
${1.23569?string.percent} ${1.23569?string["0.##"]} ${1.23569?string["0.###"]}
輸出:
124% 1.24 1.236
注意:
代碼:
<#assign timestamp=1534414202000> ${timestamp?number_to_datetime?string["yyyy/MM/dd HH:mm"]}
輸出:
2018/08/16 18:10
示例代碼:
<#assign nowTime = .now> ${nowTime} <br /> ${nowTime?string["yyyy/MM/dd HH:mm"]} <br />
輸出:
2018-8-16 18:33:50 2018/08/16 18:33
更多內建方法:https://freemarker.apache.org/docs/ref_builtins.html
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-freemarker</artifactId> </dependency>
主要配置,以下:
## Freemarker 配置 spring.freemarker.template-loader-path=classpath:/templates/ spring.freemarker.cache=false spring.freemarker.charset=UTF-8 spring.freemarker.check-template-location=true spring.freemarker.content-type=text/html spring.freemarker.expose-request-attributes=false spring.freemarker.expose-session-attributes=false spring.freemarker.request-context-attribute=request spring.freemarker.suffix=.ftl
配置項 | 類型 | 默認值 | 建議值 | 說明 |
---|---|---|---|---|
spring.freemarker.template-loader-path | String | classpath:/templates/ | 默認 | 模版存放路徑 |
spring.freemarker.cache | bool | true | 默認 | 是否開啓緩存,生成環境建議開啓 |
spring.freemarker.charset | String | - | UTF-8 | 編碼 |
spring.freemarker.content-type | String | text/html | text/html | content-type類型 |
spring.freemarker.suffix | String | .ftl | .ftl | 模板後綴 |
spring.freemarker.expose-request-attributes | bool | false | false | 設定全部request的屬性在merge到模板的時候,是否要都添加到model中 |
spring.freemarker.expose-session-attributes | bool | false | false | 設定全部HttpSession的屬性在merge到模板的時候,是否要都添加到model中. |
spring.freemarker.request-context-attribute | String | - | request | RequestContext屬性的名稱 |
更多配置:
# FREEMARKER (FreeMarkerProperties) spring.freemarker.allow-request-override=false # Whether HttpServletRequest attributes are allowed to override (hide) controller generated model attributes of the same name. spring.freemarker.allow-session-override=false # Whether HttpSession attributes are allowed to override (hide) controller generated model attributes of the same name. spring.freemarker.cache=false # Whether to enable template caching. spring.freemarker.charset=UTF-8 # Template encoding. spring.freemarker.check-template-location=true # Whether to check that the templates location exists. spring.freemarker.content-type=text/html # Content-Type value. spring.freemarker.enabled=true # Whether to enable MVC view resolution for this technology. spring.freemarker.expose-request-attributes=false # Whether all request attributes should be added to the model prior to merging with the template. spring.freemarker.expose-session-attributes=false # Whether all HttpSession attributes should be added to the model prior to merging with the template. spring.freemarker.expose-spring-macro-helpers=true # Whether to expose a RequestContext for use by Spring's macro library, under the name "springMacroRequestContext". spring.freemarker.prefer-file-system-access=true # Whether to prefer file system access for template loading. File system access enables hot detection of template changes. spring.freemarker.prefix= # Prefix that gets prepended to view names when building a URL. spring.freemarker.request-context-attribute= # Name of the RequestContext attribute for all views. spring.freemarker.settings.*= # Well-known FreeMarker keys which are passed to FreeMarker's Configuration. spring.freemarker.suffix=.ftl # Suffix that gets appended to view names when building a URL. spring.freemarker.template-loader-path=classpath:/templates/ # Comma-separated list of template paths. spring.freemarker.view-names= # White list of view names that can be resolved.
<html> <head> <title>王磊的博客</title> </head> <body> <div> Hello,${name} </div> </body> </html>
新建index.java文件,Application.java(入口文件)代碼不便,index.java代碼以下:
import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.servlet.ModelAndView; @Controller @RequestMapping("/") public class Index { @RequestMapping("/") public ModelAndView index() { ModelAndView modelAndView = new ModelAndView("/index"); modelAndView.addObject("name", "老王"); return modelAndView; } }
關鍵代碼解讀:
執行上面4個步驟以後,就能夠運行這個Java項目了,若是是IDEA使用默認快捷鍵「Shift + F10」啓動調試,在頁面訪問:http://localhost:8080/ 就可看到以下效果:
FreeMarker官方文檔:https://freemarker.apache.org/
FreeMarker翻譯的中文網站:http://freemarker.foofun.cn/toc.html