我编写了一个自定义 Spring 格式化程序(它实现了 org.springframework.format.Formatter
接口(interface))用于将表单输入值转换为 BigDecimal
美元投入的值(value)。格式化程序不接受小数点后两位以上的值。在这种情况下,ParseException
由格式化程序的 parse()
抛出方法。
public class InputDollarBigDecimalFormatter
implements Formatter<BigDecimal>
{
@Override
public BigDecimal parse(String text, Locale locale)
throws ParseException
{
// ...
}
@Override
public String print(BigDecimal amount, Locale locale)
{
// ...
}
}
格式化程序已注册,因此可以使用名为
@InputDollarBigDecimalFormat
的注释应用它.我的表单支持对象中应用了格式化程序的字段如下所示:
@InputDollarBigDecimalFormat
private BigDecimal price;
格式化程序工作正常。
问题是当
ParseException
被抛出,Spring 仍然尝试将输入值转换为 BigDecimal
使用默认转换。 这意味着 100.123
的输入值仍然成功转换为 BigDecimal
,即使我的自定义格式化程序抛出 ParseException
.如何防止 Spring 将输入值转换为
BigDecimal
当我的自定义格式化程序通过抛出 ParseException
拒绝该值时?我正在使用 Spring 3.1.0。
Spring 格式化程序是 documented here .
更新:
使用调试器单步执行代码后,我发现此操作的逻辑位于
org.springframework.beans.TypeConverterDelegate
中。类(class)。 Spring 显然是故意这样做的,所以我只能看到以下可能的解决方案:(1) 如果可能,取消注册默认
PropertyEditor
对于 BigDecimal
值(value)观。看来 Spring 注册了一个 org.springframework.beans.propertyeditors.CustomNumberEditor
用于将字符串转换为 BigDecimal
.当然,这个解决方案的缺点是默认的 PropertyEditor
不适用于其他 BigDecimal
字段(不使用自定义格式化程序)。(2) 创建
Dollar
包装 BigDecimal
的类并更改自定义格式化程序以使用 Dollar
类(class)。字段类型也必须更改为 Dollar
.在使用这些值时,这会有点麻烦。(3) 也许 Spring 已经意识到回退到默认值
PropertyEditor
是不正确的。当自定义格式化程序拒绝了一个值,因此这在 Spring 的更新版本中已更改。我很怀疑,但如果有人知道任何一种方式,你的帮助将不胜感激。(4) 但也许正确的解决方案是将自定义格式化程序视为只是帮助默认
PropertyEditor
通过允许更多格式。除了将值限制为两位小数之外,我的自定义格式化程序还允许输入值包含美元符号和逗号。我可以保留该逻辑,但删除小数位限制。然后,我可以添加一个自定义 bean 验证 (JSR 303) 约束,如果该值在小数位后不正好有两位数(除非它没有),则该约束将拒绝该值。我只需要用约束注释我的字段:@InputDollarBigDecimalFormat
@WholeDollarOrCentsConstraint
private BigDecimal price;
当然,除了格式化程序的错误消息之外,我还必须为约束添加一条错误消息。
如果其中任何一个对您来说似乎是正确的解决方案,请随时根据您的推理添加答案。
最佳答案
这对我有用。如果您查看 TypeConverterDelegate
, very first它所做的事情(以及后来作为“后备转换”位的一部分)是检查是否有为给定类型注册的自定义 PropertyEditor。如果有,它完全绕过 conversionService
部分(这是吞下您的异常的原因)和 uses the editor instead .
因此,您可以尝试创建自己的扩展类,而不是您的建议 (1)
PropertyEditorSupport
并注册BigDecimal
(参见 here 的示例)。然后你可以抛出 IllegalArgumentException
在您的 setAsText
方法。
关于spring - 使用 Formatter 时如何防止 Spring 使用默认转换逻辑,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32790149/