如何防止Spring在使用格式化程序时使用默认转换逻辑
我编写了一个自定义Spring格式化程序(它实现了该接口),用于将表单输入值转换为美元输入的如何防止Spring在使用格式化程序时使用默认转换逻辑,spring,spring-mvc,data-binding,Spring,Spring Mvc,Data Binding,我编写了一个自定义Spring格式化程序(它实现了该接口),用于将表单输入值转换为美元输入的BigDecimal值。格式化程序不接受小数点后两位数以上的值。在这种情况下,格式化程序的parse()方法会引发ParseException public class InputDollarBigDecimalFormatter implements Formatter<BigDecimal> { @Override public BigDecimal parse(S
BigDecimal
值。格式化程序不接受小数点后两位数以上的值。在这种情况下,格式化程序的parse()
方法会引发ParseException
public class InputDollarBigDecimalFormatter
implements Formatter<BigDecimal>
{
@Override
public BigDecimal parse(String text, Locale locale)
throws ParseException
{
// ...
}
@Override
public String print(BigDecimal amount, Locale locale)
{
// ...
}
}
格式化程序工作正常
问题是,当抛出ParseException
时,Spring仍然尝试使用默认转换将输入值转换为bigdecimic
。这意味着100.123
的输入值仍然成功转换为bigdecimic
,即使我的自定义格式化程序抛出一个ParseException
当自定义格式化程序通过抛出ParseException
拒绝输入值时,如何防止Spring将输入值转换为bigdecimic
我正在使用Spring3.1.0
Spring格式化程序是
更新: 在使用调试器逐步完成代码之后,我看到其逻辑在
org.springframework.beans.TypeConverterDelegate
类中。Spring显然是有意这样做的,因此我只能看到以下可能的解决方案:
(1) 如果可能,取消注册BigDecimal
值的默认PropertyEditor
。Spring似乎注册了一个org.springframework.beans.propertyeditors.CustomNumberEditor
,用于将字符串转换为BigDecimal
。当然,此解决方案的缺点是默认的propertyEdit
将不适用于其他BigDecimal
字段(不使用自定义格式设置程序)
(2) 创建一个包装BigDecimal
的Dollar
类,并将自定义格式化程序更改为与Dollar
类一起使用。字段类型也必须更改为Dollar
。在处理这些值时,这会有点麻烦
(3) 可能Spring已经意识到,当自定义格式化程序拒绝某个值时,返回默认的propertyEdit
是不正确的,因此在较新版本的Spring中对此进行了更改。我很怀疑,但如果有人知道任何一种方法,你的帮助将不胜感激
(4) 但也许正确的解决方案是将自定义格式化程序视为通过允许更多格式来帮助默认的PropertyEditor
。除了将值限制为两位小数外,我的自定义格式化程序还允许输入值包含美元符号和逗号。我可以保留这个逻辑,但去掉小数点限制。然后,我可以添加一个自定义bean验证(JSR303)约束,如果该值在小数点后不正好有两位数字(除非它没有),该约束将拒绝该值。我只需要用约束注释我的字段:
@InputDollarBigDecimalFormat
@WholeDollarOrCentsConstraint
private BigDecimal price;
当然,除了格式化程序的错误消息之外,我还必须为约束添加一条错误消息
如果其中任何一个对你来说似乎是正确的解决方案,请随意添加一个带有你的推理的答案。以下是对我有效的答案。如果查看
TypeConverterDelegate
,它所做的事情(以及稍后作为“回退转换”位的一部分)是检查是否有为给定类型注册的自定义PropertyEditor。如果有,它会完全绕过conversionService
部分(它会吞噬异常)和
因此,您可以尝试创建自己的扩展类,而不是您的建议(1)
并将其注册为
BigDecimal
(有关如何执行此操作的示例,请参阅)。然后你可以在你的方法中抛出一个IllegalArgumentException
。只是为了好玩,你有没有试过抛出IllegalArgumentException
。不幸的是,我只是尝试了一下,结果是一样的。在逐步浏览代码之后,我可以看到,对于抛出的任何RuntimeException,结果都是相同的。
@InputDollarBigDecimalFormat
@WholeDollarOrCentsConstraint
private BigDecimal price;