【freemarker】创建html页面
freemarker 创建html页面
- freemarker 简介
- 什么是 FreeMarker?
- 核心概念
- 1. 模板文件 (.ftl)
- 2. 数据模型
- 3. 配置
- 常见用法
- 完整示例
- pom文件
- 模板配置
- ftl文件
- 测试接口
freemarker 简介
什么是 FreeMarker?
FreeMarker 是一个基于 Java 的模板引擎,用于生成文本输出(HTML网页、电子邮件、配置文件、源代码等)。它采用 MVC 模式,将业务逻辑(Java代码)与表现层(模板)分离。
核心概念
1. 模板文件 (.ftl)
包含静态文本和 FreeMarker 指令的文本文件。
2. 数据模型
Java 对象(Map、List、POJO等)作为模板的数据源。
3. 配置
通过 Configuration 类进行模板引擎的配置。
常见用法
- 变量输出
ftl
${user.name} <#-- 简单变量 -->
${user.address.city!} <#-- 空值处理 -->
${user.age?string("0")} <#-- 数字格式化 -->
${user.birthday?string("yyyy-MM-dd")} <#-- 日期格式化 -->
- 条件判断
ftl
<#if user.role == "admin"><p>管理员用户</p>
<#elseif user.role == "user"><p>普通用户</p>
<#else><p>未知角色</p>
</#if><#-- 空值判断 -->
<#if user.name??>用户名存在: ${user.name}
<#else>用户名为空
</#if>
- 循环遍历
ftl
<#-- 列表遍历 -->
<#list users as user><div>${user_index + 1}. ${user.name} - ${user.email}</div><#if user_has_next><hr></#if>
</#list><#-- Map遍历 -->
<#list userMap?keys as key>Key: ${key}, Value: ${userMap[key]}
</#list><#-- 范围循环 -->
<#list 1..5 as i>${i}
</#list>
- 宏定义(函数)
ftl
<#-- 定义宏 -->
<#macro userCard user className=""><div class="user-card ${className}"><h3>${user.name}</h3><p>年龄: ${user.age}</p><p>邮箱: ${user.email!''}</p></div>
</#macro><#-- 使用宏 -->
<@userCard user=currentUser className="highlight"/>
<@userCard user=adminUser/>
- 包含其他模板
ftl
<#-- 包含头部 -->
<#include "header.ftl"><#-- 引入并传递参数 -->
<#include "footer.ftl" encoding="UTF-8" parse=true>
- 指令使用
ftl
<#-- 设置变量 -->
<#assign total = 0>
<#assign welcomeMsg = "欢迎, " + user.name><#-- 全局变量 -->
<#global siteName = "我的网站"><#-- 尝试捕获异常 -->
<#attempt>${possiblyNullValue!}
<#recover>值不存在或出错
</#attempt>
- 内置函数
ftl
<#-- 字符串操作 -->
${str?upper_case} <#-- 转大写 -->
${str?lower_case} <#-- 转小写 -->
${str?cap_first} <#-- 首字母大写 -->
${str?length} <#-- 长度 -->
${str?substring(0,5)} <#-- 子字符串 -->
${str?contains("search")?string("yes","no")} <#-- 包含判断 --><#-- 数字操作 -->
${number?round} <#-- 四舍五入 -->
${number?floor} <#-- 向下取整 -->
${number?ceiling} <#-- 向上取整 --><#-- 列表操作 -->
${list?size} <#-- 列表大小 -->
${list?join(", ")} <#-- 列表连接 -->
${list?sort} <#-- 排序 -->
${list?reverse} <#-- 反转 --><#-- 日期操作 -->
${date?string("yyyy-MM-dd HH:mm:ss")}
${date?time} <#-- 时间部分 -->
${date?date} <#-- 日期部分 -->
完整示例
pom文件
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><groupId>org.example</groupId><artifactId>frame-test</artifactId><version>1.0-SNAPSHOT</version><properties><maven.compiler.source>8</maven.compiler.source><maven.compiler.target>8</maven.compiler.target></properties><parent><artifactId>spring-boot-starter-parent</artifactId><groupId>org.springframework.boot</groupId><version>2.3.5.RELEASE</version></parent><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId></dependency><dependency><groupId>org.freemarker</groupId><artifactId>freemarker</artifactId><version>2.3.32</version></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-context-support</artifactId></dependency></dependencies></project>
模板配置
package com.test.frame.component;import freemarker.template.Template;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.ui.freemarker.FreeMarkerTemplateUtils;
import org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer;import java.util.Map;@Component
public class TemplateFtl {private final FreeMarkerConfigurer freeMarkerConfigurer;@Autowiredpublic TemplateFtl(FreeMarkerConfigurer freeMarkerConfigurer) {this.freeMarkerConfigurer = freeMarkerConfigurer;}public String render(Map<String, Object> model, String ftlName) throws Exception {//获取模板Template template = freeMarkerConfigurer.getConfiguration().getTemplate(ftlName);// 渲染模板为字符串return FreeMarkerTemplateUtils.processTemplateIntoString(template, model);}
}
ftl文件
<!DOCTYPE html>
<html>
<head><meta charset="UTF-8"><title>数据统计表</title><style>table {border-collapse: collapse;width: 100%;margin: 20px 0;}th, td {border: 1px solid #ddd;padding: 8px;text-align: center;}th {background-color: #f2f2f2;font-weight: bold;}.statistics-row {background-color: #e6f7ff;font-weight: bold;}</style>
</head>
<body>
<h2>数据统计表</h2><table><thead><tr><#list headers?values as headerName><th>${headerName}</th></#list></tr></thead><tbody><#-- 数据行 --><#list dataList as dataItem><tr><#list headers?keys as fieldName><td>${dataItem[fieldName]!''}</td></#list></tr></#list><#-- 统计行 --><tr class="statistics-row"><#-- 计算需要合并的列数(表头总数减1) --><#assign colspanCount = headers?size - 1><td colspan="${colspanCount}">统计</td><td><#-- 计算成绩总分和平均分 --><#assign totalScore = 0><#assign count = 0><#list dataList as dataItem><#if dataItem.score??><#assign totalScore = totalScore + dataItem.score><#assign count = count + 1></#if></#list><#if count gt 0><#assign averageScore = totalScore / count>总分: ${totalScore?string("0.##")}平均分: ${averageScore?string("0.##")}<#else>无数据</#if></td></tr></tbody>
</table>
</body>
</html>
目录位置
测试接口
package com.test.frame.contronller;import com.test.frame.component.TemplateFtl;
import com.test.frame.dto.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;import java.util.*;@RestController
@RequestMapping("user")
public class UserController {@AutowiredTemplateFtl templateFtl;@GetMapping("test")public String getHtml() throws Exception {User u1 = new User(1,"lili",21,98.65d);User u2 = new User(2,"lucy",23,78.6d);User u3 = new User(3,"jack",20,68.25d);List<User> userList = new ArrayList<>();userList.add(u1);userList.add(u2);userList.add(u3);Map<String,String> header = new LinkedHashMap<>();header.put("id","id");header.put("name","姓名");header.put("age","年龄");header.put("score","成绩");Map<String,Object> model = new HashMap<>();model.put("headers",header);model.put("dataList",userList);return templateFtl.render(model,"User.ftl");}
}
测试结果