1. 背景
在输入价格的时候,需要对价格的范围和小数的长度做校验。
当前 JSR-303 已经对 BigDecimal 的最小值和最大值做了通用的校验注解。
@DecimalMin(min = “0.01”, message = “报错内容”)
@DecimalMax(min = “99999999.99”, message = “报错内容”)
需要注意的是,上述的两个注解并不能对null
的 BigDecimal 对象做校验,所以通常和@NotNull
联合使用。
2. 需求
针对 BigDecimal 类型的对象做小数位数的长度校验,指定 value = 2
, 就要强制要求被修饰的对象的小数长度为2,否则报错。
3. 实现步骤
因为有
@DecimalMin(...)
打头阵,所以就稍微参考一下它的实现。
- 拿到 BigDecimal 的小数位数
BigDecimal.scale()
注意!该方法不会省略去掉小数的末尾0部分,即
150.0500 ->4
的sacle()
值是4。
- SpringMVC 会去掉传入的小数末尾的0吗?或给整数做补0操作?
不会去掉小数末尾的0也不会给整数做补0操作。
4. 代码展示
DecimalScaleLength
@Target({FIELD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Constraint(validatedBy = DecimalScaleLengthValidator.class)
public @interface DecimalScaleLength {
String message() default "";
int value();
Class<?>[] groups() default { };
Class<? extends Payload>[] payload() default { };
}
DecimalScaleLengthValidator
@Slf4j
public class DecimalScaleLengthValidator implements ConstraintValidator<DecimalScaleLength, BigDecimal> {
/**
* 小数位数
*/
protected Integer targetScale;
@Override
public void initialize(DecimalScaleLength constraintAnnotation) {
targetScale = constraintAnnotation.value();
}
@Override
public boolean isValid(BigDecimal value, ConstraintValidatorContext context) {
// 对于空的小数位数校验,直接返回 true
if (value == null) {
return true;
}
log.info("DecimalScaleLengthValidator sourceValue: {}, targetScale: {}", value, targetScale);
int scale = value.scale();
return Integer.valueOf(scale).equals(targetScale);
}
}