spring - 使用 Formatter 时如何防止 Spring 使用默认转换逻辑

标签 spring spring-mvc data-binding

我编写了一个自定义 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/

相关文章:

java - 如何在 spring 中创建一个非阻塞的@RestController webservice?

java - Gradle 将构建环境注入(inject) WebApplicationInitializer

ajax - 使用Ajax处理表单时,模型addAttribute()无法加载到相应的JSP标签

java - 在 docker 容器中几分钟后重置 Spring Boot 连接

spring - 如何正确地将复选框绑定(bind)到 thymeleaf 中的对象列表?

java - Spring MultipartFiles 在混合多部分中重复文件

java - SpringMVC 错误

Silverlight DataBinding,避免缺少属性时出现 BindingExpression Path 错误,而是隐藏控件

asp.net - 将 <a> href 绑定(bind)到 Code Behind 属性

c# - 在 WPF 中,如何绑定(bind)到 ViewModel 并将各种 XAML 元素绑定(bind)到 ViewModel 的方法?