FreeMarker基础及使用
概念:
FreeMarker是一个模板引擎,它提供模板,其他程序提供数据,最后组合起来。
FreeMarker不是一个Web框架,而只是框架的一个组件,而jsp必须在容器中运行
官网:
普通java项目配置:
1、引入freemarker-2.3.16\lib\freemarker.jar
2、工程下创建目录templates,里面创建模板文件a.ftl,文件内容是:
你好: ${user },欢迎光临
3、创建测试的java文件Test.java,文件内容是:
public class Test {
public static void main(String[] args) throws Exception {
// 创建Freemarker配置实例
Configuration cfg = new Configuration();
cfg.setDirectoryForTemplateLoading(new File("templates"));
// 创建数据模型
Map root = new HashMap();
root.put("user", "老王");
// 加载模板文件
Template t1 = cfg.getTemplate("a.ftl");
// 显示生成的数据
Writer out = new OutputStreamWriter(System.out);
t1.process(root, out);
out.flush();
out.close();
}
}
运行即可输出:
你好: 老王,欢迎光临
其中目录名templates和模板文件名a.ftl都是可以自己命名的,java中对应修改就行了
指令:
注释
<#-- <#if user=="老王">是老王</#if> -->
if
<#if user=="老王">
用户是老王
<#elseif user=="老张">
用户是老张
<#else>
用户不是老王,也不是老张
</#if>
遍历list、数组等
<#list userList as userMap>
序号:${userMap_index + 1}
姓名:${userMap.userName}
年龄:${userMap.age}
</#list>
其中userMap加上"_index"可以得到序号,从0开始
取得子集合
可以直接取出集合的子集合,指定开始索引和结束索引,如:
<#list userList[2..5] as userMap>
${userMap.userName}
</#list>
遍历索引2到索引5的元素(共4个元素),下标从0开始算
userList[2..]表示从索引2开始到结束的所有元素
${userList[0].userName}可以输出第0个元素的userName
include
类似于jsp的include,静态包含,文件类型不限,如:
<#include "b.ftl"/>
<#include "head.txt"/>
宏指令
可以定义一段语句,然后其他地方多次调用,如:
不带参
<#macro m1>
用户列表:<br/>
<#list userList as userMap>
序号:${userMap_index + 1}
姓名:${userMap.userName}
年龄:${userMap.age}
</#list>
</#macro>
<@m1 /><@m1 />
macro定义了一个宏m1,后面调用了2次,就输出2次用户列表
带参
参数不用声明类型,类似于js的参数
<#macro m2 user_name user_age>
姓名:${user_name}
年龄:${user_age}
</#macro>
<@m2 user_name="老张" user_age="18"/>
<@m2 "老王" "22"/>
上面的宏m2定义了user_name和user_age两个参数,,调用的时候写不写参数名都可以,不写就按顺序赋值
nested参数
参数调用时可以放到调用的开始与结束标签之间,而不用属性的方式做参数,这样可以将一大段代码作为参数,取参数时用<#nested/>标签
<#macro m3>
姓名:<#nested/>
</#macro>
<@m3>
张三
</@m3>
nested参数可以和属性参数一起使用
定义变量(assign)
<#assign v="user1"/>
${v}
相当于
request.setAttribute("v", "user1");
引入(import)
一个ftl可以引入另一个ftl中定义的宏、变量等,如:
b.ftl:
<#macro n2>
我是b.ftl的宏
</#macro>
<#assign v="user1"/>
hello
其中定义了宏n2和变量v
a.ftl:
<#import "b.ftl" as bb />
<@bb.n2/>
${bb.v}
其中引用了b.ftl,并指定它的命名空间为bb,这样就可以通过bb调用b.ftl中定义的宏和变量了。
引用的时候不会把b.ftl中的内容包含进来,如b.ftl中的hello不会在a.ftl中输出。
格式化(使用内建函数)
格式化日期和时间
${createDate?string("yyyy-MM-dd HH:mm:ss")}
html转换
html标签转义,如:
${testStr?html}
<br/>转换成<br/>
首字母大写(cap_first)
${testStr?cap_first}
abc转换成Abc
转大写(upper_case)
${testStr?upper_case}
abc转换成ABC
转小写(lower_case)
${testStr?lower_case}
ABC转换成abc
空值处理
ftl中输出null或者不存在的值会报异常,因此需要处理
设置默认值
${userName!}
空值默认为空字符串
${userName! "abc" }
空值默认为字符串"abc"
变量后跟1个感叹号号表示判断是否为空
判断是否为空
<#if (user.name)??>
hello,${user.name}
</#if>
变量后跟2个问号表示判断是否为空
(user.name)??要加括号,因为"??"优先级比"."高
list为空判断
??可以判断对象是否为空,list?size>0可以判断集合是否元素是否大于0(前提是集合不能为null,否则报错)。
因此判断集合不为null且size大于0用表达式:
<#if (userList?? && userList?size > 0)>
它有短路机制,相当于java的userList !=null && userList.size() > 0
如果只判断集合不为null,则用
<#if userList??>
示例:
java:
List<String> strList = new ArrayList<>();
strList.add("aaa");
strList.add("bbb");
model.addAttribute("strList", strList);
List<Map<String, Object>> userList = new ArrayList<>();
Map<String, Object> user1 = new HashMap<>();
user1.put("name", "张三");
user1.put("age", 15);
userList.add(user1);
Map<String, Object> user2 = new HashMap<>();
user2.put("name", "李四");
user2.put("age", 26);
userList.add(user2);
model.addAttribute("userList", userList);
List<Map<String, Object>> emptyList = new ArrayList<>();
model.addAttribute("emptyList", emptyList);
List<Map<String, Object>> nullList = null;
model.addAttribute("nullList", nullList);
ftl:
字符串list:<br/>
<#list strList as str>
${str}<br/>
</#list>
<br/>
map的list:<br/>
<#list userList as userMap>
${userMap.name},${userMap.age}<br/>
</#list>
<#if notExistList??>
notExistList?? 返回 true
<br/>
<#else>
notExistList?? 返回 false
<br/>
</#if>
<#if nullList??>
nullList?? 返回 true
<br/>
<#else>
nullList?? 返回 false
<br/>
</#if>
<#if emptyList??>
emptyList?? 返回 true
<br/>
<#else>
emptyList?? 返回 false
<br/>
</#if>
<#if (emptyList?size > 0)>
emptyList?size > 0?? 返回 true
<br/>
<#else>
emptyList?size > 0?? 返回 false
<br/>
</#if>
<#if (userList?size > 0)>
userList?size > 0?? 返回 true
<br/>
<#else>
userList?size > 0?? 返回 false
<br/>
</#if>
输出:
Servlet中使用freemarker:
servlet中使用跟java中使用很类似,配置:
引入freemarker.jar,
web.xml
<servlet>
<servlet-name>hello</servlet-name>
<servlet-class>example.HelloServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>hello</servlet-name>
<url-pattern>/hello</url-pattern>
</servlet-mapping>
example. HelloServlet.java
package example;
import java.util.*;
import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
import freemarker.template.*;
public class HelloServlet extends HttpServlet {
private Configuration cfg;
public void init() {
cfg = new Configuration();
cfg.setServletContextForTemplateLoading(getServletContext(), "WEB-INF/templates");
}
protected void doGet(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
Map root = new HashMap();
root.put("message", "Hello World!");
Template t = cfg.getTemplate("test.ftl");
resp.setContentType("text/html; charset=" + t.getEncoding());
Writer out = resp.getWriter();
try {
t.process(root, out);
} catch (TemplateException e) {
e.printStackTrace();
}
}
}
WEB-INF/templates/test.ftl:
<html>
<head>
<title>FreeMarker Example Web Application 1</title>
</head>
<body>
${message}
</body>
</html>
Struts2中使用freemarker:
直接使用即可,不用配置,如:
@Result(name = "success", type="freemarker", location = "/WEB-INF/template/test.ftl"
freemarker生成html
输出流指向到html的文件File即可
浙公网安备 33010602011771号