【学习笔记】初识FreeMarker简单使用

楔子:

   之前在和同事讨论,同事说“jsp技术太古老了,有几种页面技术代替,比如FreeMarker、Velocity、thymeleaf,jsp快废弃了……”云云。我这一听有点心虚……我在后端部分越刨越深,页面装配技术什么的好像只知道有jsp……趁放假自己补补课啦~

简介:

  FreeMarker是一个模板引擎,一个基于模板生成文本输出的通用工具,纯Java编写。类似jsp,简单来讲就是模板加数据模型,然后输出页面。

图片来自尚学堂课件,侵权删

  相对于jsp,FreeMarker的性能略差几十毫秒,但是复杂页面上性能比jsp更佳。

  而且最好的一点,我感觉应该是可以直接把美工写好的html放进模板中使用(无需加jsp头等),FreeMarker自带的一些标签用着也很简单。FreeMarker的模板文件格式为ftl,也可以直接用html

  FreeMarker可以应用更多的场景,与容器无关;而jsp要求有JVM环境,只能应用于web应用中。

HelloWorld:

  第一个FreeMarker代码

新建一个Java project,起名为 FreeMarker,在src外部新建一个文件夹命名为templates,如图:

在templates中新建一个file,命名为first.ftl,添加如下代码(其中的表达式类似于EL表达式):

hello,${user},这是你的第一个FreeMarker程序!

下载FreeMarker.jar并引入项目

新建FirstFreeMarker类,代码如下:

 1 package com.hellxz;
 2
 3 import java.io.File;
 4 import java.io.IOException;
 5 import java.io.OutputStreamWriter;
 6 import java.io.Writer;
 7 import java.util.HashMap;
 8 import java.util.Map;
 9
10 import freemarker.template.Configuration;
11 import freemarker.template.Template;
12 import freemarker.template.TemplateException;
13
14 /**
15  * 第一个FreeMarker程序
16  *
17  * @author hellxz
18  */
19 public class FirstFreeMarker {
20
21     @SuppressWarnings({"rawtypes","unchecked"})
22     public static void main(String[] args) throws IOException, TemplateException {
23         // 创建Freemarker配置实例
24         Configuration cfg = new Configuration();
25         cfg.setDirectoryForTemplateLoading(new File("templates"));
26
27         // 创建数据模型
28         Map root = new HashMap();
29         root.put("user", "老张");
30
31         // 加载模板文件
32         Template t1 = cfg.getTemplate("first.ftl");
33
34         // 显示生成的数据,将合并后的数据打印到控制台
35         Writer out = new OutputStreamWriter(System.out);
36         t1.process(root, out);
37         out.flush();
38         out.close();
39
40     }
41
42 }

运行代码,查看输出:

hello,老张,这是你的第一个FreeMarker程序!

测试举例:

本例子基本涵盖了大部分FreeMarker特有的属性,参考Java语言不同点写就,相同点并没有测试。通过观察代码可以很清晰的看出这些函数、指令的使用方法

新建一个Address类:

 1 package com.hellxz;
 2
 3 /**
 4  * 地址
 5  *
 6  * @author hellxz
 7  */
 8 public class Address {
 9
10     private String country; // 国家
11     private String city; // 城市
12
13     //getters & setters
14     public String getCountry() {
15         return country;
16     }
17
18     public void setCountry(String country) {
19         this.country = country;
20     }
21
22     public String getCity() {
23         return city;
24     }
25
26     public void setCity(String city) {
27         this.city = city;
28     }
29
30     public Address(String country, String city) {
31         this.country = country;
32         this.city = city;
33     }
34 }

新建一个TestFreeMarker类,代码如下:

 1 package com.hellxz;
 2
 3 import java.io.File;
 4 import java.io.IOException;
 5 import java.io.OutputStreamWriter;
 6 import java.io.Writer;
 7 import java.util.ArrayList;
 8 import java.util.HashMap;
 9 import java.util.Map;
