楔子:

   之前在和同事讨论,同事说“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. C++判断char*的指向

    char *a = "Peter"; char b[] = "Peter"; ]; strcpy_s(c, , "Peter"); 这里a指 ...

  2. 使用docker inspect获取数据卷信息时返回地址为空

    使用 docker inspect 命令查看容器挂载的volume的目录 $ sudo docker inspect --format "{{.Volumes}}" redis-m ...

  3. 微信小程序demo——入门级(附源码)

    最近小程序又蠢蠢欲动,出了一个公众号绑定小程序功能,目测不错,就看了下微信小程序文档,顺便写了几行代码,后续有空会持续更新维护. 源码:https://github.com/SibreiaDante/ ...

  4. Internet History, Technology and Security (Week 3)

    Week 3 History: The Web Makes it Easy to Use Welcome to week 3! This is our fourth and final week of ...

  5. 『编程题全队』Alpha 阶段冲刺博客Day1

    『编程题全队』Alpha 阶段冲刺博客Day1 一.Alpha 阶段全组总任务 二.各个成员在 Alpha 阶段认领的任务 三.明日各个成员的任务安排 孙志威:实现基本的网络连接, 完成燃尽图模块 孙 ...

  6. 评论alpha发布

    第一组:新蜂小组 题目:俄罗斯方块 评论:很荣幸被邀请体验此游戏,感到加速下落时不是很灵敏,没有计分,页面不够美观(据说还在改善),整体框架已完成,基本功能已具备. 第二组:天天向上 题目:连连看 评 ...

  7. net user 修改密码的坑

    不多说 直接上图 自己偷懒修改 admin的密码.. 结果没注意 这个地方 能够输入全角字符. 造成密码 实质上是全角的 标点符号 ... 以后一定注意一些. 里面的坑..说多了 都是浪费时间 另外 ...

  8. java中为什么要进行对象序列化?

    序列化其实很好理解,假如你现在做一个项目,项目是分工合作的,并且你喝其他小组成员不在同一个城市,那么你要如何把你写的那些类给其他小组成员呢?这个时候就要用到序列化了,简单的说:序列化就是将内存中的类或 ...

  9. 浅析Web数据存储-Cookie、UserData、SessionStorage、WebSqlDatabase

    Cookie 它是标准的客户端浏览器状态保存方式,可能在浏览器诞生不久就有Cookie了,为什么需要Cookie 这个东东?由于HTTP协议没有状态,所以需要一个标志/存储来记录客户浏览器当前的状态, ...

  10. 计算机网络【9】—— HTTP1.0和HTTP1.1的区别及常见状态码

    一.HTTP1.0与HTTP1.1的区别 1.HTTP 1.1支持长连接(PersistentConnection)和请求的流水线(Pipelining)处理 HTTP 1.0规定浏览器与服务器只保持 ...