1. FreeMarker 概念
FreeMarker 是一款 模板引擎: 即一种基于模板和要改变的数据, 并用来生成输出文本(HTML网页,电子邮件,配置文件,源代码等)的通用工具。 它不是面向最终用户的,而是一个Java类库,是一款程序员可以嵌入他们所开发产品的组件。
2. freemarker的环境搭建
- 创建一个maven web项目
- pom.xml添加依赖jar包
<dependency>
<groupId>org.freemarker</groupId>
<artifactId>freemarker</artifactId>
<version>2.3.30</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.0.1</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
<version>4.1.4.RELEASE</version>
</dependency>
<plugins>
<plugin>
<groupId>org.apache.tomcat.maven</groupId>
<artifactId>tomcat6-maven-plugin</artifactId>
<version>2.2</version>
</plugin>
<plugin>
<groupId>org.apache.tomcat.maven</groupId>
<artifactId>tomcat7-maven-plugin</artifactId>
<version>2.2</version>
</plugin>
</plugins>
- 配置web.xml
<web-app id="webApp_ID" version="3.0"
xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
>
<display-name>Archetype Created Web Application</display-name>
<servlet>
<servlet-name>freemarker</servlet-name>
<servlet-class>freemarker.ext.servlet.FreemarkerServlet</servlet-class>
<!-- FreemarkerServlet settings: -->
<init-param>
<param-name>TemplatePath</param-name>
<param-value>/</param-value>
</init-param>
<init-param>
<param-name>NoCache</param-name>
<param-value>true</param-value>
</init-param>
<init-param>
<param-name>ContentType</param-name>
<param-value>text/html; charset=UTF-8</param-value>
<!-- Forces UTF-8 output encoding! -->
</init-param>
<!-- FreeMarker settings: -->
<init-param>
<param-name>template_update_delay</param-name>
<param-value>0</param-value>
<!-- 0 仅用于开发阶段! Use higher value otherwise. -->
</init-param>
<init-param>
<param-name>default_encoding</param-name>
<param-value>ISO-8859-1</param-value>
<!-- The encoding of the template files. -->
</init-param>
<init-param>
<param-name>number_format</param-name>
<param-value>0.##########</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>freemarker</servlet-name>
<url-pattern>*.ftl</url-pattern>
</servlet-mapping>
</web-app>
- 创建一个servlet子类
@WebServlet("/f01")
public class FreeMarker01 extends HttpServlet {
@Override
protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//添加数据
request.setAttribute("msg","Hello Freemarker");
//请求转发跳转到ft1文件中
request.getRequestDispatcher("free/f01.ftl").forward(request,response);
}
}
- 编写freemarker文件
<#--
用el表达式来存信息
-->
${msg}
3. freemarker数据类型
- boolean类型
在freemarker中布尔类型不能直接输出,许哟啊先转换为字符串
方式1 :?c
方式2:?String 或?String(“true时的文本”,“false时的文本”)
<#--boolean类型的获取方式-->
${msg?c}<br>
${msg?String}<br>
${msg?String("yes","no")}<br>
- 日期类型
在freemarker中日期类型不能直接输出,如果输出要先转成日期型或字符串性
- 年月日 ?date
- 时分秒 ?time
- 年月日时分秒 ?datetime
- 指定格式 ?String(“自定义格式”)
<#--日期类型-->
${date?date}<br>
${date?time}<br>
${date?datetime}<br>
${date?string("yyyy-MM-dd MM:mm:ss")}
- 数值类型的数据类型
在freemarker中数值类型可以直接输出:
- 转字符串
- 普通字符串 ?c
- 货币型字符串 ?string.currency
- 百分比型字符串 ?stirng.percent
- 保留浮点型数值指定小数位(#表示一个小数位)
<#--数值类型-->
${age}<br>
${num?c}<br>
${num?string.currency}<br>
${num?string.percent}<br>
${num?string["0.###"]}<br>
- 字符串类型
<#--字符串类型-->
<#--截取字符串(左闭右开) ?substring(start,end)-->
${str1?substring(2,3)}<br>
<#--首字母小写输出-->
${str2?uncap_first}<br>
<#--首字母大写输出-->
${str1?cap_first}<br>
<#--字母转小写输出-->
${str2?lower_case}<br>
<#--字母转大写输出-->
${str1?upper_case}<br>
<#--获取字符串长度-->
${str1?length}<br>
<#--是否以指定字符开头(boolean类型)-->
${str2?starts_with("d")?string}<br>
<#--是否以指定字符串结尾(boolean类型)-->
${str1?ends_with("c")?string}<br>
<#--获取指定字符串的索引-->
${str2?index_of("o")}<br>
<#--去除字符串前后空格-->
${str1?trim}<br>
<#--替换指定字符串-->
${str2?replace("w","f")}<br>
- 小细节 空字符串的处理
<#--空字符串-->
<#--如果值不存在,直接输出的话,会报错-->
${str}<br>
<#--使用!,当值不存在的时候,默认显示空字符串-->
${str!}<br>
<#--当值不存在的时候,使用!"默认显示指定字符串"-->
${str!"这是一个默认值"}<br>
<#--使用??,判断字符串是否为空,返回布尔类型。如果想输出,需要将布尔类型转换成字符串-->
${(str??)?string}<br>
<hr>
- 序列数据类型
<#--sequence类型-->
<#--数组操作-->
<#list stars as star>
下标:${star?index}-姓名:${star}<br>
</#list>
获取序列的长度:${stars?size}<br>
获取第一个元素:${stars?first}<br>
获取最后一个元素:${stars?last}<br>
<#--List操作-->
<#list cityList as city>
${city}
</#list>
<#--升序排序-->
<#list cityList?sort as city>
${city}
</#list>
<#--倒序排序-->
<#list cityList?reverse as city>
${city}
</#list>
<#--降序序排序-->
<#list cityList?sort?reverse as city>
${city}
</#list>
<#list userList as user>
编号:${user.uid}
姓名:${user.name}
年龄:${user.age}<br>
</#list>
- hash类型
<#--Map-->
<#list cityMap?keys as key>
${key}--------------${cityMap[key]}
</#list>
<br>
<#list cityMap?values as value>
${value}
</#list>
4.freemarker常用指令
- assign指令
使用该指令你可以创建一个新的变量, 或者替换一个已经存在的变量。
- 变量 seq 存储一个序列:
<#assign
- 变量 x 中存储增长的数字:
<#assign x++>
- 作为一个方便的特性,你可以使用一个 assign 标记来进行多次定义。比如这个会做上面两个例子中相同的事情
<#assign
seq = ["foo", "bar", "baz"]
x++
>
- if, else, elseif
<#--if -->
<#assign grade =67>
<#if grade lt 60>
不及格
<#elseif grade gt 60 && grade lt 80>
良好
<#elseif grade gt 80 && grade lt 90>
优秀
<#else >
very good
</#if>
- import
引入一个库。也就是说,它创建一个新的空命名空间, 然后在那个命名空间中执行给定 path 参数中的模板, 所以模板用变量(宏,函数等)填充命名空间。 然后使得新创建的命名空间对哈希表的调用者可用
如果你用同一个 path 多次调用 import,它会创建命名空间, 但是只运行第一次 import 的调用。 后面的调用仅仅创建一个哈希表变量,你只是通过它来访问 同一个 命名空间。
<#import "/libs/mylib.ftl" as my>
<@my.copyright date="1999-2002"/>
- include
你可以使用它在你的模板中插入另外一个 FreeMarker 模板文件 (由 path 参数指定)。 被包含模板的输出格式是在 include 标签出现的位置插入的。 被包含的文件和包含它的模板共享变量,就像是被复制粘贴进去的一样。 include 指令不能由被包含文件的内容所替代, 它只是当 FreeMarker 每次在模板处理期间到达 include 指令时处理被包含的文件。所以对于如果 include 在 list 循环之中的例子, 你可以为每个循环周期内指定不同的文件名。
假设 /common/copyright.ftl 包含:
Copyright 2001-2002 ${me}<br>
All rights reserved.
那么:
<#assign me = "Juila Smith">
<h1>Some test</h1>
<p>Yeah.
<hr>
<#include "/common/copyright.ftl">
- 输出
<h1>Some test</h1>
<p>Yeah.
<hr>
Copyright 2001-2002 Juila Smith
All rights reserved.
- list指令
<#list users as user>
<p>${user}
</#list>
5.freeMarker页面静态化
原理:
将要展示在页面的数据按照一定的模板进行分布数据样式。最后以html的形式展示出来
- 实现方式
- servlet类的编写
@WebServlet("/news")
public class NewServlet extends HttpServlet {
@Override
protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//实例化模板对象
Configuration configuration = new Configuration();
//设置加载模板的上下文 以及加载模板的路径(模板存放路径)
configuration.setServletContextForTemplateLoading(getServletContext(),"/free");
//设置模板的编码格式
configuration.setDefaultEncoding("UTF-8");
//加载模板文件,获取模板对象
Template template = configuration.getTemplate("news.ftl");
//设置数据类型
Map<String,Object> map =new HashMap<>();
map.put("title","我是一个女程序员!");
map.put("source","来自伟大的地球!");
map.put("pubTime","1998-06-10");
map.put("content","你是我的小丫小苹果你是");
//生成html
//获取项目的根目录
String basePath = request.getServletContext().getRealPath("/");
//设置html文件存放的路径
File htmlFile=new File(basePath+"/html");
//判断文件目录 是否存在
if (!htmlFile.exists()){
//如果文件目录不存在
htmlFile.mkdir();
}
//得到生成的文件名
String fileName=System.currentTimeMillis()+".html";
//创建html文件
File file=new File(htmlFile,fileName);
//获取文件输出流
FileWriter writer = new FileWriter(file);
//生成html
try {
template.process(map,writer);
} catch (TemplateException e) {
e.printStackTrace();
}finally {
//关闭资源
writer.flush();
writer.close();
}
}
}
- 对应的freemarker文件
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" http-equiv="content-type" content="text/html">
<title>Title</title>
</head>
<body>
<#--新闻标题-->
<h2 align="center">${title}</h2>
<#--新闻来源 新闻发布时间-->
<p align="center">
新闻来源:${source}
发布时间:${pubTime}
</p>
<#--新闻内容-->
<p style="text-indent: 2em">
${content}
</p>
</body>
</html>
6. freemarker运算符
<#--运算符-->
<#--算数运算符-->
<#assign a1=8 a2=2>
${a1}+${a2}=${a1+a2}<br>
${a1}-${a2}=${a1-a2}<br>
${a1}*${a2}=${a1*a2}<br>
${a1}/${a2}=${a1/a2}<br>
${a1}%${a2}=${a1%a2}<br>
<#--字符串运算符-->
${"hello"+","+"freemarker"}
<#--
逻辑运算符
&&、||、!
-->
<#--
比较运算符
>(gt):大于号,推荐使用gt
<(lt):小于号,推荐使用lt
>=(gte):大于等于,推荐使用gte
<=(lte):大于号,推荐使用lte
!=:不等于
-->
<#--
空值运算符
1.??判断是否为空,返回布尔类型
如果不为空 false 如果为空, true 不能直接输出
${(name??)?string}
2.设置默认值,如果为空,则返回默认值
1.!设置默认为空字符串:
${name!}
2.设置指定默认值
${name!"zhangsan}
-->