10 import java.util.Random;
11
12 import freemarker.template.Configuration;
13 import freemarker.template.Template;
14 import freemarker.template.TemplateException;
15
16 /**
17  * FreeMarker Test
18  *
19  * @author hellxz
20  */
21 public class TestFreeMarker {
22
23     @SuppressWarnings({ "rawtypes", "unchecked" })
24     public static void main(String[] args) throws IOException, TemplateException {
25         //1.创建配置文件
26         Configuration conf = new Configuration();
27         //2.设置模板目录
28         conf.setDirectoryForTemplateLoading(new File("templates"));
29         //3.数据模型
30         Map<String,Object> map = new HashMap<>();
31         map.put("user", "老张");
32         map.put("random",new Random().nextInt(100));
33         //新建一个list放入map中,用于测试遍历list操作
34         ArrayList list = new ArrayList();
35         list.add(new Address("中国","上海"));
36         list.add(new Address("日本","东京"));
37         map.put("list", list);
38         //测试内建函数
39         map.put("html5", "<b>大写的文字</b>");
40         map.put("name", "hellxz");
41         map.put("upper", "ABCDEF");
42         //4.获取模板文件
43         Template template = conf.getTemplate("a.ftl");
44         //5.输出流
45         Writer out = new OutputStreamWriter(System.out);
46         //6.生成文件流输出
47         template.process(map, out);
48         out.flush();
49         out.close();
50     }
51 }

在templates文件夹下新建a.ftl

  1 hello,${user},今天看起来很精神嘛!
  2 ----------------------------------
  3 if分支语句测试:
  4 <#if user=="老张">
  5         老张!
  6 </#if>
  7 ----------------------------------
  8 if else 分支测试:
  9 <#if user=="老李">
 10         老李
 11 <#else>
 12         老张
 13 </#if>
 14 ----------------------------------
 15 if else if else 测试:
 16 因为大于小于号等会被转义,使用简写代替比较符号
 17 gt(great than的简写) 代替 >
 18 lt(less than的简写) 代替 <
 19 gte(great than equal的简写) 代替 >=
 20 lte (less than equal的简写) 代替 <=
 21 <#if random gt 80>
 22         优秀
 23 <#elseif random gt 60>
 24         及格
 25 <#else>
 26         不及格
 27 </#if>
 28 ----------------------------------
 29 遍历list测试:
 30 <#list list as addr>
 31         ${addr.country} ${addr.city}
 32 </#list>
 33 ----------------------------------
 34 include包含测试:
 35 <#include "include.txt"/>
 36 ----------------------------------
 37 macro无参函数(宏函数)测试:
 38 定义函数:
 39 <#macro m1>
 40     我是函数内容
 41 </#macro>
 42 调用函数测试:
 43 <@m1/><@m1/><#--这是注释内容:这里调用了两次函数-->
 44 ----------------------------------
 45 macro带参函数<#--(格式为"<#macro 函数名 [变量1 变量2 变量3 ……] </#macro>")-->:
 46 <#macro cc a b c>
 47     ${a}/${b}/${c}
 48 </#macro>
 49 调用测试<#--(格式为:"<@函数名 [变量1值 变量2值 变量3值 ……] </#macro>")-->:
 50 <@cc "中" "明" "月"/>
 51 ----------------------------------
 52 nested测试:
 53 用于一大段代码的嵌入
 54 <#macro border>
 55     <html>
 56         <head>
 57             <body>
 58                 <#nested/>
 59             </body>
 60         </head>
 61     </html>
 62 </#macro>
 63 向nested部分添加内容:
 64 <@border>
 65                 <h1>我是nested的内容</h1>
 66 </@border>
 67 ----------------------------------
 68 测试命名空间:
 69 <#import "b.ftl" as bb  />
 70 <@bb.copyright date="2010-2011" />
 71 ${bb.mail}
 72 <#assign mail="[email protected]"  />
 73 ${mail}
 74 <#assign mail="[email protected]" in bb  />
 75 ${bb.mail}
 76 -----------------------------------
 77 声明、指定变量assign:
 78 测试数据类型:
 79 <#assign ss="hellxz"/>
 80 文本型:${ss}
 81 <#assign s1=1 />
 82 数值型:${s1}
 83 <#assign s2=true/>
 84 布尔型:<#if s2>布尔型</#if>
 85 -------------------------------------
 86 字符串常见内建函数:
 87 html转义:${html5?html}
 88 cap_first(首字母大写):${name?cap_first}
 89 upper_case(转大写):${name?upper_case}
 90 lower_case(转小写):${upper?lower_case}
 91 数值常见内建函数:
 92 int(取整数部分)
 93 集合内建函数:
 94 size(取集合大小)
 95 ------------------------------------
 96 字符串空值处理:
 97 FreeMarker不支持空值,如果为空直接报错
 98 没有定义直接引用
 99 <#-- ${sss} 直接报错了-->
100 空值处理:
101 ${sss!}<#-- 为空则输出空字符串 -->
102 ${sss!"default"} <#--设置默认值,为空自动使用-->
103 ------------------------------------------
104 ??布尔值处理
105 <#if user??>
106 如果该值存在,返回true,相当于 if user != null
107 <#else>
108 该值不存在返回false
109 </#if>

