什麼是 FreeMarker?javascript
FreeMarker 是一款模板引擎:一種基於模板的、用來生成輸出文本(任何來自於 HTML格式的文本用來css
自動生成源代碼)的通用工具。它是爲 Java 程序員提供的一個開發包或者說是類庫。它不是面向最終用戶,html
而是爲程序員提供的能夠嵌入他們開發產品的一款應用程序。java
搭建SpringMVC+FreeMarker環境jquery
springmvc.xml 此處只貼出了配置FreeMarker的代碼,hibernate配置等省略。程序員
<!--對模型視圖名稱的解析,即在模型視圖名稱添加先後綴 --> <bean id="viewResolver" class="org.springframework.web.servlet.view.freemarker.FreeMarkerViewResolver"> <property name="viewClass" value="org.springframework.web.servlet.view.freemarker.FreeMarkerView" /> <property name="prefix" value="/" /> <property name="suffix" value=".html" /> <property name="contentType" value="text/html;charset=utf-8" /> <property name="exposeRequestAttributes" value="true" /> <property name="exposeSessionAttributes" value="true" /> <property name="exposeSpringMacroHelpers" value="true" /> </bean> <!-- 定義freemarker參數文件並載入 --> <bean id="freemarkerConfiguration" class="org.springframework.beans.factory.config.PropertiesFactoryBean"> <property name="location" value="classpath:freemarker.properties" /> </bean> <!-- 定義freemarker配置,包括模板根路徑、參數 --> <bean id="freemarkerConfig" class="org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer"> <!-- 注意: templateLoaderPath必須設置,不然freemarker找不到模板位置 --> <property name="templateLoaderPath" value="/WEB-INF" /> <property name="freemarkerSettings" ref="freemarkerConfiguration" /> </bean>
web.xml就照標準的springmvc配置就好了web
固然別忘了配置freemaker.propertiesspring
freemaker.propertiesapi
template_update_delay=0 defaultEncoding=UTF-8 url_escaping_charset=UTF-8 locale=zh_CN boolean_format=true,false datetime_format=yyyy-MM-dd HH:mm:ss date_format=yyyy-MM-dd time_format=HH:mm:ss number_format=0.###### whitespace_stripping=true
註釋數組
<#-- 此處是註釋 -->
註釋freemaker代碼,不要用html的註釋,沒有效果。
打印值
字符串
<#assign name="hello"> ${name} <!-- 輸出hello -->
數值
<#assign number=10> ${number} <!--輸出10 --> <#assign number2=2.5> ${number2} <!--輸出2.5 --> <#assign avg = number/number2> ${avg} <!--輸出4 -->
boolean
<#assign flag = true> ${flag} <!-- 輸出true --> <#assign flag2 = false> ${flag2} <!-- 什麼也沒有輸出 爲空字符串-->
<#assign flag3 = "true"> ${flag3} <!-- 輸出爲true --> <#assign flag4 = "false"> ${flag4}
<#if flag3> 爲真 </#if> <!-- 打印爲真,freemarker將字符串"true"轉換爲boolean -->
運算符
<#assign x=2> ${100-2} <!-- 減 打印98 --> ${10/2} <!-- 除 打印5 --> ${10*2} <!-- 乘 打印20 --> ${9%2} <!-- 取餘 打印1 -->
流程控制
<#assign x2 = 1> <#assign x3 = 5> <#assign x4 =6> <#if (x2<x3) > A </#if> <!-- 打印A,注意此處必定要加括號 --> <#if (x2>x3)> B <#else> C </#if> <!-- 打印C --> <#if (x2>x3)> A <#elseif (x2>x4)> B <#elseif (x2<x4)> C </#if> <!-- 打印C -->
<#assign x5 =5> <#switch x5> <#case 10> A <#break> <#case 5> B <#break> <#default> C </#switch> <!-- 打印5 -->
遍歷
List,Set
後臺傳入一個uerList的list或者Set
<#list userList as user> ${user.name} </#list> <!--打印出用戶名列表-->
Map
map爲後臺傳入的Map集合
<#list map?keys as k> ${k} <!-- 鍵 --> ${map[k]} <!-- 值 --> </#list>
處理空值
可在freemarker.properties中加一句classic_compatible=true若是對象爲空將不會報錯
<#if user??> </#if> <!-- 判斷user對象是否爲空,若是不爲空執行if語句中的代碼-->
<!-- 在變量後面加!處理變量值爲空的狀況--> ${user.name!} <!-- 判斷name是否爲空 若是爲空將什麼也不顯示--> ${(user.name)!} <!-- 判斷user和name是否都爲空,若是有任意一個爲空什麼都不顯示 若是你有多個對象連環調用屬性請必定要加()否則freemarker只會判斷最後一個變量,不然報錯--> ${(user.name)!"您尚未登陸"} <!-- 若是變量爲空的狀況下,將顯示默認值-->
內置函數
集合
userList 爲後臺傳入的對象集合
<#list userList?reverse as li> ${li.name} </#list> <!-- ?reverse 將對象集合順序反轉 --> ${(userList?first).name} <!-- ?first 打印集合中第一個user對象的name --> ${(userList?last).name} <!-- ?last 打印集合中最後一個user對象的name --> ${userList?size} <!-- ?size 打印集合的長度 --> <#list userList?sort as li> ${li.name} </#list><br> <!-- 將對象轉換爲字符串 順序排序 --> <#list userList?sort_by("id") as li> ${li.name} </#list><br> <!-- 將對象中的屬性值進行排序, 當前爲user中的id排序 -->
字符串
${"string"?substring(0)} <!-- 從索引0開始截取字符串 爲string --> ${"string"?substring(1)} <!-- 從索引1開始截取字符串 爲tring --> ${"string"?substring(0,1)} <!-- 從索引0到1截取字符串 爲 s --> ${"string"?substring(1,2)} <!-- 從索引1到2截取字符串爲 t --> ${"string"?cap_first} <!-- 將字符串首字母變爲大寫 String--> ${"String"?uncap_first} <!-- 將字符串首字母變爲小寫 string--> ${"string"?upper_case} <!-- 將字符串所有轉換爲大寫 --> ${"STRINg"?lower_case} <!-- 將字符串所有轉換爲小寫 --> ${"2014-11-11 9:0:0"?date("yyyy-MM-dd")} <!-- 輸出爲2014-11-11 --> ${"string"?ends_with("ing")} <!-- 判斷字符串 是否已某段字符串結尾 打印true --> ${"string"?index_of("tr")} <!-- 判斷某段字符串在一段字符串中出現的索引位置,若是沒有返回-1 打印1 --> ${"string"?contains('ing')} <!-- 判斷一個字符串中是否包含某段字符串 返回true或false --> ${"strabgab"?replace("ab","in")} <!-- 將字符串總包含的某段字符串所有替換掉 結果爲stringin--> <#list "this,is,freemaker"?split(",") as s> ${s} </#list> <!-- 使用指定的符號將字符串分割爲數組 --> ${" String "?trim} <!-- 去掉首位空格 --> <#assign num = 1> ${num?string.number} <!-- 轉換爲數字格式 1 --> ${num?string.currency} <!-- 轉換爲貨幣格式 ¥1.00 --> ${num?string. percent} <!-- 轉換爲百分比格式 100% --> <#assign flag = true> ${flag?string("yes","no")} <!-- 根據boolean類型的真假值來輸出相應的字符串 -->
freemarker宏定義
宏定義的語法爲:<#macro 宏名稱 參數1 參數2 參數3 。。。></#macro>
首先咱們新建一個freemarker的ftl文件
此處爲spring.ftl
<#macro hello> <h1>hello,World!</h1> </#macro> <#-- 定義了一個名爲hello的宏,在宏中咱們能夠寫任意的html代碼 -->
而後在個人html頁面引入
<#import "../../page/spring.ftl" as h /> <!--引入文件 --> <@h.hello /> <!-- 調用名爲hello的宏 -->
而後運行項目打印的爲
hello,World!
下面再來個帶參數的
<#macro welcome name age> <span>歡迎您, ${age} 歲的 ${name} 先生,來到freemarker的世界</span> </#macro>
頁面調用宏
<@h.welcome "小李" 22/>
打印爲
歡迎您, 22 歲的 小李 先生,來到freemarker的世界
宏嵌套 <#nested>,表示咱們能夠在宏的標籤內加入任意的內容,包括宏
<#macro go> <#nested> </#macro>
頁面調用
<#import "../../page/spring.ftl" as h /> <@h.go> 你們好! </@h.go>
此處打印的是:你們好!
咱們再來試試嵌套的,這裏我定義了兩個宏
<#macro go2> <#nested> </#macro> <#macro go3 name> ${name} </#macro>
頁面調用
<#import "../../page/spring.ftl" as h /> <@h.go2> <@h.go3 "你好"/>,你今天過得快樂嗎? </@h.go2>
此處打印的爲:你好,你今天過得快樂嗎?
使用宏作一個freemarker分頁
首先咱們的寫個分頁的ftl文件
pager.ftl
<#-- 自定義的分頁指令 屬性: pageNo 當前頁號(int類型) pageSize 每頁要顯示的記錄數(int類型) pageCount 總頁數 toURL 點擊分頁標籤時要跳轉到的目標URL(string類型) --> <#macro pager pageNo pageSize toURL pageCount> <#-- 輸出分頁表單 --> <div class="page"> <form method="post" action="${toURL}" name="qPagerForm"> <#--用於記錄當前的頁數 --> <input type='hidden' name ='page' /> <#-- 上一頁處理 --> <#if (pageNo == 1)> <span class="disabled"><a >上一頁</a></span> <#else> <span ><a href="javascript:page(${pageNo - 1})">上一頁</a></span> </#if> <#-- 若是前面頁數過多,顯示... --> <#assign start=1> <#if (pageNo > 4)> <#assign start=(pageNo - 2)> <a href="javascript:page(1)">1</a> <span style='color:#444693;'>...</span> </#if> <#-- 顯示當前頁號和它附近的頁號 --> <#assign end=(pageNo + 2)> <#if (end > pageCount)> <#assign end=pageCount> </#if> <#list start..end as i> <#if (pageNo==i)> <span ><a class="dq">${i}</a></span> <#else> <span><a href="javascript:page(${i})">${i}</a></span> </#if> </#list> <#-- 若是後面頁數過多,顯示... --> <#if (end < pageCount - 1)> <span style='color:#444693;'>...</span> </#if> <#if (end < pageCount)> <a href="javascript:page(${pageCount})">${pageCount}</a> </#if> <#-- 下一頁處理 --> <#if (pageNo == pageCount)> <span class="disabled"><a >下一頁</a></span> <#else> <span> <a href="javascript:page(${pageNo + 1})">下一頁</a> </span> </#if> </form> <script language="javascript"> function page(no){ var $qForm=$("form[name='qPagerForm']"); $qForm.find("input[name='page']").val(no); $qForm.submit(); } </script> </div> </#macro>
咱們只需將分頁的結果對象傳入頁面,分頁對象包括:分頁的結果數據,當前頁號,每頁要顯示的條數,總頁數。
@RequestMapping(value="userList") public String userList(ModelMap modelMap,@RequestParam(defaultValue="1") int page){ int pageSize = 8; Pagination p = userDmn.find(page, pageSize, "from User"); modelMap.put("p", p); return "page/userList"; }
而後將數據循環在頁面,頁面調用分頁宏
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <script type="text/javascript" src="../js/jquery-1.7.1.min.js"></script> <style type="text/css"> .page{height:30px; line-height:30px; margin:20px 0; clear:both;} .page a{color:#444693; font-size:14px; border:1px solid #eeeeee; padding:5px 8px;text-decoration: none} .page a.dq{background:#444693; padding:5px 8px; color:#fff;} </style> </head> <body> <table> <tr> <th>ID</th> <th>用戶名</th> <th>密碼</th> </tr> <#list p.list as user> <tr> <td>${user.id}</td> <td>${user.name}</td> <td>${user.pwd}</td> </tr> </#list> </table> <#import "../../page/pager.ftl" as page/> <@page.pager pageNo=p.pageNo pageSize = p.pageSize toURL="../user/userList" pageCount=p.getTotalPage()/> </body> </html>
效果圖:
當咱們在進行開發是,頁面要引入許多js和css,特別是一些公用的文件,在此咱們能夠將這些代碼寫到一個宏中,要用的話就直接調用宏。
<#macro frontJs> <script type="text/javascript" src="../js/jquery-1.7.1.min.js"></script> </#macro>
在頁面上調用宏
<#import "../../page/spring.ftl" as spring/> <@spring.frontJs />
就這樣咱們在頁面中引入了js文件。
固然咱們在每一個頁面中都去寫一個<#import />確實有點不爽,freemarker配置中有個屬性叫 auto_import,, 叫作自動導入,
auto_import=spring.ftl as spring
在此咱們就不用引入spring.ftl文件了,由於已經自動導入了,如今咱們在每一個頁面均可以直接使用,咱們能夠寫一些經常使用的宏在ftl文件中,再自動導入。
<@spring.frontJs />
在頁面中每每有相同的主菜單和左菜單,腳部,咱們均可以用這種方式來包含html代碼。
固然咱們也能夠用
<#include />
來包含相同的html頁面
freemarker獲取request對象
<bean id="viewResolver" class="org.springframework.web.servlet.view.freemarker.FreeMarkerViewResolver"> <property name="viewClass" value="org.springframework.web.servlet.view.freemarker.FreeMarkerView" /> <property name="prefix" value="/" /> <property name="suffix" value=".html" /> <property name="contentType" value="text/html;charset=utf-8" /> <property name="requestContextAttribute" value="rc" /> <property name="exposeRequestAttributes" value="true" /> <property name="exposeSessionAttributes" value="true" /> <property name="exposeSpringMacroHelpers" value="true" /> </bean>
在配置文件中加入一句
<property name="requestContextAttribute" value="rc" />
這樣就能夠在頁面中使用request對象了
${rc.contextPath}
獲取Session
User user = new User(); user.setId(1); user.setName("li"); user.setPwd("pwd"); session.setAttribute("user",user );
${Session["user"].name}
獲取Session中user對象中的name值