Freemarker语法

FreeMarker 是一款 模板引擎: 即一种基于模板和要改变的数据, 并用来生成输出文本(HTML网页,电子邮件,配置文件,源代码等)的通用工具。 它不是面向最终用户的,而是一个Java类库,是一款程序员可以嵌入他们所开发产品的组件。

特点

1. 轻量级模版引擎,不需要Servlet环境就可以很轻松的嵌入到应用程序中

2. 能生成各种文本,如html,xml,java,等

3. 入门简单,它是用java编写的,很多语法和java相似

freemarker模板文件(*.ftl)的基本组成部分:

1. 文本:直接输出的内容部分

2. 注释:会被FreeMarker直接忽略, 更不会在输出内容中显示,格式为<#--  注释内容  -->

3. 取值(插值):这部分的输出会被计算的值来替换,格式为   ${数据模型}   或   #{数据模型}(这种风格已经不建议使用)

4. ftl指令:Freemarker指令,类似于HTML标签,但是它们却是给FreeMarker的指示, 而且不会打印在输出内容中( 至于什么是内建指令,什么是自定义指令   下面会叙述到)

    • 内建指令:开始标签:<#directivename parameter>       结束标签:</#directivename>      空标签:<#directivename parameter/>   
    • 自定义指令:开始标签:<@directivename parameter>       结束标签:</@directivename>      空标签:<@directivename parameter/> 
文本, 插值, FTL 标签, 注释
<html> <head>  <title>Welcome!</title> </head> <body> <#-- Greet the user with his/her name --> <h1>Welcome ${user}!</h1> <p>We have these animals: <ul> <#list animals as animal> <li>${animal.name} for ${animal.price} Euros </#list> </ul> </body> </html>

 注意:

  • FTL是区分大小写的。 list 是指令的名称而 List 就不是。类似地 ${name} 和 ${Name} 或 ${NAME} 也是不同的。
  • 请注意非常重要的一点: 插值 仅仅可以在 文本 中使用。
  • FTL 标签 不可以在其他 FTL 标签 和 插值中使用。比如, 这样做是 错误 的: <#if <#include 'foo'>='bar'>...</#if>
  • 注释 可以放在 FTL 标签 和 插值中。
