🎏FreeMarker模板语言
三个主要概念:
①.是一个模板引擎
②.支持html标签和Jsp标签库
③.将业务与视图分离
1.FreeMarker配置web.xml
⭐一定记得引入依赖和配置web.xml
<web-app>
<!-- FreeMarker 的Servlet配置 -->
<servlet>
<servlet-name>freemarker</servlet-name>
<servlet-class>freemarker.ext.servlet.FreemarkerServlet</servlet-class>
<init-param>
<!-- 模板路径 -->
<param-name>TemplatePath</param-name>
<!-- 默认在webapp目录下查找对应的模板文件 -->
<param-value>/</param-value>
</init-param>
<init-param>
<!-- 模板默认的编码:UTF-8 -->
<param-name>default_encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
<!-- 2.3.4. 编写Servlet类 2.3.5. 新建模板文件 ftl-->
<!-- 在webapp目录下新建template文件夹,创建f01.ftl文件-->
<!-- 2.3.6. 启动项目-->
</servlet>
<!-- 处理所有以.ftl结尾的文件;ftl是freemarker默认的文件后缀 -->
<servlet-mapping>
<servlet-name>freemarker</servlet-name>
<url-pattern>*.ftl</url-pattern>
</servlet-mapping>
</web-app>
2.数据类型
分别是:布尔,字符,数值,sequence(数组集合),hash(Map集合)
Test01.java
@WebServlet("/ftl")
public class Test01 extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 字符串
req.setAttribute("msg","好家伙");
// 布尔类型
req.setAttribute("bool",true);
// 日期类型
req.setAttribute("createDate",new Date());
//数值型
req.setAttribute("age",18);
req.setAttribute("salary",10000);
req.setAttribute("avg",0.545); // 浮点型
//sequence
String arr[]={"小王","小李","小明","小飞"};
List<String> ay= Arrays.asList("小王","小李","小明","小飞");
req.setAttribute("arr",arr);
req.setAttribute("ay",ay);
//hash
Map<String,String> map=new HashMap<>();
map.put("1001","xiao");
map.put("1002","dada");
map.put("1003","between");
req.setAttribute("map",map);
req.getRequestDispatcher("template/ftl01.ftl").forward(req,resp);
}
}
ftl01.ftl文件:>>>
<#--msg参数-->
<hr>
${msg}
<hr>
①${bool?string}<br>
②${bool?string("yes","no")}<br>
③${bool?c}
<hr>
日期不能直接输出:<br>
<#-- 输出日期格式 -->
${createDate?date} <br>
<#-- 输出时间格式 -->
${createDate?time} <br>
<#-- 输出日期时间格式 -->
${createDate?datetime} <br>
<#-- 输出格式化日期格式 -->
${createDate?string("yyyy年MM月dd日 HH:mm:ss")} <br>
<hr>
数值:
<#-- 直接输出数值型 -->
${age} <br>
${salary} <br>
<#-- 将数值转换成字符串输出 -->
${salary?c} <br>
<#-- 将数值转换成货币类型的字符串输出 -->
${salary?string.currency} <br>
<#-- 将数值转换成百分比类型的字符串输出 -->
${avg?string.percent} <br>
<#-- 将浮点型数值保留指定小数位输出 (##表示保留两位小数) -->
${avg?string["0.##"]} <br>
<hr>
sequence遍历:
<#list arr as ar>
${ar}-
</#list>
<hr>
<#list ay as demo>
${demo_index}-->${demo}
</#list>
<hr>
hash的遍历:(Map的key遍历)<br>
<#list map ? keys as key>
${key}-->${map[key]}
</#list><br>
Map的value遍历<br>
<#list map ? values as vl>
${vl}
</#list>
<hr>
测试结果:》》》
字符串数据类型常用方法
<#--数据类型:
字符串类型 在freemarker中字符串类型可以直接输出;
1. 截取字符串(左闭右开) ?substring(start,end)
2. 首字母小写输出 ?uncap_first
3. 首字母大写输出 ?cap_first
4. 字母转小写输出 ?lower_case
5. 字母转大写输出 ?upper_case
6. 获取字符串长度 ?length
7. 是否以指定字符开头(boolean类型) ?starts_with("xx")?string
8. 是否以指定字符结尾(boolean类型) ?ends_with("xx")?string
9. 获取指定字符的索引 ?index_of("xx")
10. 去除字符串前后空格 ?trim 11. 替换指定字符串 ?replace("xx","xx") -->
⭐判断是否为空:
① ! :指定缺失变量的默认值
② ?? :判断变量是否存在
@WebServlet("/ftl02")
public class Test02 extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String str="1234";
String strnull="";
req.setAttribute("str",str);
req.setAttribute("strnull",strnull);
req.getRequestDispatcher("template/ftl02.ftl").forward(req,resp);
}
}
//---------------------------------------------------
${str!}
${(strnull ??)? string}
${s!}
${(s??)? string}
3.FreeMarker指令
主要指令:①list遍历指令 ②assign:自定义变量指令 ③import导入指令 ④include包含指令引入 ⑤macro宏指令
<#--自定义变量-->
<#assign str="xiaowang">
${str}
<#--gt是> lt是< gte是>=-->
<#assign score = 80>
<#if score < 60> 你个小渣渣!
<#elseif score == 60> 分不在高,及格就行!
<#elseif score gt 60 && score lt 80> 哎哟不错哦!
<#else> 你很棒棒哦!
</#if> <br>
<#-- 自定义指令 宏指令-->
<#macro sum s1 s2>
${s1+s2}
</#macro>
<@sum s1=10 s2=30></@sum><br>
<#--占位符指令nested-->
<#macro test>
这是一段文本!
<#nested>
<#nested>
</#macro>
<@test><h4>这是文本后面的内容!</h4></@test><br>
<#--导入指令import-->
<#--通过导入其他文件,直接调用其内部方法-->
<#import "ftl01.ftl" as ftl>
<@ftl.sum s1=100 s2=200></@ftl.sum><br>
<#--包含指令,include 可以使用 include 指令在你的模板中插入另外一个 FreeMarker 模板文件 。-->
<#--引入ftl01.ftl文件-->
<#include "ftl01.ftl">
<#include "demo.text">
4.FreeMarker运算符
①、算术运算符
+、-、*、/、%
②、逻辑运算符
&&、||、!
③、比较运算符
(gt): 大于号,推荐使用
gt < (lt): 小于号,推荐使用
lt >= (gte): 大于等于, 推荐是用
gte <= (lte): 小于等于,推荐使用
lte == : 等于
!= : 不等于
④、算术运算符
1. ??:判断是否为空,返回布尔类型 如果不为空返回 false, 如果为空返回 true,不能直接输出 ${(name??)?string}
2. !: 设置默认值,如果为空,则设置默认值
2.1. 设置默认为空字符串: ${name!}
2.2. 设置指定默认值 ${name!'zhangsan'}
5.FreeMarker页面静态化(了解即可)
- 定义模板news.ftl
<meta http-equiv="Content-Type"
content="text/html; charset=utf-8" />
<#-- 新闻标题 -->
<h1>${title}</h1>
<p> 新闻来源:${source}
发布时间:${pubTime?string("yyyy-MM-dd HH:mm")}
</p>
<#-- 新闻内容 -->
<p> ${content} </p>
- 加载模板NewsServlet
@WebServlet("/news")
public class NewsServlet extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 实例化模板配置对象
Configuration configuration = new Configuration();
// 设置加载模板的上下文 以及 设置加载模板路径(模板存放的路径)
configuration.setServletContextForTemplateLoading(getServletContext(),"/template");
// 设置模板的编码格式
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", new Date());
map.put("content", "中共中央政治局常务委员会近日召开会议强调,"
+ "要有针对性地开展援企、稳岗、扩就业工作,"
+ "做好高校毕业生、农民工等重点群体就业工作,"
+ "积极帮助个体工商户纾困。疫情期间,稳就业情况如何?还有哪些问题待解?"
+ "记者采访了不同群体,记录这个特别的就业季。");
// 获取项目所在的根目录
String basePath = req.getServletContext().getRealPath("/");
// 设置页面存放的目录
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);
try {
// 输出html 将模型数据填充到模板中
template.process(map, writer);
// 输出成功
System.out.println("新闻创建成功!");
} catch (TemplateException e) {
e.printStackTrace();
} finally {
writer.flush(); writer.close();
}
}
}