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

09_Spring Boot 整合 Freemarker 模板引擎的坑

09_Spring Boot 整合 Freemarker 模板引擎的坑

1.背景:

springboot 版本:3.0.2

2. 引入依赖

pom.xml 中添加:

<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId>
</dependency><!-- Spring Boot Freemarker 依赖 -->
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-freemarker</artifactId>
</dependency>

3. 配置 freemarker

application.yml 中进行如下配置

spring:freemarker:cache: falsecharset: UTF-8check-template-location: truecontent-type: text/htmlexpose-request-attributes: trueexpose-session-attributes: truerequest-context-attribute: request

4. 编写控制层代码

  • 需要使用 @Controller,而非 @RestController
  • @Controller 用于返回视图页面,@RestController 会默认返回 JSON,不适合页面跳转。

示例:

@Controller
public class FreemarkerController {@GetMapping("/freemarker")public String freemarkerTest(Model model) {model.addAttribute("message", "Hello Freemarker!");return "freemarker"; // 视图名称,对应模板文件}
}

5. 模板文件位置与命名

  • Freemarker模板文件放置于 src/main/resources/templates/ 目录。
  • 即模板文件命名为 freemarker.ftl

目录结构示例:

src└─ main└─ resources└─ templates└─ freemarker.ftl

freemarker.ftl 模板内容如下:

<!DOCTYPE html>
<html>
<head lang="en"><meta charset="UTF-8"><title>Freemarker</title>
</head>
<body>
</body>
</html>

6. 启动项目

启动后访问地址,并没有想象中的顺利,直接报错了。

第一次报错:404 错误

  • 可能是缓存或项目未正确构建导致。
  • 解决:执行 Maven clean,重新编译打包,再启动。

第二次报错:还是 404 错误

在这里插入图片描述

经过查询才知道,Spring Boot 2.2.0 起,默认模版后缀名为 ftlh

解决方案:
  • 将模板文件后缀由 .ftl 改为 .ftlh
  • 确认模板文件路径和名称与返回视图名一致。

例如:

templates/freemarker.ftlh

控制器返回:

return "freemarker"; // 自动匹配 freemarker.ftlh

templates/freemarker.ftlh

控制器返回:

return "freemarker"; // 自动匹配 freemarker.ftlh

Spring Boot 2.2.0 及以上版本 Freemarker 模板后缀名默认是 .ftlh,而不是传统的 .ftl

http://www.lryc.cn/news/595363.html

相关文章:

  • 用简鹿视频格式转换器轻松制作 GIF 表情包教程
  • 牛客周赛 Round 101(题解的token计算, 76修地铁 ,76选数,76构造,qcjj寄快递,幂中幂plus)
  • 解决vscode中vue格式化后缩进太小的问题,并去除分号 - 设置Vetur tabSize从2到4,设置prettier取消分号semi
  • 元宇宙工厂漫游指南:VR可视化在设备巡检与远程运维中的沉浸式应用
  • zabbix企业级分布式监控
  • Java 实现 UDP 多发多收通信
  • C++unordered系列的map和set类(封装)
  • WAMP配置局域网https服务
  • C# 实现:动态规划解决 0/1 背包问题
  • Nacos 探活机制深度解析:临时 / 永久实例差异及与 Sentinel 的熔断协作
  • OpenAI API(1)补全Responses(Chat Completions)API和记忆Assistants API对比分析
  • Java 大视界 -- 基于 Java 的大数据分布式计算在地球物理勘探数据处理与地质结构建模中的应用(356)
  • 16 BTLO 蓝队靶场 Drill Down 解题记录
  • 前缀和题目:元素和小于等于阈值的正方形的最大边长
  • 计算机发展史:互联网时代的万物互联与全球变革
  • MySQL 17 如何正确地显示随机消息?
  • 【爬虫】06 - 自动化爬虫selenium
  • 元宇宙与游戏:虚实交融的数字文明新纪元
  • ni-app 对鸿蒙的支持现状
  • 深入浅出 BeanUtil.copyProperties:Java 属性复制的利器与避坑指南
  • compser json和lock的作用区别
  • 基于ArcFace损失函数训练的人脸特征提取模型
  • PDF 表单字段属性详解
  • Java学习----NIO模型
  • 识别PDF中的二维码
  • 软件中如何实现自动记忆上一次选的打印机(Python示例)
  • 数据结构 之 【排序】(直接插入排序、希尔排序)
  • 二分查找-35.搜索插入位置-力扣(LeetCode)
  • C语言-字符串数组
  • Vue过度与动画效果