🌟 一、核心概念

在 FreeMarker 模板中,数字的显示格式对用户体验和输出内容的准确性至关重要。FreeMarker 提供了多种数字格式化方法,用于控制数字在模板中的输出格式。

1. 核心数字格式化指令

方法 说明 示例
?number 将字符串转换为数字(或保持数字不变) "123"?number → 123
?string 将数字格式化为字符串(支持自定义格式) 12345?string("0,000") → 12,345
?c 使用当前语言环境(locale)的默认格式输出数字 12345.67?c → 12,345.67(取决于语言环境)

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

✅ 步骤 1:使用 ?number 将字符串转为数字

<#assign strNum = "123">
<#assign num = strNum?number>
${num + 10}  <#-- 输出:133 -->

说明:适用于从变量、参数中获取字符串形式的数字并进行计算。


✅ 步骤 2:使用 ?string 自定义数字格式

<#assign price = 12345.6789>
${price?string("0.00")}  <#-- 输出:12345.68 -->

常见格式字符串:

格式 说明 示例
0 强制显示数字(无小数位) 123?string("0") → 123
0.00 保留两位小数 123.4?string("0.00") → 123.40
0,000 千分位分隔 1234567?string("0,000") → 1,234,567
0.000E0 科学计数法 12345?string("0.000E0") → 1.235E4

✅ 步骤 3:使用 ?c 输出本地化数字格式

<#setting locale="zh_CN">
<#assign amount = 1234567.89>
${amount?c}  <#-- 输出:1,234,567.89 -->

说明:?c 表示“计算机格式(computer format)”,会根据当前 locale 设置输出格式。


✅ 步骤 4:处理百分比、货币格式(结合 ?string

<#assign rate = 0.75>
${rate?string("0.00%")}  <#-- 输出:75.00% -->

<#assign money = 12345.67>
${money?string("$0,000.00")}  <#-- 输出:$12,345.67 -->

✅ 步骤 5:将数字转换为字符串用于逻辑判断

<#assign num = 123>
<#if num?string == "123">
  <p>数字等于 123</p>
</#if>

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

❌ 错误 1:对非数字使用 ?number

<#assign text = "abc">
${text?number}  <#-- 报错:无法将字符串转换为数字 -->

解决方法:

  • 确保变量是数字或可转换为数字的字符串
  • 或使用 <#if var?is_number> 进行判断

❌ 错误 2:格式字符串不合法

${123?string("invalid-format")}  <#-- 报错:格式字符串非法 -->

解决方法:

  • 使用合法的格式字符串,如 "0,000", "0.00%"
  • 参考 Java 的 DecimalFormat 语法规范

❌ 错误 3:误用 ?c 导致格式不一致

<#setting locale="en_US">
<#assign num = 1234567.89>
${num?c}  <#-- 输出:1,234,567.89 -->

<#setting locale="de_DE">
${num?c}  <#-- 输出:1.234.567,89 -->

说明:?c 输出依赖当前语言环境设置,不同地区格式不同。


❌ 错误 4:未设置 locale 导致 ?c 输出异常

<#assign num = 12345.67>
${num?c}  <#-- 如果未设置 locale,可能输出无千分位或异常格式 -->

解决方法:

  • 使用 <#setting locale="zh_CN"> 明确设置语言环境

🧠 四、使用技巧

1. 数字格式统一管理(宏封装)

<#macro formatNumber num pattern>
  ${num?string(pattern)}
</#macro>

<@formatNumber num=12345.67 pattern="0,000.00" />  <#-- 输出:12,345.67 -->

2. 本地化货币显示(结合 ?c 与货币符号)

<#setting locale="zh_CN">
<#assign amount = 12345.67>
¥${amount?c}

3. 判断变量是否为数字

<#if value?is_number>
  <p>这是一个数字:${value}</p>
<#else>
  <p>这不是一个数字</p>
</#if>

4. 动态格式化(根据变量值选择格式)

<#assign num = 1234567.89>
<#if num >= 1000000>
  ${num?string("0.00M")}  <#-- 输出:1.23M -->
<#else>
  ${num?string("0,000.00")}
</#if>

🏆 五、最佳实践

实践项 建议
使用 ?number 转换字符串为数字 用于逻辑判断或计算
使用 ?string 实现精确格式控制 如千分位、百分比、货币等
使用 ?c 支持本地化输出 适用于多语言项目
避免对非数字调用格式化方法 使用 ?is_number 提前判断
统一数字格式宏封装 提高可维护性
明确设置 locale 避免因语言环境不同导致格式混乱
对大数字使用科学计数法 提高可读性

🔧 六、性能优化

优化项 说明
避免频繁调用 ?string 可将格式化结果缓存为变量
减少 <#if> 中多次调用格式化 提前格式化并赋值
避免在 <#list> 中重复格式化 可在数据模型中预处理
减少复杂格式字符串使用 0,000.000E0 等复杂格式会增加解析开销
合理使用 ?c 适用于多语言项目,但需配合 locale 设置

📚 七、总结

维度 内容
核心方法 ?number, ?string, ?c
功能 数字转换、格式化输出、本地化支持
注意事项 避免非数字调用、格式字符串合法性、locale 设置
最佳实践 封装宏、预处理、统一格式、合理使用 locale
性能优化 缓存变量、避免重复调用、减少复杂格式解析

📌 附录:数字格式化示例汇总

输入数字 格式表达式 输出结果(示例)
12345.6789 0.00 12345.68
1234567 0,000 1,234,567
0.75 0.00% 75.00%
12345.67 $0,000.00 $12,345.67
1234567.89 0.000E0 1.235E6
1234567.89 ?c(zh_CN) 1,234,567.89
1234567.89 ?c(de_DE) 1.234.567,89

📚 推荐阅读


📌 总结一句话:
FreeMarker 提供了强大的数字格式化能力,通过 ?number, ?string, ?c 等内置方法,可以实现字符串转数字、自定义格式输出、本地化数字显示等功能。掌握其使用方式、注意事项与最佳实践,是构建高质量、多语言模板系统的关键。