Freemarker如何输出可用于BigDecimal构造函数的准确BigDecimal值
Freemarker 直接输出对象toString()结果实现方案
核心实现写法
直接通过Freemarker的?api内置器调用BigDecimal对象的原生toString()方法,不会触发框架自动数值转换,模板写法如下:
BigDecimal copy = new BigDecimal("${original?api.toString()}");
方案说明
- 你之前使用的
?c/?computer、?number、?percent等所有数值格式化内置器,都会先将传入对象识别为数值类型,再按照框架内置规则做格式化输出,遇到高精度、极值范围的BigDecimal时,必然会出现精度丢失、科学计数法转换、极小值输出为0等和原生字符串结果不符的问题,无法满足BigDecimal实例化的精度要求。 ?api内置器的作用是直接访问Java对象的原生公共方法,调用过程不会触发Freemarker的自动类型转换、格式化逻辑,拿到的返回值和Java代码里直接调用original.toString()的结果完全一致,不会出现值被篡改的问题。
适配注意事项
- 该写法要求Freemarker版本不低于2.3.22,同时需要在Freemarker配置中开启
api_builtin_enabled开关,即调用configuration.setAPIBuiltinEnabled(true),部分安全默认配置较高的场景会默认关闭该开关,手动开启即可使用。 - 如果受环境限制无法开启
?api功能,不需要额外包装非数值类型对象,只需要在数据模型传入阶段,提前把对应BigDecimal的toString()结果作为独立字符串字段传入,模板中直接引用该字符串字段输出即可,实现成本比包装类低很多。 - 你提到的包装仅带
toString()方法的非数值类型对象的方案属于兜底方案,在上述两种方式都无法使用时可以正常生效。
内容的提问来源于stack exchange,提问作者fkleedorfer
相关产品推荐
相关产品推荐

