打个比方: 用户看到的金钱数值都是保留两位的,但是实际service计算、存储在DB中的数值都是保留多位的,【至于四舍五入还是奇进偶不进就结合具体的业务处理】最后扣款是扣除两位小数
假如所有和价格相关的属性都在service层自己进行倍数的放大和缩小,代码显得十分的冗余!毕竟不是主业务代码,次业务代码都要想方设法的抽取出来!
例如 在数据库中存储都是四位小数的存储,在service层都是四位小数的运算,最后的输出结果使用序列化器,缩小10000倍,交给前端保留两位小数显示。
配置Jackson自定义序列化器、反序列化器
public class MoneyDeserializer extends StdDeserializer<Long> {
public MoneyDeserializer() {
this(null);
}
public MoneyDeserializer(Class<?> vc) {
super(vc);
}
/**
* 金额反序列化
* 小数 -> Long
* 保留四位小数,放大10000倍
*/
@Override
public Long deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {
String text = p.getText().trim();
double v = Double.parseDouble(text);
return (long) (v * 10000);
}
}
public class MoneySerializer extends StdSerializer<Long> {
public MoneySerializer() {
this(null);
}
public MoneySerializer(Class<Long> t) {
super(t);
}
/**
* 金额序列化
* Long -> 小数
* 缩小10000倍
*/
@Override
public void serialize(Long value, JsonGenerator gen, SerializerProvider provider) throws IOException {
BigDecimal result = new BigDecimal(value.toString()).divide(new BigDecimal("10000"), 4, BigDecimal.ROUND_HALF_EVEN);
gen.writeNumber(result.toPlainString());
}
}
使用Jackson自定义序列化器、反序列化器
- VO接收参数,将金钱数值放大10000倍
@Data
public class CreateNormalVO {
@NotNull(message = "产品标价最小值不能为空")
@JsonDeserialize(using = MoneyDeserializer.class)
private Long productPriceMin;
@NotNull(message = "产品标价最大值不能为空")
@JsonDeserialize(using = MoneyDeserializer.class)
}
- 将service层处理完的entity赋值给 下面这个输出的VO,将金钱数值缩小10000倍给前端保留两位显示处理
@Data
public class OutputNormalProductVO {
@JsonSerialize(using = MoneySerializer.class)
protected Long productPriceMin;
@JsonSerialize(using = MoneySerializer.class)
protected Long productPriceMax;
}