FreeMarker --- 网页静态化入门简介

一、概述

FreeMarker是一个模板引擎,一个基于模板生成文本输出的通用工具,使用纯Java编写。FreeMarker被设计用来生成HTMLWeb页面,特别是基于MVC模式的应用程序。

所谓模板,就是一份已经写好了基本内容,有着固定格式的文档,其中空出或者用占位符标识的内容,由使用者来填充,不同的使用者给出的数据是不同的。在模板中的占位符,在模板运行时,由模板引擎来解析模板,并采用动态数据替换占位符部分的内容。

FreeMarker不是一个Web应用框架,而适合作为Web应用框架一个组件,FreeMarker与Web容器无关,即在Web运行时,它并不知道Servlet或HTTP。它不仅可以用作表现层的实现技术,而且还可以用于生成XML,JSP或Java文件等。

虽然FreeMarker具有一些编程的能力,但通常由Java程序准备要显示的数据,由FreeMarker生成页面,通过模板显示准备的数据(如下图)

 

分离表现层和业务逻辑
使用JSP开发过程中在页面中大量的存在业务逻辑的代码,使得页面内容凌乱,在后期大量的修改维护过程中就变得非常困难。FreeMarker根本不支持Java脚本代码,而是使用el表达式来输出展示数据。FreeMarker的设计初衷就是:模板+数据模型=输出,模板只负责数据在页面中的表现,不涉及任何的逻辑代码,而所有的逻辑都是由数据模型来处理的。用户最终看到的输出是模板和数据模型合并后创建的。
 
 
提高开发效率
在我们以往的开发中,使用的都是JSP页面来展示数据的,即所谓的表现层。我们都知道,JSP在第一次执行的时候需要转换成Servlet类,开发阶段进行功能调适时,需要频繁的修改JSP,每次修改都要编译和转换,那么试想一天中我们浪费在程序编译的时间有多少。相对于JSP来说,FreeMarker模板技术不存在编译和转换的问题,所以就不会存在上述问题。而且开发过程中,我们在不必在等待界面设计开发人员完成页面原形后,我们再来开发程序。

 
 
分工明确
以往用JSP展现数据时,程序员并不熟悉界面设计技术,反之界面开发人员,也并不熟悉程序语言。协调工作很困难,使用FreeMarker后,作为界面开发人员,只专心创建HTML文件、图像以及Web页面的其他可视化方面,不用理会数据;而程序开发人员则专注于系统实现,负责为页面准备要显示的数据。

 

下载地址:

https://freemarker.apache.org/freemarkerdownload.html

 

资源:

API:

https://freemarker.apache.org/docs/api/index.html

http://tool.oschina.net/apidocs/apidoc?api=freemarker

 

用户手册:

https://freemarker.apache.org/docs/index.html

http://freemarker.foofun.cn/

 

二、入门案例

2.1 在WEB-INF下创建freemarker引擎模板ftl

 

<link rel="stylesheet" type="text/css" href="css/promotion_detail.css">
<div class="container promotions" >
    <div class="col-md-2 prolist">
        <h5 class="title"><a href="#/promotion"><strong>返回促销列表</strong></a></h5>
        <img src="images/pro.jpg" class="img-responsive">
    </div>
    <div class="col-md-10 procontent">
        <h5 class="title">${promotion.title}</h5>
        <div class="intro">
            <p>活动范围: ${promotion.activeScope}</p>
            <p>活动时间: ${promotion.startDate?string("yyyy-MM-dd")} - ${promotion.endDate?string("yyyy-MM-dd")}</p>
        </div>
        <div class="partline clearfix"></div>
        <div class="promotionbox">
            ${promotion.description}
        </div>
    </div>
</div>

 

 

2.2 Action中freemarker实现

 