新建b.ftl 用于测试命名空间

1 <#macro copyright date>
2   <p>Copyright (C) ${date} 北京尚学堂.</p>
3 </#macro>
4 <#assign mail = "[email protected]">

在templates下新建include.txt,用于测试include指令

我是被包含的内容!

运行TestFreeMarker,查看输出(这里为了方便比较,加上行号):

 1 hello,老张,今天看起来很精神嘛!
 2 ----------------------------------
 3 if分支语句测试:
 4         老张!
 5 ----------------------------------
 6 if else 分支测试:
 7         老张
 8 ----------------------------------
 9 if else if else 测试:
10 因为大于小于号等会被转义,使用简写作为比较符号
11 gt=great than = >
12 lt=less than = <
13 gte = great than equal = >=
14 lte = less than equal = <=
15         及格
16 ----------------------------------
17 遍历list测试:
18         中国 上海
19         日本 东京
20 ----------------------------------
21 include包含测试:
22 我是被包含的内容!
23 ----------------------------------
24 macro无参函数(宏函数)测试:
25 定义函数:
26 调用函数测试:
27     我是函数内容
28     我是函数内容
29 ----------------------------------
30 macro带参函数:
31 调用测试:
32     中/明/月
33 ----------------------------------
34 nested测试:
35 用于一大段代码的嵌入
36 向nested部分添加内容:
37     <html>
38         <head>
39             <body>
40                 <h1>我是nested的内容</h1>
41             </body>
42         </head>
43     </html>
44 ----------------------------------
45 测试命名空间:
46   <p>Copyright (C) 2010-2011 北京尚学堂.</p>
47 [email protected].com
48 [email protected].com
49 [email protected].com
50 -----------------------------------
51 声明、指定变量assign:
52 测试数据类型:
53 文本型:hellxz
54 数值型:1
55 布尔型:布尔型
56 -------------------------------------
57 字符串常见内建函数:
58 html转义:&lt;b&gt;大写的文字&lt;/b&gt;
59 cap_first(首字母大写):Hellxz
60 upper_case(转大写):HELLXZ
61 lower_case(转小写):abcdef
62 数值常见内建函数:
63 int(取整数部分)
64 集合内建函数:
65 size(取集合大小)
66 ------------------------------------
67 字符串空值处理:
68 FreeMarker不支持空值,如果为空直接报错
69 没有定义直接引用
70 空值处理:
71
72 default
73 ------------------------------------------
74 ??布尔值处理
75 如果该值存在,返回true,相当于 if user != null

看了一下漏了一个日期处理,这里补一下:

map.put("date", new Date());

a.ftl中模板写法:

${date?string("yyyy-MM-dd HH:mm:ss")}

输出:

2018-02-18 16:18:10

字符串连接
字符串连接有两种语法:
(1) 使用${..}或#{..}在字符串常量内插入表达式的值;
(2)  直接使用连接运算符“+”连接字符串。
如,下面两种写法等效:
              ${"Hello, ${user}"}                                                                                                               
              ${"Hello, " + user + "!"}                                                                                                        
有一点需要注意: ${..}只能用于文本部分作为插值输出,而不能用于比较等其他用途,如:
              <#if ${isBig}>Wow!</#if>                                                                                                               
              <#if "${isBig}">Wow!</#if>                                                                                                             
应该写成:
              <#if isBig>Wow!</#if>

截取子串
截取子串可以根据字符串的索引来进行,如果指定一个索引值,则取得字符串该索引处的字符;如果指定两个索引值,则截取两个索引中间的字符串子串。如:
              <#assign number="01234">
              ${number[0]} <#-- 输出字符0 -->
              ${number[0..3]} <#-- 输出子串“0123” -->

本文为FreeMarker简单的语法使用,servlet以及struts部分见下篇博客

原文地址:https://www.cnblogs.com/hellxz/p/8452880.html

时间: 2024-08-30 11:59:33

【学习笔记】初识FreeMarker简单使用的相关文章

RTX51 Tiny实时操作系统学习笔记—初识RTX51 Tiny

 一,RTX51 Tiny简单介绍 RTX51 Tiny是一种实时操作系统(RTOS),能够用它来建立多个任务(函数)同一时候运行的应用(从宏观上看是同一时候运行的,但从微观上看,还是独立运行的).嵌入式应用系统常常有这样的需求.RTOS能够提供调度.维护.同步等功能. 实时操作系统能灵活的调度系统资源,像CPU和存储器,而且提供任务间的通信.RTX51 Tiny是一个功能强大的RTOS,且易于使用,它用于8051系列的微控制器.该RTOS最多支持16个任务,基于RTX51 Tiny构建的应用程

