楔子:

   之前在和同事讨论,同事说“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转义:&lt;b&gt;大写的文字&lt;/b&gt;
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

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

  1. Spring MVC 学习笔记10 —— 实现简单的用户管理(4.3)用户登录显示全局异常信息

    </pre>Spring MVC 学习笔记10 -- 实现简单的用户管理(4.3)用户登录--显示全局异常信息<p></p><p></p>& ...

  2. Spring MVC 学习笔记9 —— 实现简单的用户管理(4)用户登录显示局部异常信息

    Spring MVC 学习笔记9 -- 实现简单的用户管理(4.2)用户登录--显示局部异常信息 第二部分:显示局部异常信息,而不是500错误页 1. 写一个方法,把UserException传进来. ...

  3. Spring MVC 学习笔记8 —— 实现简单的用户管理(4)用户登录

    Spring MVC 学习笔记8 -- 实现简单的用户管理(4)用户登录 增删改查,login 1. login.jsp,写在外面,及跟WEB-INF同一级目录,如:ls Webcontent; &g ...

  4. Arduino学习笔记① 初识Arduino

    1.前言     近段时间,博主陆续更新了ESP8266学习笔记,主要开发平台是Arduino.但是,对于很多无基础的初学者来说,甚至不了解Arduino是什么.因此,博主决定加入一个Arduino学 ...

  5. blfs(systemv版本)学习笔记-制作一个简单的桌面系统

    我的邮箱地址:zytrenren@163.com欢迎大家交流学习纠错! 大概思路: lfs(系统)+xorg(驱动)+i3-wm(窗口+桌面)+lightdm(显示管理器+登录管理器) 链接: lfs ...

  6. [原创]java WEB学习笔记41:简单标签之带属性的自定义标签(输出指定文件,计算并输出两个数的最大值 demo)

    本博客为原创:综合 尚硅谷(http://www.atguigu.com)的系统教程(深表感谢)和 网络上的现有资源(博客,文档,图书等),资源的出处我会标明 本博客的目的:①总结自己的学习过程,相当 ...

  7. [原创]java WEB学习笔记40:简单标签概述(背景,使用一个标签,标签库的API,SimpleTag接口,创建一个自定义的标签的步骤 和简单实践)

    本博客为原创:综合 尚硅谷(http://www.atguigu.com)的系统教程(深表感谢)和 网络上的现有资源(博客,文档,图书等),资源的出处我会标明 本博客的目的:①总结自己的学习过程,相当 ...

  8. wxPython学习笔记(初识)

    今天正式开始学习wxPython,基于对类的不熟悉,理解有点生硬,但还是做了些笔记. 1.是什么组成了一个wxpython程序? 一个wxpython程序必须有一个application(wx.App ...

  9. XML学习笔记4——XSD简单数据类型

    XSD提供了数据类型,并且支持自定义数据类型,但这一切都是建立在XSD内置数据类型和一套扩展内置数据类型的规则基础之上的,在这一篇笔记中,就来看看XSD中的数据类型. 1.XSD数据类型图 先看一下数 ...

随机推荐

  1. Effective Modern C++翻译(6)-条款5:auto比显示的类型声明要更好

        在概念上说,auto关键字和它看起来一样简单,但是事实上,它要更微妙一些的.使用auto会让你在声明变量时省略掉类型,同时也会防止了手动类型声明带来的正确性和性能上的困扰:虽然按照语言预先定义 ...

  2. 如何修改eclipse下注释的颜色

    修改注释颜色:window -- preferences -- java --editor --syntax coloring -- comments 中的前两个就是修改注释颜色的.点击右边的colo ...

  3. Vue 爬坑之路(一)—— 使用 vue-cli 搭建项目 (增补)

    cd  指定好安装目录 vue init webpack  项目名称 执行  vue vue list  查看可应用模板 vue init webpack  +名字 项目已启动

  4. UpdateBatch与事务处理的一点总结

    对于某些设置或者提交,如果希望是全部修改完毕后才确定生效,可以将DataSet的LockType:=ltBatchOptimistic,这样就可以了.然后每次做的修改和改动都暂时保存在缓存中,必须通过 ...

  5. javascript定时保存表单数据的代码

    (忘记是不是两家邮箱都有这个功能). 那这个功能是怎么做的呢? 定时,我们知道怎么弄,但保存呢?也许我们会通过隐藏域等手段来存放数据.但是,这个却有个缺点:那就是刷新页面后,数据将会丢失. 而此时,就 ...

  6. java 加载过程

    1.main方法进入方法区 2.main方法进栈 3.调用xxx类加载到jvm中 类属性进入数据共享区,方法进入到方法区

  7. 整理:python的二维数组操作

    Python中初始化一个5 x 3每项为0的数组,最好方法是: multilist = [[0 for col in range(5)] for row in range(3)] 如果初始化一个二维数 ...

  8. 【刷题】洛谷 P1519 穿越栅栏 Overfencing

    题目描述 描述 农夫John在外面的田野上搭建了一个巨大的用栅栏围成的迷宫.幸运的是,他在迷宫的边界上留出了两段栅栏作为迷宫的出口.更幸运的是,他所建造的迷宫是一个“完美的”迷宫:即你能从迷宫中的任意 ...

  9. ZJOI2018外省选手酱油记Day1

    Day0 上午考试...又爆零了 下午讲完题后放假 然后就滚回去收拾行李准备去\(ZJ\) Day1 衢州?我怎么从来没听过这个地方..肯定是我见识少 下午 上高铁出发,\(3个小时\),看了一下电影 ...

  10. 51nod 1376 最长上升子序列的数量 | DP | vector怒刷存在感!

    51nod 1376 最长上升子序列的数量 题解 我们设lis[i]为以位置i结尾的最长上升子序列长度,dp[i]为以位置i结尾的最长上升子序列数量. 显然,dp[i]要从前面的一些位置(设为位置j) ...