<h1>Welcome ${user <#-- The name of user -->}!</h1>
<p>We have these animals:
<ul>
<#list <#-- some comment... --> animals as <#-- again... --> animal>

工作原理:(借用网上的图片)                 

语法及使用方法:

数据类型

和java不同,FreeMarker不需要定义变量的类型,直接赋值即可。

字符串: value = "xxxx" 。如果有特殊字符 string = r"xxxx" 。单引号和双引号是一样的。

数值:value = 1.2。数值可以直接等于,但是不能用科学计数法。

布尔值:true or  false。

List集合:list = [1,2,3] ; list=[1..100] 表示 1 到 100 的集合,反之亦然。

Map集合:map = {"key" : "value" , "key2" : "value2"},key 必须是字符串哦!

实体类:和EL表达式差不多,直接点出来。

字符串操作

字符串连接:可以直接嵌套${"hello , ${name}"} ; 也可以用加号${"hello , " + name}

字符串截取:string[index]。index 可以是一个值,也可以是形如 0..2 表示下标从0开始,到下标为2结束。一共是三个数。

比较运算符

== (等于),!= (不等于),gt(大于),gte(大于或者等于),lt(小于),lte(小于或者等于)。不建议用 >,<  可能会报错!

一般和 if 配合使用

变量空判断

 !    指定丢失变量的默认值;一般配置变量输出使用。 对表达式自动检查 null 值和空字符串

Invoice Date: ${(customer.invoice.date)!}
//如果 customer、invoice 或者 date 中有一个为空值或空字符串,你只会得到标签:
Invoice Date:

Invoice Date: ${(customer.invoice.date)!'No Invoice Available'}
//如果所有值丢失,你会得到:
Invoice Date: No Invoice Available

??    判断变量是否存在。一般配合if使用 <#if value??></#if>

支持 JSON

FreeMarker 内置 JSON 支持。 比方说你有以下的 JSON 存储到变量命名 user 的字符串中。

{ 'firstName': 'John', 'lastName': 'Smith', 'age': 25, 'address': { 'streetAddress': '21 2nd Street', 'city': 'New York', 'state': 'NY', 'postalCode': 10021 }}

使用 ?eval 将从字符串转换为一个 JSON 对象,然后像其他数据一样在表达式中使用。

<#assign user = user?eval>
User: ${user.firstName}, ${user.address.city}

 取值(插值)指令及适用类型:

 ${var}  适用类型:java中常用的八大基本类型以及我们的String引用类型,但是,freemarker中boolean类型显示时true==yes  false==no

//在后台文件中定义变量
String strVar = "世界你好";
int intVar = 10;
boolean booVar = true;
//在页面中获取变量:
<font color="red"> ${strVar} </font><br>            //String获取
<font color="red"> ${intVar} </font><br>           //int获取
<font color="red"> ${booVar?string("yes","no")} </font>  //boolean获取
//展示结果:String获取:世界你好  int获取:10  boolean获取:yes

 ${var!}   适用类型:对 null 或者不存在的对象进行取值,可以设置默认值,例:${var!'我是默认值'}    即,有值时显示正常值,无值时显示默认值

//在后台文件中定义变量
String strVar = "世界你好";
String str = null;
//在页面中获取变量:
<font color="red"> ${strVar!"我是空"} </font><br> //String获取
<font color="red"> ${str!} </font><br>//str获取
<font color="red"> ${str!"默认"} </font><br>//str获取
//展示结果:String获取:世界你好  str获取:  str获取:默认

 ${封装对象.属性}   适用类型:对封装对象进行取值,例:${User.name}

//在后台文件中封装对象User[ name,  age ]
String name = "姓名";
int age = 18;
//在页面中获取变量:
<font color="red"> ${User.name} </font><br>//name获取
<font color="red"> ${User.age} </font><br>//age获取
//展示结果:name获取:姓名    age获取:18

${date?String('yyyy-MM-dd')}  适用类型:对日期格式进行取值,要强调的是,定义Date类型的变量时,java.util.Date无法输出日期,须使用java.sql.Date

//在后台文件中定义变量
java.sql.Date date = new Date().getTime();
java.sql.Date time = new Date().getTime();
java.sql.Date datetime = new Date().getTime();
//在页面中获取变量:
<font color="red"> ${date?string('yyyy-MM-dd')} </font><br>//date获取
<font color="red"> ${date?string('HH:mm:ss')} </font><br>//time获取
<font color="red"> ${date?string('yyyy-MM-dd HH:mm:ss')} </font><br>//datetime获取
//展示结果:未给出

${var?html}  适用类型:转义HTML内容

//在后台文件中封装变量Menu[ name, model ]
Menu m = new Menu(); 
m.setName(" freemarker ");
m.setModel("<font color = 'red'>我只是个菜单</font>");
//在页面中获取变量:
<font color="red"> ${m.model} </font><br>//非转义获取:
${m.model?html} </font><br>//转义获取:
//展示结果:
//非转义获取:我只是个菜单
//转义获取:<font color = 'red'>我只是个菜单</font>

<#assign num = 100 />  适用类型:定义变量,支持计算和赋值

//在页面中定义变量:
<#assign num = 100 />
//在页面中获取变量
<font color="red"> ${num)} </font><br>// num获取:
<font color="red"> ${num * 10} </font><br>//计算结果:
//展示结果:num获取:100    计算结果:1000

对List集合进行取值
  <#list  list集合  as  item> 
    ${item}    --取值
  </#list>

//在后台文件中定义变量
List<String> strList = new ArrayList<String>();
strList.add("第一个值");
strList.add("第二个值");
strList.add("第三个值");
//在页面中获取变量:
<#list  strList  as  item> 
  ${item!}<br/>    //取值
</#list>
//展示结果:
//第一个值
//第二个值
//第三个值   

对Map集合进行取值
  <#list map?keys as key>
    ${key}:${map[key]}
  </#list>

//在后台文件中定义变量
Map<String, Object> m = new HashMap<String, Object>();
m.put("name","姓名");
m.put("age",18);
m.put("sex","男");
//在页面中获取变量:
<#list m?keys as key>
    ${key}:${m[key]}
</#list>
// 展示结果:
//name:姓名
//age:18
//sex:男

  条件判断指令:                                

 <#if 条件>输出</#if>

//在页面中定义变量并判断条件:
<#assign age = 18 /><br>
<#if age == 18>
    <font color="red"> age = 18</font>
</#if>
//展示结果: age = 18

<#if 条件>  输出 <#else> 输出 </#if>

