当前位置: 首页 > news >正文

模板引擎:FreeMarker

FreeMarker 是一种模板引擎,主要用于生成文本输出,如网页、电子邮件、配置文件等。

简介

主要特点

  • 强大的模板语言
  • 支持变量、表达式、循环、条件判断等基本编程结构,能够灵活地处理数据并生成动态内容。
  • 可以方便地访问 Java 对象的属性和方法,实现数据的展示和处理。
  • 与 Java 集成良好
  • 可以在 Java 应用程序中轻松地使用 FreeMarker 来生成动态的 HTML、XML 或其他文本格式的输出。
  • 支持与各种 Java 框架集成,如 Spring、Struts 等。
  • 多用途
  • 不仅适用于 Web 开发,还可以用于生成报告、文档、代码模板等多种场景。
  • 可以根据不同的需求定制模板,提高开发效率。

工作原理

  • 模板文件
    • 由 FreeMarker 模板语言编写的文件,包含静态内容和动态指令。
    • 静态内容在生成输出时直接复制到输出中,动态指令则根据数据模型进行处理并生成相应的输出内容。
  • 数据模型
    • 通常是一个 Java 对象,包含要在模板中显示的数据。
    • 可以通过配置或编程的方式将数据模型传递给 FreeMarker 进行处理。
  • 模板引擎
    • 负责解析模板文件和数据模型,并生成最终的输出文本。
    • 根据模板中的指令,从数据模型中获取数据并进行相应的处理,将结果插入到输出中。

使用步骤

  1. 引入 FreeMarker 库 在 Java 项目中,需要添加 FreeMarker 的依赖库。
  2. 创建模板文件
  3. 使用FreeMarker 模板语言编写模板文件,定义静态内容和动态指令。
  4. 准备数据模型 创建一个 Java 对象,包含要在模板中显示的数据。
  5. 配置 FreeMarker 设置模板文件的路径、编码等参数。
  6. 生成输出
  7. 使用 FreeMarker 的API,将数据模型传递给模板引擎,生成最终的输出文本。

总之,FreeMarker 是一个功能强大的模板引擎,能够帮助开发人员快速生成动态的文本输出,提高开发效率。它在 Java 开发中得到了广泛的应用,特别是在 Web 开发领域。

环境搭建&快速入门

导入依赖

<!-- web的起步依赖 -->
<!-- 后端项目一般导入,应为要使用controller功能 -->
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- freemarker的起步依赖 -->
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-freemarker</artifactId>
</dependency>
<!-- lombok的依赖,提供一些注解来简化开发 -->
<dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId>
</dependency>
<!-- apahce 对 java io 的封装,用来操作一些文件 -->
<dependency><groupId>org.apache.commons</groupId><artifactId>commons-io</artifactId><version>1.3.2</version>
</dependency>

freemarker配置

spring:freemarker:# 是否开启Freemarker缓存,本地开发环境建议设置为false,生产环境建议设置为true(生产环境关闭,方便测试)cache: false# 设置字符集charset: UTF-8# 禁止使用请求覆盖模型allow-request-override: false# 检查模板位置是否存在check-template-location: true# 内容类型content-type: text/html# 是否暴露请求属性expose-request-attributes: true# 是否暴露会话属性expose-session-attributes: true# 文件后缀suffix: .ftl# 模板加载路径(在导出为html文件的时候有作用)template-loader-path: classpath:/templates/

创建freemarker的模板存放目录

resource下创建templates目录,此目录为默认的freemarker的模板存放目录。

templates下创建模板文件01-basic.ftl,模板中的插值表达式最终会被freemarker替换成具体的数据。

<!DOCTYPE html>
<html>
<head><meta charset="utf-8"><title>Hello Worldl</title>
</head>
<body>
<b>普通文本 String 展示:</b><br><br> Hello ${name} <br>
<hr>
<b>对象 Student 中的数据展示: </b><br/>姓名: ${stu.name}<br/>年龄: ${stu.age}
<hr>
</body>
</html>

其中的${name}``${stu.name}``${stu.age}是freemarker的插值表达式,插值表达式最终会被替换为具体的数据。

freemarker作为springmvc-一种视图格式,默认情况下SpringMVC支持freemarkeri视图格式。

controller中使用模板

编写一个controller:

import com.shiguang.authtest.entity.Student;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;import java.util.Date;@Controller
@RequestMapping("freemarker")
public class TestFreeMarkerController {@RequestMapping("basic")public String test(Model model){model.addAttribute("name", "freemarker");Student student = new Student();student.setAge(18);student.setName("张三");student.setBirthday(new Date());student.setMoney(1000.86);model.addAttribute("stu", student);return "01-basic";}
}
import lombok.Data;import java.util.Date;@Data
public class Student{private String name;private int age;private Date birthday;private double money;
}

启动项目访问该页面,发现数据绑定到了html上。

