【学习笔记】初识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类,代码如下:
package com.hellxz; import java.io.File; import java.io.IOException; import java.io.OutputStreamWriter; import java.io.Writer; import java.util.HashMap; import java.util.Map; import freemarker.template.Configuration; import freemarker.template.Template; import freemarker.template.TemplateException; /** * 第一个FreeMarker程序 * * @author hellxz */ public class FirstFreeMarker { @SuppressWarnings({"rawtypes","unchecked"}) public static void main(String[] args) throws IOException, TemplateException { // 创建Freemarker配置实例 Configuration cfg = new Configuration(); cfg.setDirectoryForTemplateLoading(new File("templates")); // 创建数据模型 Map root = new HashMap(); root.put("user", "老张"); // 加载模板文件 Template t1 = cfg.getTemplate("first.ftl"); // 显示生成的数据,将合并后的数据打印到控制台 Writer out = new OutputStreamWriter(System.out); t1.process(root, out); out.flush(); out.close(); } }
运行代码,查看输出:
hello,老张,这是你的第一个FreeMarker程序!
测试举例:
本例子基本涵盖了大部分FreeMarker特有的属性,参考Java语言不同点写就,相同点并没有测试。通过观察代码可以很清晰的看出这些函数、指令的使用方法
新建一个Address类:
package com.hellxz; /** * 地址 * * @author hellxz */ public class Address { private String country; // 国家 private String city; // 城市 //getters & setters public String getCountry() { return country; } public void setCountry(String country) { this.country = country; } public String getCity() { return city; } public void setCity(String city) { this.city = city; } public Address(String country, String city) { this.country = country; this.city = city; } }
新建一个TestFreeMarker类,代码如下:
package com.hellxz; import java.io.File; import java.io.IOException; import java.io.OutputStreamWriter; import java.io.Writer; import java.util.ArrayList; import java.util.HashMap; import java.util.Map; import java.util.Random; import freemarker.template.Configuration; import freemarker.template.Template; import freemarker.template.TemplateException; /** * FreeMarker Test * * @author hellxz */ public class TestFreeMarker { @SuppressWarnings({ "rawtypes", "unchecked" }) public static void main(String[] args) throws IOException, TemplateException { //1.创建配置文件 Configuration conf = new Configuration(); //2.设置模板目录 conf.setDirectoryForTemplateLoading(new File("templates")); //3.数据模型 Map<String,Object> map = new HashMap<>(); map.put("user", "老张"); map.put("random",new Random().nextInt(100)); //新建一个list放入map中,用于测试遍历list操作 ArrayList list = new ArrayList(); list.add(new Address("中国","上海")); list.add(new Address("日本","东京")); map.put("list", list); //测试内建函数 map.put("html5", "<b>大写的文字</b>"); map.put("name", "hellxz"); map.put("upper", "ABCDEF"); //4.获取模板文件 Template template = conf.getTemplate("a.ftl"); //5.输出流 Writer out = new OutputStreamWriter(System.out); //6.生成文件流输出 template.process(map, out); out.flush(); out.close(); } }
在templates文件夹下新建a.ftl
hello,${user},今天看起来很精神嘛! ---------------------------------- if分支语句测试: <#if user=="老张"> 老张! </#if> ---------------------------------- if else 分支测试: <#if user=="老李"> 老李 <#else> 老张 </#if> ---------------------------------- if else if else 测试: 因为大于小于号等会被转义,使用简写代替比较符号 gt(great than的简写) 代替 > lt(less than的简写) 代替 < gte(great than equal的简写) 代替 >= lte (less than equal的简写) 代替 <= <#if random gt 80> 优秀 <#elseif random gt 60> 及格 <#else> 不及格 </#if> ---------------------------------- 遍历list测试: <#list list as addr> ${addr.country} ${addr.city} </#list> ---------------------------------- include包含测试: <#include "include.txt"/> ---------------------------------- macro无参函数(宏函数)测试: 定义函数: <#macro m1> 我是函数内容 </#macro> 调用函数测试: <@m1/><@m1/><#--这是注释内容:这里调用了两次函数--> ---------------------------------- macro带参函数<#--(格式为"<#macro 函数名 [变量1 变量2 变量3 ……] </#macro>")-->: <#macro cc a b c> ${a}/${b}/${c} </#macro> 调用测试<#--(格式为:"<@函数名 [变量1值 变量2值 变量3值 ……] </#macro>")-->: <@cc "中" "明" "月"/> ---------------------------------- nested测试: 用于一大段代码的嵌入 <#macro border> <html> <head> <body> <#nested/> </body> </head> </html> </#macro> 向nested部分添加内容: <@border> <h1>我是nested的内容</h1> </@border> ---------------------------------- 测试命名空间: <#import "b.ftl" as bb /> <@bb.copyright date="2010-2011" /> ${bb.mail} <#assign mail="my@163.com" /> ${mail} <#assign mail="my@163.com" in bb /> ${bb.mail} ----------------------------------- 声明、指定变量assign: 测试数据类型: <#assign ss="hellxz"/> 文本型:${ss} <#assign s1=1 /> 数值型:${s1} <#assign s2=true/> 布尔型:<#if s2>布尔型</#if> ------------------------------------- 字符串常见内建函数: html转义:${html5?html} cap_first(首字母大写):${name?cap_first} upper_case(转大写):${name?upper_case} lower_case(转小写):${upper?lower_case} 数值常见内建函数: int(取整数部分) 集合内建函数: size(取集合大小) ------------------------------------ 字符串空值处理: FreeMarker不支持空值,如果为空直接报错 没有定义直接引用 <#-- ${sss} 直接报错了--> 空值处理: ${sss!}<#-- 为空则输出空字符串 --> ${sss!"default"} <#--设置默认值,为空自动使用--> ------------------------------------------ ??布尔值处理 <#if user??> 如果该值存在,返回true,相当于 if user != null <#else> 该值不存在返回false </#if>
新建b.ftl 用于测试命名空间
<#macro copyright date> <p>Copyright (C) ${date} 北京尚学堂.</p> </#macro> <#assign mail = "bjsxt@163.com">
在templates下新建include.txt,用于测试include指令
我是被包含的内容!
运行TestFreeMarker,查看输出(这里为了方便比较,加上行号):
hello,老张,今天看起来很精神嘛! ---------------------------------- if分支语句测试: 老张! ---------------------------------- if else 分支测试: 老张 ---------------------------------- if else if else 测试: 因为大于小于号等会被转义,使用简写作为比较符号 gt=great than = > lt=less than = < gte = great than equal = >= lte = less than equal = <= 及格 ---------------------------------- 遍历list测试: 中国 上海 日本 东京 ---------------------------------- include包含测试: 我是被包含的内容! ---------------------------------- macro无参函数(宏函数)测试: 定义函数: 调用函数测试: 我是函数内容 我是函数内容 ---------------------------------- macro带参函数: 调用测试: 中/明/月 ---------------------------------- nested测试: 用于一大段代码的嵌入 向nested部分添加内容: <html> <head> <body> <h1>我是nested的内容</h1> </body> </head> </html> ---------------------------------- 测试命名空间: <p>Copyright (C) 2010-2011 北京尚学堂.</p> bjsxt@163.com my@163.com my@163.com ----------------------------------- 声明、指定变量assign: 测试数据类型: 文本型:hellxz 数值型:1 布尔型:布尔型 ------------------------------------- 字符串常见内建函数: html转义:<b>大写的文字</b> cap_first(首字母大写):Hellxz upper_case(转大写):HELLXZ lower_case(转小写):abcdef 数值常见内建函数: int(取整数部分) 集合内建函数: size(取集合大小) ------------------------------------ 字符串空值处理: FreeMarker不支持空值,如果为空直接报错 没有定义直接引用 空值处理: default ------------------------------------------ ??布尔值处理 如果该值存在,返回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部分见我的下篇博客
http://www.cnblogs.com/hellxz/p/8453239.html
- Webservice学习笔记二,使用Axis发布简单的Web服务
- Android 学习 笔记_12. Spinner的简单实使用
- OpenCV学习笔记(8)VS2008 MFC下使用OpenCV2.0进行简单图像处理
- NuGet学习笔记(1)——初识NuGet及快速安装使用
- entlib5.0 学习笔记 caching application block2 简单使用示例
- Silverlight学习笔记一(理解一下机制,使用一下布局,实现一个简单的用户登录)
- MVC学习笔记三:WebGrid控件的简单使用
- 学习笔记,VB.NET使用DirectSound9 (1) 简单播放
- Android 学习 笔记_12. Spinner的简单实使用
- DayDayUp之HTML5学习笔记 二 使用header、aside、section、footer实现一个简单的界面
- 安卓学习笔记:使用PopupWindow创建简单菜单
- (学习笔记)简单正则表达式的使用实例[javascript]
- Yii学习笔记--简单的使用
- NodeJS-学习笔记(2)--使用node提供的express框架开发简单的web应用
- Unity 学习笔记(1) — Unity简介及简单使用
- 【Android】学习笔记(9)——SQLite简单使用
- OpenCV学习笔记(8)VS2008 MFC下使用OpenCV2.0进行简单图像处理
- Watir学习笔记之一 浏览器的简单使用
- cocos2d-x的Sptrite Action SpriteFrame Animation texture使用的简单方法---学习笔记
- entlib5.0 学习笔记 caching application block2 简单使用示例