//在页面中定义变量并判断条件:
<#assign age = 20 /><br>
<#if age == 18>
  <font color="red"> age = 18</font>
<#else>
  <font color="red"> age != 18</font>
</#if>
//展示结果: age != 18

<#if 条件1> 输出 <#elseif 条件2> 输出 <#else> 输出 </#if>

 //在页面中定义变量并判断条件:
<#assign age = 20 /><br>
<#if age &gt; 18>
  <font color="red">青年</font>
<#elseif age == 18>
  <font color="red"> 成年</font>
<#else>
  <font color="red"> 少年</font>
</#if>
//展示结果:成年

switch  --常与case break default一起使用  参数可为字符串

//在页面中定义变量并判断:
<#switch var="星期一">
<#case "星期一">
  油焖大虾
<#break>
<#case "星期二">
  炸酱面
<#break>
<#default>
  肯德基
</#switch>
//展示结果: 油焖大虾 

自定义函数、自定义指令:               

(1) 自定义函数 —— 实现TemplateMthodModelEx
(2) 自定义指令 —— 实现TemplateDirectiveModel

<@自定义指令名称 入参(key-value格式) ; 出参(list格式)>
  运行条件
</@自定义指令名称>
注意,不同的返回值用逗号( , )间隔开  
<@mydirective parameters>...</@mydirective>//对于用户自定义的指令,如果指令没有嵌套内容,那么必须这么使用 
<@mydirective parameters />

常用内建函数、macro(宏指令)、function(函数指令):               

(1) 常用内建函数
     

处理字符串

html

对字符串进行HTML编码

substring

截取字符串,包头不包尾(下标)

cap_first

 第一个字母大写 

lower_case

将字符串转成小写

upper_case

将字符串转成大写

end_with     

以什么字母结尾    

contains              

是否包含目标字符串

date  datetime  time          

转换成日期格式

starts_with   

以什么字母开头

index_of             

返回某个指定的字符串值在字符串中首次出现的位置(下标)

last_index_of                  

获取指定字符出现的最后位置(下标)

split    

分隔

trim 

去两端空格

size

获得集合中元素的个数

int

取得数字的整数部分

处理数字

string x?string("0.##")    

变成小数点后几位

round 

四舍五入

floor    

去掉小数点

ceiling 

近1   变成整数

处理list

first

取List值第一个值

last

取List值最后一个值

seq_contains

是否包含指定字符

seq_index_of

 指定字符所在位置

size

集合大小

reverse

集合倒序排列

sort

对集合进行排序

sort_by

根据某一个属性排序

chunk

 分块处理

其他

is_string:      

是否为字符类型

is_number:   

是否为整数类型

is_method:  

是否为方法

(): 

判断整个变量

has_content:     

判断对象是否为空或不存在

eval:

求值

(2) macro(宏指令)

     可以理解为java的封装方法,供其他地方使用。宏指令也称为自定义指令,macro指令

     调用:<@macro_name param />
     语法:<#macro  变量名  参数>  
                  <#nested/>  
               </#macro>

     使用:<@变量名  />


(3) function(函数指令)
     调用:${function_name(param)}
     语法:<#function  变量名  参数>  
                      <#return>  
                </#function>

FreeMarker 程序

通过模拟简单的代码自动生产工具来感受第一个FreeMarker程序。

项目目录结构:

项目创建流程:

第一步:创建一个maven项目导入 FreeMarker jar 包

第二步:创建目录templates,并创建一个 FreeMarker模版文件 hello.ftl

第三步:创建一个运行FreeMarker模版引擎的 FreeMarkerDemo.java 文件

第四步:运行main方法后刷新项目

pom.xml 文件 ,maven 项目核心文件,管理 jar 包。

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.freemark</groupId>
    <artifactId>freemarkerStudy</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>war</packaging>

    <dependencies>
        <dependency>
            <groupId>org.freemarker</groupId>
            <artifactId>freemarker</artifactId>
            <version>2.3.20</version>
        </dependency>
    </dependencies>
    
</project>

 hello.ftl  FreeMarker基本语法: ${xxx} xxx 相当于占位符,java后台给xxx赋值后,再通过${}输出

package ${classPath};
public class ${className} {  
    public static void main(String[] args) {
        System.out.println("${helloWorld}");
    }
}

FreeMarkerDemo.java 核心方法,使用 FreeMarker 模版引擎。

package com.freemark.hello;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileOutputStream;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.util.HashMap;
import java.util.Map;
import freemarker.template.Configuration;
import freemarker.template.Template;