注意

  • 模板中的插值表达式${stu.name}model.addAttribute("stu", student)对应,他会读取到该对象下的name属性。
  • Modelorg.springframework.ui.Model包下的。
  • 类上不能使用@RestController注解,因为它返回的是html模板,应该使用@Controller

指令语法

注释

注释,即<#-- -->,介于之间的内容会被忽略。

<#-- 这是注释的内容 -->

插值

即为${},介于之间的内容会被真实数据替代。

<a>hello ${name}</a>

FTL指令(重点)

即为<#>FTL指令</#>,和HTML标记类似,名字前加#予以区分,FreeMarker会解析标签中的表达式或逻辑。

FTL指令(List)

controller类中的写法:

import com.shiguang.authtest.entity.Student;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;import java.util.Date;@Controller
@RequestMapping("freemarker")
public class TestFreeMarkerController {@RequestMapping("basic")public String test(Model model){model.addAttribute("name", "freemarker");Student student1 = new Student();student1.setAge(18);student1.setName("张三");student1.setBirthday(new Date());student.setMoney(1000.86);Student student2 = new Student();student2.setAge(21);student2.setName("李四");student2.setBirthday(new Date());student.setMoney(2009.86);List<Student> students = new ArrayList<>();students.add(student1);students.add(student2);model.addAttribute("stus", students);return "01-basic";}
}

模板中的使用:

<#-- 在controller中Model中添加的是Student的集合(ArryList) -->
<#-- stus是controller中在model中添加的集合数据的key,stu代指集合中被遍历的别名 -->
<#list stus as stu><tr><#-- 使用 别名_index 可以拿到对应元素的下标 --><td>${stu_index}</td><#-- 下标加一可以拿到当前元素的序号 --><td>${stu_index + 1}</td><td>${stu.name}</td><td>${stu.age}</td><td>${stu.money}</td></tr>
</#list>
FTL指令(Map)

controller类中的写法:

import com.shiguang.authtest.entity.Student;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;import java.util.Date;@Controller
@RequestMapping("freemarker")
public class TestFreeMarkerController {@RequestMapping("basic")public String test(Model model){model.addAttribute("name", "freemarker");Student student1 = new Student();student1.setAge(18);student1.setName("张三");student1.setBirthday(new Date());student.setMoney(1000.86);Student student2 = new Student();student2.setAge(21);student2.setName("李四");student2.setBirthday(new Date());student.setMoney(2009.86);Map<String,Student> students = new HashMap<>();stus.put("zc",student1);stus.put("ls",student2);model.addAttribute("stus", students);return "01-basic";}
}

模板中的使用:

<#-- 方式一:可以通过${Model中键的名称['键的名称'].值的属性名}获取map值 -->
<a>${stus['zc'].name}</a>
<#-- 方式二:可以通过${Model中键的名称.键的名称.值的属性名}获取map值 -->
<a>${stus.zc.name}</a>
<#-- map的遍历:map的遍历需要使用list,获取到map中所有key的名称,然后再通过key来访问map -->
<#list stus?keys as key><#-- 使用 别名_index 可以拿到对应元素的下标 --><td>${key_index}</td><#-- 下标加一可以拿到当前元素的序号 --><td>${key_index + 1}</td><td>${stus[key].name}</td><td>${stus[key].age}</td><td>${stus[key].money}</td>
</#list>
FTL指令(If)

controller类中的写法:

import com.shiguang.authtest.entity.Student;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;import java.util.Date;@Controller
@RequestMapping("freemarker")
public class TestFreeMarkerController {@RequestMapping("basic")public String test(Model model){model.addAttribute("name", "freemarker");Student student1 = new Student();student1.setAge(18);student1.setName("张三");student1.setBirthday(new Date());student.setMoney(1000.86);Student student2 = new Student();student2.setAge(21);student2.setName("李四");student2.setBirthday(new Date());student.setMoney(2009.86);List<Student> students = new ArrayList<>();students.add(student1);students.add(student2);model.addAttribute("stus", students);return "01-basic";}
}

模板中的使用:

<#-- if语句基本格式 -->
<#if 判断条件表达式>
<#else>
</#if><#-- 用法示例:如果是“张三”则修改为红色 -->
<#list stus as stu><tr><#if stu.name='张三'><td style="color:red;">${stu.name}</td><#else><td>${stu.name}</td></#if><td>${stu.age}</td><td>${stu.money}</td></tr>
</#list>

注意

在freemarker中,判断是否相等表达式中,=与==是一样。

FTL指令(数学表达式)

FreeMarker表达式中完全支持算数运算,FreeMarker支持的运算符包括:

算数运算符说明
加载+
减法-
乘法*
除法/
求模(求余)%
比较运算符说明
=或者==判断两个值是否相等
!=判断两个值是否不等
>或者gt判断左边值是否大于右边值
>=或者gte判断左边值是否大于等于右边值
<或者lt判断左边值是否小于右边值
<=或者lte判断左边值是否小于等于右边值

