1. 程式人生 > 實用技巧 >FreeMarker網頁靜態化

FreeMarker網頁靜態化

網頁靜態化解決方案在實際開發中運用比較多,例如新聞網站,入口網站中的新聞頻道或者是文章類的頻道。

網頁靜態化技術和快取技術的共同點都是為了減輕資料庫的訪問壓力,但是具體的應用場景不同,快取比較適合小規模的資料,而網頁靜態化比較適合大規模且相對變化不太頻繁 的資料。另外網頁靜態化還有利於seo。另外我們如果將網頁以純靜態化的形式展現,就可以使用Nginx這樣的高效能的web伺服器來部署。Nginx可以承載5萬的併發,而Tomcat只有幾百。

一.FreeMarker簡介

FreeMarker 是一款用 Java 語言編寫的模板引擎 : 即一種基於模板和要改變的資料, 並用來生成輸出文字(html網頁,XML,jsP 或 Java 等)的通用工具。 它不是面向終端使用者的,而是一個Java類庫,是一款程式設計師可以嵌入他們所開發產品的元件。

中文線上文件:http://freemarker.foofun.cn/

二.FreeMarker使用步驟

1.第一步:工程中引入FreeMarker依賴

<!-- FreeMarker的座標 -->
<dependency>
    <groupId>org.freemarker</groupId>
    <artifactId>freemarker</artifactId>
    <version>2.3.23</version>
</dependency> 

2.第二步:建立模板檔案(test.ftl)

模板檔案中有四種元素:
  • 文字,直接輸出的部分

  • 註釋,即<#--...-->格式不會輸出

  • 插值(Interpolation):即${..}部分,將使用資料模型中的部分替代輸出

  • FTL指令:FreeMarker指令,和html標記類似,名字前加#予以區分,不會輸出

<!-- 模板檔案以 .ftl結尾 -->
<html>
<head>
    <meta charset="utf-8">
    <title>Freemarker入門DEMO </title>
</head>
<body>
<#--我是一個註釋,我不會有任何輸出  -->
${name},你好。${message}
<#-- FTL指令,引入檔案 -->
<#include "foot.ftl">
</body>
</html>

3.第三步:生成檔案(main方法)

執行後,可生成test.html檔案。

public class FreeMarkerTest{
    public static void main(String[] args) {
        //1.建立配置類,傳入自身版本號
        Configuration configuration=new Configuration(Configuration.getVersion());
        //2.設定模板所在的目錄 
        configuration.setDirectoryForTemplateLoading(new 
             File("D:/dintalk/freemarkerDemo/src/main/resources/"));
        //3.設定字符集
        configuration.setDefaultEncoding("utf-8");
        //4.載入模板
        Template template = configuration.getTemplate("test.ftl");
        //5.建立資料模型
        Map map=new HashMap();
        map.put("name", "song");
        map.put("message", "歡迎來到我的叮噹屋");
        //6.建立Writer物件
        Writer out =new FileWriter(new File("d:\\test.html"));
        //7.輸出
        template.process(map, out);
        //8.關閉Writer物件
        out.close();
    }
}

4.第三步:生成檔案(Spring環境中)

4.1resources/spring下建立applicaitonContext-freemarker.xml配置檔案
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:dubbo="http://code.alibabatech.com/schema/dubbo"
       xsi:schemaLocation="http://www.springframework.org/schema/beans 
               http://www.springframework.org/schema/beans/spring-beans.xsd
            http://code.alibabatech.com/schema/dubbo 
             http://code.alibabatech.com/schema/dubbo/dubbo.xsd">

    <!-- 1.duboo埠配置,預設是20880 -->
    <dubbo:protocol name="dubbo" port="20885"></dubbo:protocol>
    <dubbo:application name="dintalk-page-service"/>
    <dubbo:registry address="zookeeper://192.168.25.130:2181"/>
    <dubbo:annotation package="com.dintalk.page.service.impl"/>
    
    <!-- 2.freemarker的配置 -->
    <bean id="freemarkerConfig"
        class="org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer">
        <!-- 指定模板的位置和預設編碼 -->
        <property name="templateLoaderPath" value="/WEB-INF/ftl/"/>
        <property name="defaultEncoding" value="UTF-8"/>
    </bean>

