模板引擎FreeMarker的介紹和使用

模板引擎

  • 模板引擎的目標是“數據+模板=結果”
  • 模板引擎將數據與展現有效的“解耦”
  • 前端只需要知道怎麼編寫前端,後端只需關注後端,用模板引擎把兩者整合

在這裏插入圖片描述

主流的模板引擎

  • Java Server Page(jsp)

  • FreeMarker

  • Beetl(擁有前兩者的優點,但是作爲新的模板,還未普及,前面兩個更常用)

FreeMarker和JSP
在這裏插入圖片描述

  • 只要不是開發淘寶、京東這樣的大型軟件,兩者的執行效率相差不多

FreeMarker

  • FreeMarker是免費開源的模板引擎技術
  • 要下載jar
  • FreeMarker腳本爲FreeMarker Template Language
  • FreeMarker 提供了大量內建函數來簡化開發(這就是很多人放棄jsp用FreeMarker的原因)

在java類中創建數據

import java.io.IOException;
import java.io.OutputStreamWriter;
import java.util.Calendar;
import java.util.HashMap;
import java.util.Map;
import freemarker.core.ParseException;
import freemarker.template.Configuration;
import freemarker.template.MalformedTemplateNameException;
import freemarker.template.Template;
import freemarker.template.TemplateException;
import freemarker.template.TemplateNotFoundException;

public class FreeMarkerSample {

	public static void main(String[] args) throws TemplateNotFoundException, MalformedTemplateNameException, ParseException, IOException, TemplateException {
		
		//1、加載模板
		//創建核心配置對象
		/*傳入版本號,每個版本的FreeMarker語法和解析方式都略有不同*/
		Configuration config=new Configuration(Configuration.VERSION_2_3_28);
		//設置加載的目錄
		/*第一個參數表示在這個類所在包中加載指定的ftl文件,第二個參數是空字符串,表示當前包 */
		config.setClassForTemplateLoading(FreeMarkerSample.class, "");
		//得到模板對象
		/*因爲上面指定了只在特定的類所在的包中加載ftl文件,所以這裏直接寫文件名就行*/
		Template t=config.getTemplate("sample1.ftl");
		
		//2、創建數據
		/*FreeMarker中的數據就是一個Map對象5*/
		Map<String,Object> data=new HashMap<>();
		data.put("site", "百度");
		data.put("url","http://www.baidu.com");
		data.put("date",Calendar.getInstance().getTime());
		data.put("number",456654456.7889);
		
		Map<String,Object> info=new HashMap<>();
		info.put("cpu","i5");
		Computer computer=new Computer("123","張三",7896.5f,info);
		data.put("compu",computer);
        
		//3、產生輸出(可以向控制檯、網絡中的流、文件中輸出)
		/*第一個參數是數據,第二個參數是向哪裏輸出*/
		t.process(data,new OutputStreamWriter(System.out));//像控制檯中輸出
	}
}

語法(均在.ftl文件中進行演示)

  • FTL取值

    只有輸出纔要加${}

在這裏插入圖片描述

<#-- FreeMarker取值 -->
${site}-${url}

<#-- 默認值,如果取的值不存在則會輸出後面的默認值 -->
${author!"不存在的屬性"}

<#-- 日期格式化輸出,如果不格式化會拋異常(日期不能轉成字符串) -->
${date?string("yyyy年MM月dd日 HH:mm:ss")}

<#-- 數字格式化輸出,如果不指定格式,默認按國際化貨幣格式輸出(三位一逗號,保留三位小數),四捨五入 -->
${number?string("0,0000.00")}


<#-- ${屬性名.對象中的屬性名} -->
ID:${compu.id}
User:${compu.user}
Price:${compu.price?string("0.00")}
<#-- 對象中集合屬性中值的獲取 -->
<#-- 數據中(Map中)保存對象的輸出方式跟EL表達式差不多 -->
<#-- ${屬性名.對象中集合屬性的屬性名["集合中的key"]}通過key獲取value -->
CPU:${compu.info["cpu"]}
Memory:${compu.info["memory"]!"memory not exist"}

關於多級訪問的變量,比如 animals.python.price, 書寫代碼:animals.python.price!0 當且僅當 animals.python 永遠存在, 而僅僅最後一個子變量 price 可能不存在時是正確的 (這種情況下我們假設價格是 0)。 如果 animalspython 不存在, 那麼模板處理過程將會以"未定義的變量"錯誤而停止。爲了防止這種情況的發生, 可以如下這樣來編寫代碼 (animals.python.price)!0。 這種情況就是說 animalspython 不存在時, 表達式的結果是 0。對於 ?? 也是同樣用來的處理這種邏輯的; 將 animals.python.price?? 對比(animals.python.price)??來看。

  • if 分支判斷

在這裏插入圖片描述

<#-- if分支 -->
<#-- FreeMarker中字符串的判斷直接用==  -->
<#if compu.id=="123">
這是重要設配
<#elseif compu.id=="456">
正常保護等級
<#else>
接近廢棄的電腦
</#if>

<#-- ??用於判斷該對象是否爲空,不爲空返回true,爲空返回false -->
<#if compu.user??>
這臺電腦有人使用
<#else>
這臺電腦無人使用
</#if>
  • switch分支判斷

在這裏插入圖片描述

<#--在FreeMarker中,空格也會輸出,所以這裏爲了格式不留空格書寫-->