@Action(value = "promotion_showDetail")
    public String showDetail() throws IOException, TemplateException {
        // 先判断id对应html是否存在,如果存在,直接返回
        String htmlRealPath = ServletActionContext.getServletContext().getRealPath("/freemarker");
        File htmlFile = new File(htmlRealPath + "/" + model.getId() + ".html");

        // 如果html文件不存在,查询数据库,结合freemarker模板生成页面
        if (!htmlFile.exists()){
            // 配置对象,配置模板位置
            Configuration configuration = new Configuration(Configuration.VERSION_2_3_22);
            configuration.setDirectoryForTemplateLoading(new File(ServletActionContext.getServletContext().getRealPath("/WEB-INF/freemarker_templates")));

            // 获取模板对象
            Template template = configuration.getTemplate("promotion_detail.ftl","utf-8");

            // 动态数据对象
            Promotion promotion = WebClient.create(Constant.BOS_MANAGEMENT_URL + "/bos_management/services/promotionService/promotion/" + model.getId()).accept(MediaType.APPLICATION_JSON).get(Promotion.class);
            Map<String,Object> parameterMap = new HashMap<>();
            parameterMap.put("promotion",promotion);

            // 合并输出
            template.process(parameterMap,new OutputStreamWriter(new FileOutputStream(htmlFile), "utf-8"));

        }

        // 如果html存在,直接将响应输出流返回
        ServletActionContext.getResponse().setContentType("text/html;charset=utf-8");
        FileUtils.copyFile(htmlFile,ServletActionContext.getResponse().getOutputStream());

        return NONE;
    }

 

 

 

 

 

三、FreeMarker模板文件.ftl主要有4个部分组成

3.1 文本:直接输出的部分

3.2 注释:即<#-- ... -->格式部分,不会输出

3.3 插值:即${...}或者#{...}格式的部分,将使用数据模型中的部分替代输出

3.4 FTL指令:FreeMarker指令,和HTML标记类似,名字前加#,例如<#list>

 

FTL指令规则:FreeMarker有三种FTL标签,这和HTML的标签是完全类似的

 

  • 开始标签:<#directivename parameters>
  • 结束标签:</#directivename>
  • 空标签: <#directivename parameters />

实际上,使用标签时前面的#符号也可能变成@,如果该指令是一个用户指令而不是系统内建指令时,应将#符号改为@符号

 

 

插值规则:FreeMarker的插值有如下两种类型

 

  • 通用插值:${expr}
  • 数字格式化插值:#{expr}或者#{expr;format}

 

    

通用插值,有可以分为四种情况

a、插值结果为字符串值:直接输出表达式结果

