FreeMarker入门
一、什么是 FreeMarker?
FreeMarker 是一款 模板引擎: 即一种基于模板和要改变的数据, 并用来生成输出文本(HTML网页,电子邮件,配置文件,源代码等)的通用工具。而FreeMarker最初的设计,是被用来在MVC模式的Web开发框架中生成HTML页面的,它没有被绑定到 Servlet或HTML或任意Web相关的东西上。它也可以用于非Web应用环境中。
模板文件存放在Web服务器上,就像通常存放静态HTML页面那样。当有人来访问这个页面, FreeMarker将会介入执行,然后动态转换模板,用最新的数据内容替换模板中 ${..}
的部分, 之后将结果发送到访问者的Web浏览器中。
访问者的Web浏览器就会接收到例如第一个HTML示例那样的内容 (也就是没有FreeMarker指令的HTML代码),访问者也不会察觉到服务器端使用的FreeMarker。 (当然,存储在Web服务器端的模板文件是不会被修改的;替换也仅仅出现在Web服务器的响应中。)
二、语法指令
1)基础语法种类:
- 注释,即 <#-- -->,介于其之间的内容会被freemarker忽略
- 插值(Interpolation):即
${..}
部分,freemarker会用真实的值代替${..}
- <# >FTL指令</#> 和HTML标记类似,名字前加#予以区分,Freemarker会解析标签中的表达式或逻辑
- 文本,不是freemarker的注释、插值、FTL指令的内容会被freemarker忽略解析,直接输出内容
2)集合指令(List和Map)
- 如果是list集合中存储了多个student对象,可以通过<#list></#list>指令遍历集合
<#list stus as stu> <tr> <td>${stu_index+1}</td> <td>${stu.name}</td> <td>${stu.age}</td> <td>${stu.money}</td> </tr> </#list>
- 如果是map集合中value又是一个map对象,也是通过<#list></#list>指令遍历map集合
<#list stuMap?keys as key > <tr> <td>${key_index + 1}</td> <td>${stuMap[key].name}</td> <td>${stuMap[key].age}</td> <td>${stuMap[key].money}</td> </tr> </#list>
3)if指令
<#list stus as stu > <#if stu.name='小红'> <tr style="color: red"> <td>${stu_index}</td> <td>${stu.name}</td> <td>${stu.age}</td> <td>${stu.money}</td> </tr> <#else > <tr> <td>${stu_index}</td> <td>${stu.name}</td> <td>${stu.age}</td> <td>${stu.money}</td> </tr> </#if> </#list>
三、入门使用
1)导入依赖
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-freemarker</artifactId> </dependency>
2) 创建项目
a、项目结构图:
b、实体类和SpringBoot启动类就不再复述;freemarker.ftl 模板文件如下:
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>Hello World!</title> </head> <body> <b>普通文本 String 展示:</b><br><br> Hello ${name!'====='}<br> <hr> <b>对象Student中的数据展示:</b><br/> 姓名:${(stu.name)!''}<br/> <#-- ${name!''}表示如果name为空显示空字符串--> 年龄:${stu.age} <hr> 当前日期:${today?date}<br> <#--显示年月日: ${today?date}--> 当前日期:${today?time}<br> 当前日期:${today?datetime}<br> 当前日期:${today?string("yyyy年MM月")}<br><#--自定义格式化:${today?string("yyyy年MM月")}--> 整数:${point} <#--point是数字型,使用${point}会显示这个数字的值,每三位使用逗号分隔。--> 字符串:${point?c}<#--如果不想显示为每三位分隔的数字,可以使用c函数将数字型转成字符串输出 指令:${point?c}--> <br> </body> </html>
c、application.yml 配置文件如下:
server: port: 8881 #服务端口 spring: application: name: freemarker-demo #指定服务名 freemarker: cache: false #关闭模板缓存,方便测试 settings: template_update_delay: 0 #检查模板更新延迟时间,设置为0表示立即检查,如果时间大于0会有缓存不方便进行模板测试 suffix: .ftl #指定Freemarker模板文件的后缀名 template-loader-path: classpath:/templates #指定模板文件存放的位置
d、运行测试代码:
package com.heima.freemarker.test; import com.heima.freemarker.FreemarkerApp; import com.heima.freemarker.pojo.Student; import freemarker.template.Configuration; import freemarker.template.Template; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.context.junit4.SpringRunner; import java.io.FileWriter; import java.util.Date; import java.util.HashMap; import java.util.Map; @SpringBootTest(classes = FreemarkerApp.class) @RunWith(SpringRunner.class) public class FreemarkerTest { @Autowired private Configuration configuration; //通过模板文件,填充数据后生成一个html文件 @Test public void test() throws Exception{ //指定模板文件,创建模板对象 Template template = configuration.getTemplate("freemarker.ftl"); /** * 第一个参数:模型数据 * 第二个参数:输出流 */ template.process(getData(),new FileWriter("d:\\index.html")); } private Map<String,Object> getData(){ Map<String,Object> map = new HashMap<>(); // map.put("name","freemarker"); //学生对象 Student student = new Student(); student.setName("张三"); student.setAge(18); map.put("stu",student); //日期类型 map.put("today",new Date()); //长整型 map.put("point",38743874387983398L); return map; } }
e、打开 d:\index.html 路径下的html文件,效果如下:
四、与thymeleaf比较
- 从写代码的角度看,freemarker更习惯于我们的思维。
- 从前后分离开发的角度看thymeleaf更合适,值的绑定都是基于html的dom元素属性的,适合前后联调。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?