capwap学习笔记&mdash;&mdash;初识capwap(四)

2.5.7 CAPWAP传输机制 WTP和AC之间使用标准的UDP客户端/服务器模式来建立通讯. CAPWAP协议支持UDP和UDP-Lite [RFC3828]. ¢ 在IPv4上,CAPWAP控制和数据通道使用UDP.此时CAPWAP报文中的UDP校验和必须设置为0.AC上的CAPWAP控制报文端口为UDP众所周知端口5246,数据报文端口为UDP众所周知端口5247 ,WTP可以随意选择CAPWAP控制和数据端口. ¢ 在IPv6上,CAPWAP控制通道一般使用UDP,而数据通道可以使用U

capwap学习笔记&mdash;&mdash;初识capwap(五)

3. CAPWAP Binding for IEEE 802.11 ¢ CAPWAP协议本身并不包括任何指定的无线技术.它依靠绑定协议来扩展对特定无线技术的支持. ¢ RFC5416就是用来扩展CAPWAP对IEEE 802.11网络的支持.其中定义了控制消息字段,新的控制消息,消息元素. ¢ 注意,这个协议仅支持IEEE 802.11-2007规范,并不支持IEEE 802.11-2007 standard中定义的ad hoc网络模式(即点到点模式,也就是IBSS),也不适用于four-add

[简明python教程]学习笔记之编写简单备份脚本

[[email protected] 0503]# cat backup_ver3.py #!/usr/bin/python #filename:backup_ver3.py import os import time #source source=['/root/a.sh','/root/b.sh','/root/c.sh'] #source='/root/c.sh' #backup dir target_dir='/tmp/' today=target_dir+time.strftime('

StyleCop学习笔记——初识StyleCop

一.定义 StyleCop是微软的一个开源的静态代码分析工具,检查c#代码一致性和编码风格. 二.支持的环境. JetBrains R# 5.1.3 ( 5.1.3000.12) JetBrains R# 6.0 (6.0.2202.688) JetBrains R# 6.1 (6.1.37.86) JetBrains R# 6.1.1 (6.1.1000.82) JetBrains R# 7.0.1 (7.0.1098.2760) JetBrains R# 7.1.3 (7.1.3000.22

capwap学习笔记&mdash;&mdash;初识capwap(二)

2.5.1 AC发现机制 WTP使用AC发现机制来得知哪些AC是可用的,决定最佳的AC来建立CAPWAP连接. WTP的发现过程是可选的.如果在WTP上静态配置了AC,那么WTP并不需要完成AC的发现过程. WTP首先发送一个 Discovery Request message给受限的广播地址,或者CAPWAP的多播地址(224.0.1.140),或者是预配置的AC的单播地址.在IPV6网络中,由于广播并不存在,因此使用"All ACs multicast address" (FF0X

capwap学习笔记&mdash;&mdash;初识capwap(一)

2 初识CAPWAP 2.1 CAPWAP简介 说了半天CAPWAP,连全称都还没说,汗-- CAPWAP--Control And Provisioning of Wireless Access Points Protocol Specification.其由两个部分组成:CAPWAP协议和无线BINDING协议. 前者是一个通用的隧道协议,完成AP发现AC等基本协议功能,和具体的无线接入技术无关.后者是提供具体和某个无线接入技术相关的配置管理功能.这么说吧,前者规定了各个阶段需要干什么事,后

capwap学习笔记&mdash;&mdash;初识capwap(三)

2.5.6 CAPWAP状态机详解 2.5.6.1 Start to Idle 这个状态变迁发生在设备初始化完成. ¢  WTP: 开启CAPWAP状态机. ¢  AC:  开启CAPWAP状态机. 2.5.6.2 Idle to Discovery 这个状态变迁发生是为了支持CAPWAP发现进程. ¢   WTP: WTP进入发现状态是为了优先去传输第一个Discovery Request message.在进入这个状态之前,WTP设置发现DiscoveryInterval timer,将Di

《大话设计模式》学习笔记系列--1. 简单工厂模式

简单工厂模式实现了一种"工厂"概念的面向对象设计模式,它可以在不指定对象具体类型的情况下创建对象.其实质是定义一个创建对象的接口,但让实现这个接口的类来决定实例化具体类.工厂方法让类的实例化推迟到子类中进行. 以书本上的计算器程序为例,其UML描述如下: 图中,AddOperator, SubtactOpertor继承算式基类Operator,而CreateOperator则是负责创建一个操作类,而不指明具体的子类类型. 下面,我们来看代码: 首先操作积累: /// <summa