Spring Web中FastMoney使用及Lombok、表单转换问题
解决方案
1. 用Lombok配置FastMoney类型字段
FastMoney没有公共无参构造函数,无法通过常规方式直接实例化,需要结合Lombok的扩展能力和Jackson自定义反序列化来解决:
调整DTO的Lombok注解与构造逻辑
修改PaymentDto,通过自定义Builder方法来适配FastMoney的实例化规则,同时保留Lombok的便利性:
@Data @Builder @AllArgsConstructor @NoArgsConstructor // 为Jackson反序列化提供基础构造(可选,若自定义反序列化无需则可省略) public class PaymentDto { private String recipientName; @JsonInclude @JsonDeserialize(using = FastMoneyDeserializer.class) // 关联自定义反序列化器 private FastMoney amount; // 自定义Builder方法,支持传入纯金额数值,自动绑定默认货币 public static class PaymentDtoBuilder { public PaymentDtoBuilder amount(BigDecimal amount) { // 这里用业务约定的默认货币,比如USD或系统默认区域货币 this.amount = FastMoney.of(amount, CurrencyUnit.getInstance(Locale.getDefault())); return this; } public PaymentDtoBuilder amount(String amountStr) { // 支持解析带货币的字符串,如"100.00 USD" this.amount = FastMoney.parse(amountStr); return this; } } }
添加Jackson自定义反序列化器
编写反序列化器处理前端传入的纯数字或字符串金额,自动补全默认货币:
public class FastMoneyDeserializer extends JsonDeserializer<FastMoney> { @Override public FastMoney deserialize(JsonParser p, DeserializationContext ctxt) throws IOException { String value = p.getText(); // 处理纯数字格式的金额,绑定默认货币 if (value.matches("\\d+(\\.\\d+)?")) { return FastMoney.of(new BigDecimal(value), CurrencyUnit.of("USD")); } // 处理带货币标识的字符串格式 return FastMoney.parse(value); } }
配置完成后,Postman提交{"amount": 100.00}或{"amount": "100.00"}时,会自动转换为带默认货币的FastMoney实例。
2. Thymeleaf表单提交值转换为FastMoney
Spring MVC无法自动将表单字符串转换为FastMoney,需要自定义类型转换器:
实现Converter接口
@Component public class StringToFastMoneyConverter implements Converter<String, FastMoney> { @Override public FastMoney convert(String source) { // 处理表单提交的纯数字金额,绑定默认货币 if (source.matches("\\d+(\\.\\d+)?")) { return FastMoney.of(new BigDecimal(source), CurrencyUnit.of("USD")); } // 支持用户输入带货币的格式,如"100.00 USD" return FastMoney.parse(source); } }
注册转换器(可选)
如果Spring未自动扫描到转换器,可在Web配置类中手动注册:
@Configuration public class WebConfig implements WebMvcConfigurer { @Override public void addFormatters(FormatterRegistry registry) { registry.addConverter(new StringToFastMoneyConverter()); } }
之后Thymeleaf表单提交的金额(如<input type="text" name="amount" value="100.00"/>)会自动转换为FastMoney实例并绑定到PaymentDto。
补充说明
JavaMoney的设计强制绑定货币,无货币的金额不具备业务意义。如果暂时不需要前端指定,建议后端统一使用业务约定的默认货币,后续再扩展多货币支持。
内容的提问来源于stack exchange,提问作者happybuddha
相关产品推荐
相关产品推荐