b、插值结果为数字值:根据默认格式(#setting 指令设置)将表达式结果转换成文本输出。可以使用内建的字符串函数格式单个插值,例如

<#setting number_format = "currency" />
<#assign price = 42 />
${price}
${price?string}
${price?string.number}
${price?string.currency}
${price?string.percent}

    

c、输出值为日期值:根据默认格式(由 #setting 指令设置)将表达式结果转换成文本输出,可以使用内建的字符串函数格式化单个插值,例如

<#assign lastUpdated = "2009-01-07 15:05"?datetime("yyyy-MM-dd HH:mm") />
${lastUpdated?string("yyyy-MM-dd HH:mm:ss zzzz")};
${lastUpdated?string("EEE,MMM d,yy")};
${lastUpdated?string("EEEE,MMMM dd,yyyy,hh:mm:ss a '('zzz')'")};
${lastUpdated?string.short};
${lastUpdated?string.long};
${lastUpdated?String.full};

   

d、插值结果为布尔值
<#assign foo=true />
${foo?string("是foo","非foo")}

 

数字格式化插值:数字格式化插值可采用#{expr;format}的形式来格式化数字,其中format可以是:

  • mX:小数部分最小X位
  • MX:小数部分最大X位

 

例如:

<#assign x = 2.582 />

<#assign y =4 />

#{x;M2};

#{y;M2};

#{x;m1};

#{y;m1};

#{x;m1M2};

#{y:m1M2};

 

四、FreeMarker标签

4.1 assign 

assign指令在前面已经使用了多次,它用于为该模板页面创建或替换一个顶层变量,assign指令的用法有多种,包含

创建或替换一个顶层变量,或者创建或替换多个变量等。

示范代码:
<#assign x>
<#list ["星期一", "星期二", "星期三", "星期四", "星期五", "星期六", "星期天"] as n>
${n}
</#list>
</#assign>

 

4.2 break 

<#break>指令用于跳出迭代
 

示例代码:
<#list ["星期一", "星期二", "星期三", "星期四", "星期五", "星期六", "星期天"] as x>
${x_index + 1}.${x}<#if x_has_next>,</if>
<#if x="星期四"><#break></#if>
</#list>

4.3 case 

switch , case , default , break这些指令显然是分支指令,作用类似于Java的switch语句

 

示例代码:
<#switch x>
<#case x = 1>
     1
<#case x = 2>
     2
<#default>
     d
</#switch> 
如果x=1 输出 1 2, x=2输出 2, x=3 输出d
 

4.4 if 
这是一个典型的分支控制指令,该指令的作用完全类似于Java语言中的if,if指令的语法格式如下:
 

示例如下:
<#assign age=23>
<#if (age>60)>老年人
<#elseif (age>40)>中年人
<#elseif (age>20)>青年人
<#else> 少年人
</#if>

 

4.5 else 
这是一个典型的分支控制指令,该指令的作用完全类似于Java语言中的if,if指令的语法格式如下:
 

示例如下:
<#assign age=23>
<#if (age>60)>老年人
<#elseif (age>40)>中年人
<#elseif (age>20)>青年人
<#else> 少年人
</#if>

 

4.6 elseif 
这是一个典型的分支控制指令,该指令的作用完全类似于Java语言中的if,if指令的语法格式如下:
 

示例如下:
<#assign age=23>
<#if (age>60)>老年人
<#elseif (age>40)>中年人
<#elseif (age>20)>青年人
<#else> 少年人
</#if>

 

4.7 escape 
escape指令导致body区的插值都会被自动加上escape表达式,但不会影响字符串内的插值,只会影响到body内出现的插值。
 

示例代码:
<#escape x as x?html>
First name:${firstName}
Last name:${lastName}
Maiden name:${maidenName}
</#escape>

 

4.8 import 
该指令用于导入FreeMarker模板中的所有变量,并将该变量放置在指定的Map对象中。
 

示例代码:
<#import "/libs/mylib.ftl" as my> 

4.9 include 
include指令的作用类似于JSP的包含指令,用于包含指定页。
 

示例代码:
<#include "/common/copyright.ftl" encoding=”GBK”> 

4.10 list 
list指令是一个迭代输出指令,用于迭代输出数据模型中的集合。
 

示例代码:
<#list ["星期一", "星期二", "星期三", "星期四", "星期五", "星期六", "星期天"] as x>
${x_index + 1}.${x}<#if x_has_next>,</if>
<#if x="星期四"><#break></#if>
</#list> 

4.11 macro 
macro可以用于实现自定义指令,通过使用自定义指令,可以将一段模板片段定义成一个用户指令。
 

示例代码:
<#macro book booklist>     //定义一个自定义指令booklist是参数
<#list booklist as book>
   ${book}
</#list>
</#macro> 

 

4.12 nested 
和macro标签一起使用, 在nested指令中使用循环变量时,可以使用多个循环变量

 

示例代码:
<#macro repeat count>
<#list 1..count as x>     //使用nested指令时指定了三个循环变量
   <#nested x, x/2, x==count>
</#list>
</#macro>
<@repeat count=4 ; c halfc last>
${c}. ${halfc}<#if last> Last! </#if>
</@repeat>

 

4.13 noescape 
对于放在escape指令中所有的插值而言,这此插值将被自动加上escape表达式,如果需要指定escape指令中某些插值无需添加escape表达式,则应该使用noescape指令,放在noescape指令中的插值将不会添加escape表达式.
 

示例代码:
<#escape x as x?html>
First name:${firstName}
<#noescape>Last name:${lastName}</#noescape>
Maiden name:${maidenName}
</#escape>

 

4.14 noparse 
noparse指令指定FreeMarker不处理该指定里包含的内容。
 

示例代码:
<#noparse>
<#list books as book>
   <tr><td>${book.name}<td>作者:${book.author}
</#list>
</#noparse> 

 

4.15 return 
return指令用于结束macro指令,一旦在macro指令中执行了return指令,则FreeMarker不会继续处理macro指令里的内容

 

示例代码:
<#macro book>
spring
<#return>
j2ee
</#macro>
<@book />
上面的代码输出:spring,而j2ee位于return指令之后,不会输出.

 

4.16 setting 
用来设置整个系统的一个环境。
 

示例代码:
${1.2}
<#setting locale="en_US">
${1.2}
输出
1,2
1.2

 

4.17 switch 
switch , case , default , break这些指令显然是分支指令,作用类似于Java的switch语句

 

示例代码:
<#switch x>
<#case x = 1>
     1
<#case x = 2>
     2
<#default>
     D
</#switch> 
如果x=1 输出 1 2, x=2输出 2, x=3 输出d

 

4.18 字符串处理 
各种处理字符串的方法,有:
html安全输出、substring的用法、类似String.split的用法、取得字符串长度、大写输出字符、小写输出字符、首字符大写、首字符小写、去掉字符串前后空格、每个单词的首字符大写、类似String.indexof:、类似String.lastIndexOf 、替换字符串 replace等 

 

4.19 对象是不是null 
判断对象是不是null

<#if mouse?exists>
       Mouse found
<#else>
也可以直接${mouse?if_exists})输出布尔形

 

五、FreeMarker内建函数

1、获取集合大小

共 ${testList?size} 条记录

 

2、转换JSON字符串为对象

<#assign text="{'bank':'工商银行','account':'10101920201920212'}" />

<#assign data=text?eval />

开户行:${data.bank}  账号:${data.account}

 

3、日期格式化

后台封装数据:

dataModel.put("today", new Date());

freemarker函数:

当前日期:${today?date} <br>
当前时间:${today?time} <br>   
当前日期+时间:${today?datetime} <br>        

日期格式化:  ${today?string("yyyy年MM月")}

 

4、数字转换为字符串

 

后台封装数据:

map.put("point", 102920122);

freemarker函数c:

 

 

我们会发现数字会以每三位一个分隔符显示,有些时候我们不需要这个分隔符,就需要将数字转换为字符串,使用内建函数c

${point?c}

 

六、FreeMarker运算符

1、空值处理运算符

用法为:variable??,如果该变量存在,返回true,否则返回false 

<#if aaa??>
  aaa变量存在
<#else>
  aaa变量不存在
</#if>

 

2、缺失变量默认值:“!”

我们除了可以判断是否为空值,也可以使用!对null值做转换处理

${aaa!'-'}

在代码中不对aaa赋值,也不会报错了 ,当aaa为null则返回!后边的内容-

 

3、算数运算符

逻辑运算符有如下几个: 
逻辑与:&& 
逻辑或:|| 
逻辑非:! 
逻辑运算符只能作用于布尔值,否则将产生错误 

 

4、比较运算符

表达式中支持的比较运算符有如下几个: 
1  =或者==:判断两个值是否相等. 
2  !=:判断两个值是否不等. 
3  >或者gt:判断左边值是否大于右边值 
4  >=或者gte:判断左边值是否大于等于右边值 
5  <或者lt:判断左边值是否小于右边值 
6  <=或者lte:判断左边值是否小于等于右边值 
注意:=和!=可以用于字符串,数值和日期来比较是否相等,但=和!=两边必须是相同类型的值,否则会产生错误,而且FreeMarker是精确比较,"x","x ","X"是不等的.其它的运行符可以作用于数字和日期,但不能作用于字符串,大部分的时候,使用gt等字母运算符代替>会有更好的效果,因为 FreeMarker会把>解释成FTL标签的结束字符,当然,也可以使用括号来避免这种情况,如:<#if (x>y)> 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
毕设新项目-基于Java开发的智慧养老院信息管理系统源码+数据库(含vue前端源码).zip 【备注】 1、该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的,请放心下载使用!有问题请及时沟通交流。 2、适用人群:计算机相关专业(如计科、信息安全、数据科学与大数据技术、人工智能、通信、物联网、自动、电子信息等)在校学生、专业老师或者企业员工下载使用。 3、用途:项目具有较高的学习借鉴价值,不仅适用于小白学习入门进阶。也可作为毕设项目、课程设计、大作业、初期项目立项演示等。 4、如果基础还行,或热爱钻研,亦可在此项目代码基础上进行修改添加,实现其他不同功能。 欢迎下载!欢迎交流学习!不清楚的可以私信问我! 毕设新项目-基于Java开发的智慧养老院信息管理系统源码+数据库(含vue前端源码).zip毕设新项目-基于Java开发的智慧养老院信息管理系统源码+数据库(含vue前端源码).zip毕设新项目-基于Java开发的智慧养老院信息管理系统源码+数据库(含vue前端源码).zip毕设新项目-基于Java开发的智慧养老院信息管理系统源码+数据库(含vue前端源码).zip毕设新项目-基于Java开发的智慧养老院信息管理系统源码+数据库(含vue前端源码).zip毕设新项目-基于Java开发的智慧养老院信息管理系统源码+数据库(含vue前端源码).zip毕设新项目-基于Java开发的智慧养老院信息管理系统源码+数据库(含vue前端源码).zip毕设新项目-基于Java开发的智慧养老院信息管理系统源码+数据库(含vue前端源码).zip毕设新项目-基于Java开发的智慧养老院信息管理系统源码+数据库(含vue前端源码).zip
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值