/**
 * 最常见的问题: 
 *     java.io.FileNotFoundException: xxx does not exist. 解决方法:要有耐心
 *     FreeMarker jar 最新的版本(2.3.23)提示 Configuration 方法被弃用
 * 代码自动生产基本原理:
 *     数据填充 freeMarker 占位符
 */
public class FreemarkerDemo {
    
    private static final String TEMPLATE_PATH = "src/main/java/com/freemark/hello/templates";
    private static final String CLASS_PATH = "src/main/java/com/freemark/hello";
    
    public static void main(String[] args) {
        // step1 创建freeMarker配置实例
        Configuration configuration = new Configuration();
        Writer out = null;
        try {
            // step2 获取模版路径
            configuration.setDirectoryForTemplateLoading(new File(TEMPLATE_PATH));
            // step3 创建数据模型
            Map<String, Object> dataMap = new HashMap<String, Object>();
            dataMap.put("classPath", "com.freemark.hello");
            dataMap.put("className", "AutoCodeDemo");
            dataMap.put("helloWorld", "通过简单的 <代码自动生产程序> 演示 FreeMarker的HelloWorld!");
            // step4 加载模版文件
            Template template = configuration.getTemplate("hello.ftl");
            // step5 生成数据
            File docFile = new File(CLASS_PATH + "\" + "AutoCodeDemo.java");
            out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(docFile)));
            // step6 输出文件
            template.process(dataMap, out);
            System.out.println("^^^^^^^^^^^^^^^^^^^^^^^^AutoCodeDemo.java 文件创建成功 !");
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                if (null != out) {
                    out.flush();
                }
            } catch (Exception e2) {
                e2.printStackTrace();
            }
        }
    }
}

 运行程序后刷新项目,会发现多了java类,xml。通过FreeMarker做了一个简易的工具类,公司的一个标准管理页面及其增删改查等功能,以及相关的配置文件(十三个文件),一个回车就全部自动生成(偷懒ing)。

FreeMarker Web

这里是和SpringMVC整合的,SpringMVC的配置就不多说了,源码地址:https://gitee.com/itdragon/springmvc

//导入相关的jar   pom.xml
<dependency>
  <groupId>org.freemarker</groupId>
  <artifactId>freemarker</artifactId>
  <version>2.3.20</version>
</dependency>
<dependency>
  <groupId>org.springframework</groupId>
  <artifactId>spring-context-support</artifactId>
  <version>4.1.4.RELEASE</version>
</dependency>

//springmvc的配置文件
<!-- 整合Freemarker -->
    <!-- 放在InternalResourceViewResolver的前面,优先找freemarker -->  
    <bean id="freemarkerConfig" class="org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer">  
        <property name="templateLoaderPath" value="/WEB-INF/views/templates"/>  
    </bean>  
    <bean id="viewResolver" class="org.springframework.web.servlet.view.freemarker.FreeMarkerViewResolver">  
        <property name="prefix" value=""/>  
        <property name="suffix" value=".ftl"/>  
        <property name="contentType" value="text/html; charset=UTF-8"/>
    </bean>

//Controller 层
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller
public class HelloFreeMarkerController {   
    @RequestMapping("/helloFreeMarker")
    public String helloFreeMarker(Model model) {
        model.addAttribute("name","ITDragon博客");  
        return "helloFreeMarker";
    }
}

//Freemarker文件
<html>  
<head>  
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">  
<title>FreeMarker Web</title>  
</head>  
<body>  
    <h1>Hello ${name} !</h1>  
</body>  
</html>

小结

  1. 知道了FreeMarker是一块模版引擎,可以生产xml,html,java等文件

  2. 知道了FreeMarker文件提供占位符,java文件提供数据,通过FreeMarker模版引擎生产有数据的页面,文中将数据放在Map中。web应用可以用setter/getter 方法

  3. 知道了FreeMarker语法中字符串的显示特殊字符,截取的操作。以及一些内置方法的使用

  4. 重点了解FreeMarker的空判断知识点。判断变量是否为空用 "??" ,如果变量为空设置默认值。如果不注意空问题,可能会出现黄色页面的提示哦!

  5. FreeMarker的宏概念,命名空间,引入文件,给变量赋值,集合的遍历等。

  6. Freemarker 整合SpringMVC。

原文地址:https://www.cnblogs.com/whatarewords/p/10937266.html