</beans>
4.2編寫生成頁面的方法(以商城生成商品詳情頁為例)
/**
     * 根據商品id生成sku商品詳情的靜態化頁面
     * @param goodsId 商品id
     * @return
     */
    @Override
    public boolean genItemHtml(Long goodsId) {
        try {
            Configuration configuration = markerConfig.getConfiguration();
            Template template = configuration.getTemplate("item.ftl");
            //1.建立資料模型
            Map dataModel = new HashMap();

            //2.載入商品資料
            TbGoods tbGoods = goodsMapper.selectByPrimaryKey(goodsId);
            dataModel.put("goods", tbGoods);

            //3.載入商品描述
            TbGoodsDesc tbGoodsDesc = goodsDescMapper.selectByPrimaryKey(goodsId);
            dataModel.put("goodsDesc", tbGoodsDesc);

            //4.載入商品詳情列表
            TbItemExample example = new TbItemExample();
            example.createCriteria().andGoodsIdEqualTo(goodsId);
            example.setOrderByClause("is_default desc");
            List<TbItem> itemList = itemMapper.selectByExample(example);
            dataModel.put("itemList", itemList);

            //5.建立輸出物件
            FileWriter fileWriter = new FileWriter(pageDir + goodsId + ".html");
            template.process(dataModel, fileWriter);

            //關閉資源
            fileWriter.close();
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

資源搜尋網站大全 https://www.renrenfan.com.cn

三.FreeMarker常用FTL指令及函式

1.FTL指令

assign 指令 :在頁面上定義變數

<!-- 簡單型別 -->
<#assign linkman="宋先生">
<!-- 物件型別 -->
<#assign info={"mobile":"1501****212",‘address‘:‘北京市昌平區‘} >

include 指令:引入其他模板檔案

<#include "head.ftl">

if 指令:做條件判斷

<#if test=1>
  test=1
<#elseif test=2>  
  test=2
<#else>
  其他
</#if>

list 指令:實現遍歷

<#list goodsList as goods>
  ${goods_index+1} 商品名稱: ${goods.name} 價格:${goods.price}<br>
</#list>
<!-- 如果想在迴圈中得到索引,使用迴圈變數+_index就可以得到 -->

2.內建函式

內建函式語法格式: 變數+?+函式名稱
<!-- 1.獲取集合大小 : ? size -->
共 ${goodsList?size} 條記錄 

<!-- 2.轉換jsON字串為物件 : ? eval -->
<#assign text="{‘name‘:‘song‘,‘sex‘:‘man‘}" />
<#assign user=text?eval />
姓名:${user.name}  性別:${user.sex}

<!-- 3.日期格式化 : ? date ?time ?datetime ?string("yyy..") -->
dataModel.put("today", new Date());
當前日期:${today?date} <br>
當前時間:${today?time} <br> 
當前日期+時間:${today?datetime} <br>        
日期格式化:  ${today?string("yyyy年MM月")}

<!-- 4.數字轉為字串物件 : ?c -->
map.put("point", 102920122);
累計積分:${point}  <!-- 累計積分:102,920,122  -->
累計積分:${point?c}  <!-- 累計積分:102920122  -->

<!-- 5.空值處理運算子 -->
<!--如果你在模板中使用了變數但是在程式碼中沒有對變數賦值,
那麼執行生成時會丟擲異常。但是有些時候,有的變數確實是null如何解決-->

<!-- 5.1判斷變數是否存在 ?? -->
<#if aaa??>
  aaa變數存在
<#else>
  aaa變數不存在
</#if>
<!-- 5.2缺失變數預設值 ! 使用!對null值做轉換處理 -->
 ${aaa!‘-‘}
<!--在程式碼中不對aaa賦值也不會報錯,當aaa為null則返回!後邊的內容- -->

3.運算子

算術運算子

FreeMarker表示式中完全支援算術運算,FreeMarker支援的算術運算子包括:+, - , * , / ,% 。

邏輯運算子

邏輯運算子有如下幾個: 邏輯與:&& 邏輯或:|| 邏輯非:! 邏輯運算子只能作用於布林值,否則將產生錯誤。

比較運算子

表示式中支援的比較運算子有如下幾個:

1 =或者== : 判斷兩個值是否相等。

2 != : 判斷兩個值是否不等。

3 >或者gt : 判斷左邊值是否大於右邊值 。

4 >=或者gte : 判斷左邊值是否大於等於右邊值。

5 <或者lt : 判斷左邊值是否小於右邊值。

6 <=或者lte : 判斷左邊值是否小於等於右邊值。

注意:=和!=可以用於字串,數值和日期來比較是否相等,但=和!=兩邊必須是相同型別的值,否則會產生錯誤,而且FreeMarker是精確比較,"x","x ","X"是不等的.其它的執行符可以作用於數字和日期,但不能作用於字串,大部分的時候,使用gt等字母運算子代替>會有更好的效果,因為 FreeMarker會把>解釋成FTL標籤的結束字元,當然,也可以使用括號來避免這種情況,如:<#if (x>y)> 。