Grails Command Object为何将BigDecimal类型转换为整数?
解决方案
这个问题我之前在项目里也踩过坑,其实就是Grails参数绑定的Locale在搞鬼——默认情况下,它会跟着服务器的区域设置走,如果服务器用的是把逗号当小数点的Locale(比如欧洲一些地区),那提交的0.55就会被当成0,55的错误格式,直接把小数点忽略掉变成整数55。下面给你几个能保住Command Object优势的解决方案,按需选就行:
1. 给Command Object字段添加绑定格式注解
这是最直接的局部解决方案,只针对这个字段生效:
import grails.databinding.BindingFormat class AddOnBodyCommand implements Validateable { @BindingFormat('0.00') BigDecimal addOnPrice }
@BindingFormat('0.00')明确告诉Grails按照两位小数的格式解析参数,强制用点作为小数点分隔符,不管服务器的Locale设置是什么,提交的0.55都会被正确绑定为0.55的BigDecimal,完美解决你的问题,而且不影响其他字段的绑定逻辑,还能继续用Command Object做校验。
2. 全局配置绑定Locale
如果你的整个项目都需要统一用点作为小数点分隔符,可以在全局配置里指定Locale:
在grails-app/conf/application.groovy中添加:
grails.databinding.locale = new Locale('en', 'US')
这样所有的数值类型绑定都会遵循美式Locale的规则(点是小数点,逗号是千分位),一劳永逸解决所有类似的数值绑定问题。
3. 自定义数据绑定转换器(灵活扩展)
如果需要更复杂的转换逻辑(比如同时兼容点和逗号作为小数点),可以自定义一个转换器:
首先创建转换器类:
import org.grails.databinding.converters.ValueConverter import java.math.BigDecimal class CustomBigDecimalConverter implements ValueConverter { @Override boolean canConvert(Object value) { // 只处理字符串类型的输入 value instanceof String } @Override Object convert(Object value) { if (!value) return null // 统一把逗号替换成点,再转成BigDecimal String cleanValue = value.toString().replace(',', '.') return new BigDecimal(cleanValue) } @Override Class<?> getTargetType() { BigDecimal } }
然后在grails-app/conf/spring/resources.groovy里注册这个转换器:
beans = { customBigDecimalConverter(CustomBigDecimalConverter) }
这个方案的好处是灵活性极高,不管前端提交的是0.55还是0,55,都能正确转换成对应的BigDecimal,适合多语言场景的项目。
内容的提问来源于stack exchange,提问作者Rauññ
相关产品推荐
相关产品推荐