<#-- switch分支 -->
<#switch compu.id>
<#case "123">
這臺電腦很重要
<#break>
<#case "456">
正常保護等級
<#break>
<#default>
廢棄電腦
</#switch>
  • list迭代列表

在這裏插入圖片描述

<#-- 迭代List,並把值賦給arr,其中arr_index代表迭代的索引,從0開始 -->
<#list arrayList as arr>
${arr_index+1}-${arr}
</#list>

  • list迭代Map

在這裏插入圖片描述

<#-- 把Map中的key取出來(linkedMap?keys)當作一個List,再迭代 -->
<#list linkedMap?keys as key>
${key}-${linkedMap[key]}
</#list>

FreeMarker內建函數

在這裏插入圖片描述

${words?replace("blood","*****")}將字符串words中的blood子字符串替換爲*****輸出

?string實現三目運算符的操作${(words?index_of("blood")!=-1)?String("包含敏感詞彙",words)}

${name?cap_first}
${brand?upper_case}
${brand?length}
${words?replace("blood" , "*****")}
${words?index_of("blood")}
<#-- 利用?string實現三目運算符的操作 -->
${(words?index_of("blood") != -1)?string("包含敏感詞彙","不包含敏感詞彙")}

${n?round}
${n?floor}
${n?ceiling}

公司共有${computers?size}臺電腦
第一臺:${computers?first.model}
最後一臺:${computers?last.model}

排序

<#-- 默認按照指定屬性升序排列,可以調用reverse函數進行降序排列 -->
<#list computers?sort_by("price")?reverse as c>
	${c.sn}-${c.price}
</#list>

Freemarker與Servlet的整合

ftl文件怎麼在web項目中被執行

  • Freemarker對整合servlet有良好的支持,在FreeMarker.jar包中存在支持Servlet的類

在這裏插入圖片描述

  • 需要使用這個Servlet類就必須在web.xml中註冊
<!--註冊FreemarkerServlet  -->
  <servlet>
  	<servlet-name>freemarker</servlet-name>
  	<servlet-class>freemarker.ext.servlet.FreemarkerServlet</servlet-class>
  	<!--配置初始化參數,通知FreemarkerServlet在哪個目錄下尋找.ftl文件(設置加載的目錄)  -->
  	<init-param>
  		<param-name>TemplatePath</param-name>
  		<param-value>/WEB-INF/ftl</param-value>
  	</init-param>
  </servlet>
  
  <!--FreemarkerServlet映射地址,只要瀏覽器地址欄中的URL是以.ftl結尾,就會被FreemarkerServlet處理  -->
  <servlet-mapping>
  	<servlet-name>freemarker</servlet-name>
  	<url-pattern>*.ftl</url-pattern>
  </servlet-mapping>

在配置初始化參數的時候,我們指定了FreemarkerServlet在哪個目錄下尋找.ftl腳本文件,所以我們的.ftl文件都要保存在這個文件中

在這裏插入圖片描述

通過在瀏覽器中輸入http://localhost:8080/項目名/test.ftl就可以輸出這個腳本文件中的內容(並不要把完整的路徑輸入到瀏覽器中)

在這裏插入圖片描述

**執行原理:**當瀏覽器地址欄中輸入的URL以.ftl結尾,就會被FreemarkerServlet類處理,FreemarkerServlet類就會到web.xml配置文件指定的加載目錄中(就是init-param中配置的templatePath參數值)尋找和URL中同名的.ftl腳本文件進行輸出(上面是在/WEB-INF/ftl文件下尋找test.ftl文件進行輸出)

Freemarker與servlet

ListServlet.java

@WebServlet("/list")
public class ListServlet extends HttpServlet {
	private static final long serialVersionUID = 1L;
    /**
     * @see HttpServlet#HttpServlet()
     */
    public ListServlet() {
        super();
        // TODO Auto-generated constructor stub
    }

	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		List<Employee> employees=new ArrayList<>();
		employees.add(new Employee(7823l,"李四","技術部","java高級工程師",15000f));
		employees.add(new Employee(7824l,"張丹","市場部","客戶經理",14500f));
		request.setAttribute("employees", employees);
        
        //FreemarkerServlet會檢測到是以.ftl結尾的URL,進行處理(尋找對應的.ftl腳本文件進行輸出)
		request.getRequestDispatcher("/employee.ftl").forward(request, response);
	}
}

employee.ftl

<table class="table table-bordered table-hover">
                <thead>
                <tr>
                    <th>序號</th>
                    <th>員工編號</th>
                    <th>姓名</th>
                    <th>部門</th>
                    <th>職務</th>
                    <th>工資</th>
                    <th>&nbsp;</th>
                </tr>
                </thead>
                <tbody>
                <#--按員工編號升序輸出-->
                <#list employees?sort_by("empno") as emp>
                <tr>
                    <td>${emp_index+1}</td>
                    <#-- 整數輸出 -->
                    <td>${emp.empno?string("0")}</td>
                    <td>${emp.name}</td>
                    <td>${emp.department}</td>
                    <td>${emp.job}</td>
                    <td style="color: red;font-weight: bold">¥${emp.salary?string("0,000.00")}</td>
                </tr>
               </#list>
                </tbody>
 </table>

.ftl腳本文件中的數據是從哪裏獲取的?

從當前頁面的請求、會話、ServletContext中自動依次查找,如果都沒查找到,又沒有做其他處理,則會拋出異常。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章