Spring Boot+Thymeleaf中String转joda.money类型绑定问题解决
问题根因
Spring MVC 执行Thymeleaf表单绑定时,前端数字输入框提交的值默认以String类型传递到后端,框架内置的类型转换规则未覆盖org.joda.money.Money类型,找不到匹配的转换策略时就会抛出BindException。
实现方案
推荐使用全局类型转换器实现,一次配置全项目生效,无需重复编写绑定逻辑。
方案1:全局Converter(推荐)
- 编写自定义转换类实现Spring的
Converter<S,T>接口,完成String到Money的转换逻辑,可根据业务指定固定默认币种:
import org.joda.money.CurrencyUnit; import org.joda.money.Money; import org.springframework.core.convert.converter.Converter; import org.springframework.stereotype.Component; import java.math.BigDecimal; @Component public class StringToMoneyConverter implements Converter<String, Money> { // 按业务需求替换为对应币种,示例为人民币CNY,美元可改为CurrencyUnit.USD private static final CurrencyUnit DEFAULT_CURRENCY_UNIT = CurrencyUnit.CNY; @Override public Money convert(String sourceVal) { if (sourceVal == null || sourceVal.trim().isEmpty()) { return null; } BigDecimal amount = new BigDecimal(sourceVal.trim()); return Money.of(DEFAULT_CURRENCY_UNIT, amount); } }
- 若转换器未被自动注册(少数低版本Spring Boot需要手动配置),添加WebMVC配置类手动注册:
import org.springframework.context.annotation.Configuration; import org.springframework.format.FormatterRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; @Configuration public class WebConfig implements WebMvcConfigurer { private final StringToMoneyConverter stringToMoneyConverter; public WebConfig(StringToMoneyConverter stringToMoneyConverter) { this.stringToMoneyConverter = stringToMoneyConverter; } @Override public void addFormatters(FormatterRegistry registry) { registry.addConverter(stringToMoneyConverter); } }
方案2:单Controller生效的@InitBinder配置
如果不需要全局生效,只需要在处理Governor表单的Controller中添加绑定逻辑即可:
import org.joda.money.CurrencyUnit; import org.joda.money.Money; import org.springframework.web.bind.WebDataBinder; import org.springframework.web.bind.annotation.InitBinder; import java.beans.PropertyEditorSupport; import java.math.BigDecimal; // 该方法写在你的GovernorController内部 @InitBinder public void initMoneyBinder(WebDataBinder binder) { binder.registerCustomEditor(Money.class, new PropertyEditorSupport() { @Override public void setAsText(String text) { if (text == null || text.trim().isEmpty()) { setValue(null); return; } setValue(Money.of(CurrencyUnit.CNY, new BigDecimal(text.trim()))); } }); }
注意事项
- 如果业务场景支持多币种,可以在前端表单新增币种选择输入项,调整转换器逻辑同时接收币种、金额参数解析生成Money实例即可
- 转换逻辑中可根据需要添加金额格式校验、非法入参异常提示,避免非数字传入导致转换报错
内容的提问来源于stack exchange,提问作者iank
相关产品推荐
相关产品推荐

