Java|FreeMarker 复用 layout

项目里的页面一多,重复的页面布局就不可避免地冒了出来,作为程序员,消除重复,义不容辞。那么,今天就来聊聊如何在 FreeMarker 中复用页面 layout,让代码更优雅、更易维护。

常规做法:include

FreeMarker 提供了 include 指令,可以把一些公共页面元素单独提取出来,然后在需要的地方通过 include 引入,例如:

less 复制代码
<#-- includes/header.ftl -->
<p>我来组成头部</p>
less 复制代码
<#-- includes/footer.ftl -->
<p>我来组成底部</p>
javascript 复制代码
<#-- somepage.ftl -->
<#include "./includes/header.ftl">
<p>我是页面内容</p>
<#include "./includes/footer.ftl">
<script>
// 这里是一些 JavaScript 代码
</script>

去除重复:抽象 layout

但是所有类似的页面都要手写这个结构也挺麻烦的,更糟糕的是,一旦这些页面的结构发生变化,得在 N 个页面里反复修改,想想都头大。

很多博客引擎(比如 Jekyll)都支持 layout 功能,允许我们定义统一的页面布局,具体页面只需专注于内容。

FreeMarker 虽然没有内置 layout,但我们可以用 macro 来实现类似的效果。

比如,抽象出一个 layout/page.ftl 文件,作为布局模板:

arduino 复制代码
<#-- layout/page.ftl -->
<#macro layout body js="">
<#include "../includes/header.ftl" />
${body}
<#include "../includes/footer.ftl" />
${js}
</#macro>

然后在需要的页面这样用:

typescript 复制代码
<#import "./layout/page.ftl" as base>
<#assign body>
<p>我是页面内容</p>
<p>当前时间:<span id="current-time">${.now?string("yyyy-MM-dd HH:mm:ss")}</span></p>
</#assign>
<#assign js>
<script>
// 每隔一秒刷新当前时间
setInterval(function() {
    document.getElementById("current-time").innerHTML = new Date().toLocaleString();
}, 1000);
</script>
</#assign>
<@base.layout body=body js=js />

页面效果如下:

减少手工输入:code snippets

虽然布局复用问题解决了,但每次新建页面还得手写一遍结构,还是不够优雅。程序员的信条是:能自动化的绝不手动!

这时就轮到编辑器/IDE 的 code snippets 功能登场了。把上面的结构定义成代码片段,新建页面时只需输入一个触发词,基本结构就自动生成。

以 VSCode 为例,可以在项目的 .vscode 目录下新建 layout.code-snippets 文件,内容如下:

swift 复制代码
{
    "page_layout": {
        "scope": "ftl",
        "prefix": "layout:page",
        "body": [
            "<#import \"./layout/page.ftl\" as base>",
            "",
            "<#assign body>",
            "",
            "",
            "",
            "</#assign>",
            "",
            "<#assign js>",
            "",
            "<script>",
            "",
            "</script>",
            "",
            "</#assign>",
            "",
            "<@base.layout body=body js=js />"
        ],
        "description": "Page layout template for FTL files"
    }
}

这样新建 .ftl 文件后,输入 layout:page,页面布局结构就自动生成了。

如图所示:

IntelliJ IDEA 也可以用 Live Templates 实现同样的效果。

本文相关代码和示例已上传至 GitHub,见 github.com/mzlogin/lea... 的 freemarker-test 目录。


如果读完文章有收获,可以关注我的微信公众号「闷骚的程序员」并🌟设为星标🌟,随时阅读更多内容。

相关推荐
腾渊信息科技公司38 分钟前
Spring Boot对接MES实战:视觉检测数据自动同步方案
java·人工智能·spring boot·后端·计算机视觉·ai·软件需求
爱笑的源码基地2 小时前
高并发 Redis 缓存门诊HIS系统源码,含财务统计药房进销存
java·程序·门诊系统·诊所系统·云诊所源码
IT_陈寒2 小时前
Vue这个特性差点让我加班到凌晨,谁懂啊
前端·人工智能·后端
段一凡-华北理工大学2 小时前
向量数据库实战:选型、调优与落地~系列文章12:文本分块策略实战:chunk_size 怎么选?重叠多少?
开发语言·数据库·后端·oracle·rust·工业智能体·高炉智能化
码事漫谈3 小时前
1999年的电商前夜和2026年的AI前夜 历史押韵但从不重复
后端
Conan在掘金3 小时前
鸿蒙报错速查:arkts-strict-typing Property does not exist on type 'object',object 装函数就炸,根因 + 真解法
后端
颜酱3 小时前
01 | 骨架搭建:FastAPI + Vue 跑通第一个 SSE 流式问答
前端·人工智能·后端
程序员cxuan4 小时前
Grok Build 被众人唾骂,结果老马把它开源了
人工智能·后端·程序员
莫逸风4 小时前
【AgentScope 2.0】 0. 学习指南
java·llm·agent·agentscope
从零开始的代码生活_4 小时前
C++ 继承详解:访问控制、对象模型、菱形继承与设计取舍
开发语言·c++·后端·学习·算法