模板引擎Freemarker基础知识
-
Freemarker是什么
- FreeMarker是一款模板引擎: 即一种基于模板和要改变的数据, 并用来生成输出文本(HTML网页、电子邮件、配置文件、源代码等)的通用工具。
-
常用的java模板引擎还有 Jsp、Freemarker、Thymeleaf 、Velocity 等。
freemarker并不关心数据的来源,只是根据模板的内容,将数据模型在模板中显示并输出文件(通常为html,也可以生成其它格式的文本文件)
freemarker作为springmvc一种视图格式,默认情况下SpringMVC支持freemarker视图格式。
FreeMarker 基础指令
map即为freemarker静态化所需要的数据模型
List指令
1、注释,即:<#‐‐被注释的内容‐‐>
2、插值(Interpolation):即 ${…} 部分,freemarker会用真实的值替换 ${…} 中的内容
3、FTL指令:和HTML标记类似,名字前加#予以区分,Freemarker会解析标签中的表达式或逻辑。例如:<#list stuMap?keys as k> ,就是获取stuMap中的所有的key作为一个list集合,然后取list集合中的一个key赋值给k.
4、文本,仅文本信息,这些不是freemarker的注释、插值、FTL指令的内容会被freemarker忽略解析,直接输出内容。
解释Demo:
<#list stus as stu> <tr> <td>${stu_index + 1}</td> <td>${stu.name}</td> <td>${stu.age}</td> <td>${stu.mondy}</td> </tr> </#list>
其中:
_index:得到循环的下标,使用方法是在stu后边加"_index",它的值是从0开始
-
遍历Map数据
-
或者姓名:${stuMap['stu1'].name}<br/>
-
姓名:${stuMap.stu1.name}<br/>
其中stuMap是一个map集合,stu1是map集合中的一个元素对象,name是stu1的一个属性,如果采用list集合去遍历的话,第二种方法就不适用了。
-
if指令
- if 指令即判断指令,是常用的FTL指令,freemarker在解析时遇到if会进行判断,条件为真则输出if中间的内容,否则跳过内容不再输出。
例如: -
<td <#if stu.name =='小明'>style="background:red;"</#if>>${stu.name}</td>
意思就是如果stu的姓名是小明的话,就加背景色
-
其它指令
-
运算符
1、算数运算符 FreeMarker表达式中完全支持算术运算,FreeMarker支持的算术运算符包括:+, - , * , / , %
2、逻辑运算符 逻辑运算符有如下几个: 逻辑与:&& 逻辑或:|| 逻辑非:! 逻辑运算符只能作用于布尔值,否则将产生错误
3、比较运算符 表达式中支持的比较运算符有如下几个: 1 =或者==:判断两个值是否相等. 2 !=:判断两个值是否不等. 3 >或者gt:判断左边值是否大于右边值 4 >=或者gte:判断左边值是否大于等于右边值 5 <或者lt:判断左边值是否小于右边值 6 <=或者lte:判断左边值是否小于等于右边值
注意: =和!=可以用于字符串,数值和日期来比较是否相等,但=和!=两边必须是相同类型的值,否则会产生错误,而且FreeMarker是精确比较,“x”,"x ","X"是不等的.其它的运行符可以作用于数字和日期,但不能作用于字符串,大部分的时候,使用gt等字母运算符代替>会有更好的效果,因为 FreeMarker会把>解释成FTL标签的结束字符,当然,也可以使用括号来避免这种情况,如:<#if (x>y)>
空值处理
1、判断某变量是否存在使用 “??” 用法为:variable??,如果该变量存在,返回true,否则返回false
例如:
-
<#if stus??> <#list stus as stu> ...... </#list> </#if>
意思就是:如果stus集合不为空就遍历
2、缺失变量默认值使用 “!” 使用!要以指定一个默认值,当变量为空时显示默认值。
例: ${name!’’}表示如果name为空显示空字符串。
如果是嵌套对象则建议使用()括起来。
例如: ${(stu.bestFriend.name)!’’}表示,如果stu或bestFriend或name为空默认显示空字符串。
-
内建函数
- 内建函数语法格式: 变量+?+函数名称
例如:
1、和到某个集合的大小
${集合名?size}
2、日期格式化 -
显示年月日: ${today?date} 显示时分秒:${today?time} 显示日期+时间:${today?datetime} <br> 自定义格式化: ${today?string("yyyy年MM月")}
3、内建函数c
map.put(“point”, 102920122);
point是数字型,使用${point}会显示这个数字的值,不并每三位使用逗号分隔。
如果不想显示为每三位分隔的数字,可以使用c函数将数字型转成字符串输出
${point?c}
4、将json字符串转成对象
一个例子:
其中用到了 assign标签,assign的作用是定义一个变量。
-
<#assign text="{'bank':'工商银行','account':'10101920201920212'}" /> <#assign data=text?eval /> 开户行:${data.bank} 账号:${data.account}
一般这种语法不会用
-
入门Demo
要导入的依赖
-
<dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-freemarker</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> </dependency> <dependency> <groupId>com.squareup.okhttp3</groupId> <artifactId>okhttp</artifactId> </dependency> <dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-io</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> </dependency> </dependencies>
配置文件
-
server: port: 8088 #服务端口 spring: application: name: test-freemarker #服务名 freemarker: cache: false #关闭模板缓存,及时改及时测 settings: template_update_delay: 0 #检查模板更新延迟时间,例如设置为1秒,就是1秒后检查模板是否更新,设置为0表示立即检查,
模型类
-
@Data public class Student { private String name;//姓名 private int age;//年龄 private Date birthday;//生日日期 private Float money;//金额 private List<Student> friends;//朋友 private Student bestFriend;//最好的朋友 }
创建模板
-
<!DOCTYPE html> <html> <head> <meta charset="utf‐8"> <title>Hello World!</title> </head> <body> Hello ${name}! <br/> 遍历数据模型中的list学生信息,(数据模型中的名称为stus) <table> <tr> <td>序号</td> <td>姓名</td> <td>年龄</td> <td>金额</td> <td>出生日期</td> </tr> <#--判断list集合是否为空,为空就不执行--> <#if stus??> <#list stus as stu> <tr> <td>${stu_index+1}</td> <td <#if stu.name == '小明'>style="background-color: cyan" </#if>>${stu.name}</td> <td>${stu.age}</td> <td <#if (stu.money > 300)>style="background: red" </#if>>${stu.money}</td> <td>${stu.birthday?date}</td> </tr> </#list> </#if> </table> <br/> 学生的个数:${stus?size} <br/> 遍历数据模型中的stuMap(map数据),第一种方法,在中括号中填写map的key;第二种方法,在map后面直接加 "." <br/> 姓名:${(stuMap['stu1'].name)!''}<br/><#--如果stu1用户存在就显示,否则就显示一个空字符串--> 年龄:${(stuMap['stu1'].age)!''}<br/> 金额:${(stuMap['stu1'].money)!''}<br/> 姓名:${(stuMap.stu1.name)!''}<br/> 遍历map中的key,用list标签,stuMap?key就是一个key列表(是一个list)<br/> <#list stuMap?keys as k> 姓名:${stuMap[k].name}<br/> 年龄:${stuMap[k].age}<br/> </#list> <br/> <#--?c的作用就是去掉每三位数字一个分隔符--> ${point?c} <br/> <#assign text="{'bank':'工商银行','account':'101920201920212'}" /> <#--?eval的作用就是把text的json字符串转为Java对象--> <#assign data=text?eval /> 开户行:${data.bank} 账号:${data.account} </body> </html>
接口数据
-
@RequestMapping("/test1") public String test1(Map<String, Object> map){ //map就是freemarker模板所使用的数据 map.put("name", "好好学习!"); Student stu1 = new Student(); stu1.setName("小明"); stu1.setAge(18); stu1.setMoney(1000.86f); stu1.setBirthday(new Date()); Student stu2 = new Student(); stu2.setName("小红"); stu2.setMoney(200.1f); stu2.setAge(19); stu2.setBirthday(new Date()); List<Student> friends = new ArrayList<>(); friends.add(stu1); stu2.setFriends(friends); stu2.setBestFriend(stu1); List<Student> stus = new ArrayList<>(); stus.add(stu1); stus.add(stu2); //向数据模型放数据 map.put("stus",stus); //准备map数据 HashMap<String,Student> stuMap = new HashMap<>(); stuMap.put("stu1",stu1); stuMap.put("stu2",stu2); //向数据模型放数据 map.put("stu1",stu1); //向数据模型放数据 map.put("stuMap",stuMap); map.put("point",102920122); //返回freemarker模板的位置,基于resources/templates路径的,freemarker会从resources/templates下面找 return "test1";//这个只能是不带后缀的文件名 }
使用模板文件静态化
-
public void getGenerateTest() throws IOException, TemplateException { //获取配置 Configuration configuration = new Configuration(Configuration.getVersion()); //获取模板 //获取模板路径 String path = this.getClass().getResource("/").getPath(); configuration.setDirectoryForTemplateLoading(new File(path + "/templates/")); //获取模板文件 Template template = configuration.getTemplate("test1.ftl"); //获取数据模型 Map modelMap = getModelMap(); //静态化,生成html页面 String templateIntoString = FreeMarkerTemplateUtils.processTemplateIntoString(template, modelMap); // System.out.println(templateIntoString); InputStream inputStream = IOUtils.toInputStream(templateIntoString); FileOutputStream outputStream = new FileOutputStream(new File("D:/else/test.html")); IOUtils.copy(inputStream,outputStream); //关流 inputStream.close(); outputStream.close(); }
使用模板字符串静态化
-
public void getGenerateTestByString() throws IOException, TemplateException { //获取模板字符串 String templateString="" + "<html>\n" + " <head></head>\n" + " <body>\n" + " 名称:${name}\n" + " </body>\n" + "</html>"; //生成模板 Configuration configuration = new Configuration(Configuration.getVersion()); //获取模板加载器 StringTemplateLoader stringTemplateLoader = new StringTemplateLoader(); //把字符串模板放入模板加载器中 stringTemplateLoader.putTemplate("template", templateString); //设置模板加载器 configuration.setTemplateLoader(stringTemplateLoader); //转成模板 Template template = configuration.getTemplate("template", "utf-8"); //获取模型数据 Map modelMap = getModelMap(); //静态化 String templateIntoString = FreeMarkerTemplateUtils.processTemplateIntoString(template, modelMap); InputStream inputStream = IOUtils.toInputStream(templateIntoString); FileOutputStream fileOutputStream = new FileOutputStream(new File("D:/else/test2.html")); IOUtils.copy(inputStream, fileOutputStream); fileOutputStream.close(); inputStream.close(); }
-