:::danger
注意

  • =和!=可以用于字符串、数值和日期来比较是否相等
  • =和!=两边必须是相同类型的值,否则会产生错误
  • 字符串"x",“X”,"×"的比较是不相等的,因为freemarker是精确匹配
  • gt代替>,freemarker会把>解释成FTL标签的结束字符,可使用括号避免这种情况,如<#if(x>y)>

:::

运算符说明
&&逻辑与
!逻辑非
空值处理

变量是否存在

freemarker中如果使用的变量不存在,则会报错。

判断某个变量是否存在使用"??",用法为variable??,如果该变量存在则返回true,否则返回false

我们可以在使用变量的时候,进行存在判断,保证不会报错,例如:

<#if stus??><#-- 详细的对stus的操作 -->
</#>

变量缺失

如果想要给定一个不存在的变量默认值,则可以使用"!",用法为${name!'这是默认值'},如果name变量不存在,这个插值表达式就会返回"这是默认值"这个字符串。

如果是嵌套对象则建议使用()括起来,例如:${(stu.name)!'这是默认值'}

内建函数

内建函数语法格式:变量?函数名称,之前的map名称?keys就是内建函数。

内建函数说明
集合名称?size获取集合的大小
map名称?keys获取map的key的集合
日期类型变量?date显示年月日
日期类型变量?time显示时分秒
日期类型变量?datetime显示日期+时间
日期类型变量?string("yyyy年MM月")定义格式化
数字类型变量?c将数字类型转换为字符串输出(默认情况下的数字类型会每三位之间一个逗号分隔符)
JSON字符串类型?eval将JSON字符串转换为对象类型(转化为对象类型后可以使用插值表达式获取值)

普通文本

文本,仅文本信息,这些不是freemarker的注释、插值、FTL指令的内容会被freemarker忽略解析,直接输出内容。

这是一个普通文本

输出静态化文件

使用freemarker将原生的API界面生成html文件(通过模板+数据)–>生成html界面

我们可以通过使用reemarker.template包下的Configuration,来实现将freemarker模板输出为html页面。

java代码中怎么写:

import freemarker.template.Configuration;public class FreeMarkerTest{// 注意,这里注入的Configuration是哪个包下的@Autowiredprivate Configuration configuration;public void soutFreeMarkerToTtml(){// 指定模板Template template = configuration.getTemplate("01-basic.ftl");//需要在配置文件中的template-loader-path指定加载路径,否则会找不到模板/*** 参数说明* 参数1:模型数据(Map集合)* 参数2:输出流*/template.process(getData(),new FileWriter("d:/test/list.html")); }public Map getData(){Map<String,Object> templateData = new HashMap<>();templateData.put("name", "freemarker");Student student1 = new Student();student1.setAge(18);student1.setName("张三");student1.setBirthday(new Date());student.setMoney(1000.86);Student student2 = new Student();student2.setAge(21);student2.setName("李四");student2.setBirthday(new Date());student.setMoney(2009.86);List<Student> students = new ArrayList<>();students.add(student1);students.add(student2);templateData.put("stus", students);}
}
http://www.xdnf.cn/news/558613.html

相关文章:

  • 基于pyttsx3的文字转语音实现
  • 输出字母在字符串中位置索引
  • 超强吸水宠物垫行业2025数据分析报告
  • 从计算机组成原理寻址方式参悟指针的本质
  • cpu的x86架构跟ARM架构的区别介绍
  • SpringBoot整合LangChain4J
  • 深入探讨 Java 中的函数式编程
  • 9-社区动态(Stack布局)
  • 探秘大数据架构:解锁高效数据处理的密码
  • SpringBoot3+Vue3(1)-后端 请求头校验,jwt退出登录,mybaits实现数据库用户校验
  • 拦截指定注解(FeignClient),补偿重试
  • java异常处理
  • 7-Zip软件下载与使用攻略:如何使用7z格式解压缩更高效?
  • MySQL 8.0 OCP 1Z0-908 题目解析(9)
  • Redis--Redis命令详解
  • linux安装JDK8
  • Python Day27 学习
  • leetcode 33. Search in Rotated Sorted Array
  • vue图片懒加载指令实现
  • 指针深入理解(二)
  • 在表格中使用AI解析通信协议
  • Vue3 父子组件传值, 跨组件传值,传函数
  • 进程——概念及状态
  • 算法训练之分治(快速排序)
  • 浏览器播放 WebRTC 视频流
  • 从客厅到驾驶舱:FSHD 如何成为全场景显示「破局者」
  • 第四十一节:人脸检测与识别-Haar 级联分类器
  • 城市共治的伦理平台愿景
  • 第6天-Python操控摄像头:从入门到实战
  • 四元数中 w xyz 的含义及应用