🌟 一、核心概念

在 FreeMarker 模板中,空白字符(空格、换行、缩进等)在输出 HTML、XML 或其他结构化文本时可能会导致不必要的冗余内容。<#compress> 是 FreeMarker 提供的一个模板指令,用于压缩指定区域内的空白字符,从而优化输出内容的格式与大小。

1. <#compress> 的作用

  • 压缩空白字符:去除多个连续的空格、换行、制表符等。
  • 保留结构语义:在 HTML 中保留 <pre><textarea> 等标签的原始空白。
  • 提升输出质量:适用于生成 HTML、XML、JSON 等格式时去除多余空白。

2. 常见使用场景

场景 说明
HTML 输出优化 减少页面体积,提升加载速度
JSON 输出压缩 去除换行和缩进,便于传输
模板调试输出 去除模板中因换行导致的多余空格
XML 格式化 保持结构清晰同时去除多余空白

🛠️ 二、操作步骤(详细)

✅ 步骤 1:基本使用方式

<#compress>
  <div>
    <p>这是一个测试段落。</p>
  </div>
</#compress>

输出结果:

<div><p>这是一个测试段落。</p></div>

说明:所有换行、缩进都被移除,只保留必要的空格。


✅ 步骤 2:压缩变量输出

<#assign content = "   Hello   World   ">
<#compress>${content}</#compress>

输出:

Hello World

✅ 步骤 3:压缩宏输出内容

<#macro renderParagraph>
  <p>
    这是一个段落内容。
  </p>
</#macro>

<#compress>
  <@renderParagraph />
</#compress>

输出:

<p>这是一个段落内容。</p>

✅ 步骤 4:保留 <pre><textarea> 的空白

<#compress>
  <pre>
    这是一个预格式文本,
    会保留空白。
  </pre>

  <textarea>
    用户输入内容
  </textarea>
</#compress>

输出:

<pre>
    这是一个预格式文本,
    会保留空白。
  </pre><textarea>
    用户输入内容
  </textarea>

说明:FreeMarker 默认会跳过 <pre><textarea> 内容的压缩,保留原始空白。


✅ 步骤 5:压缩并去除首尾空白

<#compress trim_left trim_right>
  Hello   World
</#compress>

输出:

Hello World

可选参数:

  • trim_left:去除左侧空白
  • trim_right:去除右侧空白
  • trim:等价于 trim_left trim_right

✅ 步骤 6:嵌套压缩区域

<#compress>
  <div>
    <#compress>
      <p>嵌套压缩内容</p>
    </#compress>
  </div>
</#compress>

输出:

<div><p>嵌套压缩内容</p></div>

⚠️ 三、常见错误与注意事项

❌ 错误 1:误用 <#compress> 导致内容不可读

<#compress>
  <p>段落1</p>
  <p>段落2</p>
</#compress>

输出:

<p>段落1</p><p>段落2</p>

问题:两个 <p> 标签之间没有换行,HTML 结构清晰度降低。

解决方法:

  • 在需要保留结构换行时,不要使用 <#compress>
  • 或在 HTML 中添加 <!-- --> 作为分隔符

❌ 错误 2:压缩 JSON 导致语法错误

<#compress>
{
  "name": "张三",
  "age": 25
}
</#compress>

输出:

{"name":"张三","age":25}

问题:虽然语法正确,但可读性差。

解决方法:

  • 开发环境保留格式
  • 生产环境再启用 <#compress>

❌ 错误 3:压缩 <pre><textarea> 内容

<#compress>
  <pre>
    123
    456
  </pre>
</#compress>

输出:

<pre>
    123
    456
  </pre>

FreeMarker 默认不会压缩 <pre> 内容,但如果模板结构复杂,仍需注意。


🧠 四、使用技巧

1. 与 <#assign> 结合压缩赋值内容

<#assign cleanText = "<#compress>  Hello   World  </#compress>">
${cleanText}

2. 使用 <#compress> 优化 JSON 输出

<#function toJson data>
  <#return "<#compress>${data?json_string}</#compress>">
</#function>

3. 使用 <#compress> 去除模板中换行导致的空白

<#compress>
  <#list users as user>
    <div>${user.name}</div>
  </#list>
</#compress>

4. 动态控制是否启用压缩

<#if enableCompress>
  <#compress>
    ${content}
  </#compress>
<#else>
  ${content}
</#if>

🏆 五、最佳实践

实践项 建议
生产环境启用压缩 减少输出体积,提升性能
开发环境禁用压缩 提高调试可读性
避免压缩 <pre><textarea> 内容 保留用户输入格式
不要过度压缩 HTML 可能影响结构可读性
在输出 JSON/XML 时启用压缩 提高传输效率
压缩前避免空行和缩进 减少压缩逻辑负担
配合宏使用提高复用性 将压缩逻辑封装为宏

🔧 六、性能优化

优化项 说明
避免在循环中频繁使用 <#compress> 会增加字符串处理开销
减少嵌套压缩区域 多层压缩影响性能
避免压缩大段文本 可考虑在 Java 层预处理
使用 <#compress> 时避免复杂逻辑 如嵌套 <#if><#list>
合理控制压缩范围 只压缩需要压缩的内容,避免全模板压缩

📚 七、总结

维度 内容
核心指令 <#compress>
压缩内容 空格、换行、缩进等空白字符
保留内容 <pre><textarea> 等标签内的空白
调用方式 <#compress>...</#compress>
支持参数 trim_left, trim_right, trim
注意事项 避免影响 HTML 结构、JSON 可读性
最佳实践 生产压缩、开发不压缩、封装宏、避免嵌套
性能优化 避免在循环中使用、减少嵌套、合理控制范围

📌 附录:压缩前后对比示例

原始内容 压缩后内容
<p> Hello World </p> <p>Hello World</p>
<div> \n <span>内容</span> \n</div> <div><span>内容</span></div>
<pre>\n 保留空白\n</pre> <pre>\n 保留空白\n</pre>
{ "name": "张三", "age": 25 } {"name":"张三","age":25}

📚 推荐阅读


📌 总结一句话:
<#compress> 是 FreeMarker 中用于压缩模板输出空白字符的核心指令,通过合理使用可以显著优化 HTML、JSON、XML 等输出内容的大小与结构。但在开发调试、结构可读性等方面需谨慎使用,建议结合环境配置与封装宏实现最佳实践。