13

我正在寻找一种方法来验证java.lang.DoubleSpring 命令 bean 中的字段的最大值和最小值(一个值必须位于给定的值范围之间),例如,

public final class WeightBean
{
     @Max(groups={ValidationGroup.class}, value=Double.MAX_VALUE, message="some key or default message")
     @Min(groups={ValidationGroup.class}, value=1D, message="some key or default message")
     private Double txtWeight;  //Getter and setter.

     public interface ValidationGroup{}         
}

但两者@Max@Min不能java.lang.Double取值。

请注意,由于舍入错误,不支持 double 和 float(某些提供程序可能会提供一些近似支持)

那么验证这些字段的方法是什么?

我正在使用 Spring 3.2.0 和 Hibernate Validator 4.3.1 CR1。

4

7 回答 7

11

您可以使用注释,但根据具体情况,您可能会得到错误的结果。这是双打和 imo 在许多情况下的普遍问题,应该避免使用 _Double_s。也许切换到不同的类型是最好的解决方案?例如大十进制?

于 2013-03-19T16:18:27.533 回答
8

如果您已切换到 BigDecimal(或 BigInteger),则可以使用@DecimalMin@DecimalMax。但这仍然不是 float 或 double 的解决方案。

于 2015-01-28T20:14:01.667 回答
5

我避免了doublefloat类型,并实现了一个自定义验证器,它可以BigDecimal根据精度和比例来验证一个值。

约束描述符。

package constraintdescriptor;

import constraintvalidator.BigDecimalRangeValidator;
import java.lang.annotation.Documented;
import static java.lang.annotation.ElementType.ANNOTATION_TYPE;
import static java.lang.annotation.ElementType.FIELD;
import static java.lang.annotation.ElementType.METHOD;
import java.lang.annotation.Retention;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
import java.lang.annotation.Target;
import javax.validation.Constraint;
import javax.validation.Payload;

@Target({METHOD, FIELD, ANNOTATION_TYPE})
@Retention(RUNTIME)
@Constraint(validatedBy = BigDecimalRangeValidator.class)
@Documented
public @interface BigDecimalRange {
    public String message() default "{java.math.BigDecimal.range.error}";
    public Class<?>[] groups() default {};
    public Class<? extends Payload>[] payload() default {};

    long minPrecision() default Long.MIN_VALUE;
    long maxPrecision() default Long.MAX_VALUE;
    int scale() default 0;
}

约束验证器。

package constraintvalidator;

import constraintdescriptor.BigDecimalRange;
import java.math.BigDecimal;
import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;

public final class BigDecimalRangeValidator implements ConstraintValidator<BigDecimalRange, Object> {

    private long maxPrecision;
    private long minPrecision;
    private int scale;

    @Override
    public void initialize(final BigDecimalRange bigDecimalRange) {
        maxPrecision = bigDecimalRange.maxPrecision();
        minPrecision = bigDecimalRange.minPrecision();
        scale = bigDecimalRange.scale();
    }

    @Override
    public boolean isValid(final Object object, final ConstraintValidatorContext cvc) {
        boolean isValid = false;

        if (object == null) { // This should be validated by the not null validator (@NotNull).
            isValid = true;
        } else if (object instanceof BigDecimal) {
            BigDecimal bigDecimal = new BigDecimal(object.toString());
            int actualPrecision = bigDecimal.precision();
            int actualScale = bigDecimal.scale();
            isValid = actualPrecision >= minPrecision && actualPrecision <= maxPrecision && actualScale <= scale;

            if (!isValid) {
                cvc.disableDefaultConstraintViolation();
                cvc.buildConstraintViolationWithTemplate("Precision expected (minimun : " + minPrecision + ", maximum : " + maxPrecision + "). Maximum scale expected : " + scale + ". Found precision : " + actualPrecision + ", scale : " + actualScale).addConstraintViolation();
            }
        }

        return isValid;
    }
}

这也可以在需要时扩展到其他类型。


最后在 bean 中,类型的属性BigDecimal可以通过@BigDecimalRange注解进行如下注解。

package validatorbeans;

public final class WeightBean {

    @BigDecimalRange(minPrecision = 1, maxPrecision = 33, scale = 2, groups = {ValidationGroup.class}, message = "The precision and the scale should be less than or equal to 35 and 2 respectively.")
    private BigDecimal txtWeight; // Getter and setter.

    public interface ValidationGroup {}
}
于 2013-03-24T11:03:53.417 回答
3

您也可以@Digits从休眠验证器 API 中使用

@Digits(integer = 10 /*precision*/, fraction = 2 /*scale*/)
于 2017-02-20T10:23:06.750 回答
3

@AssertTrue有时与/ @AssertFalsefrom配对很方便javax.validation.constraints

public final class WeightBean {
    @NotNull
    private Double txtWeight;  //Getter and setter.

    @AssertTrue
    public boolean getTxtWeightCheck() {
        return txtWeight > 0.1 && txtWeight < 0.9;
    }
}
于 2018-04-27T14:23:50.113 回答
2

较新版本的 Hibernate Validator(至少 6.0.17)支持@DecimalMin/Max双注释

类进行验证

于 2019-09-09T09:49:07.743 回答
0

Hibernate 验证器适用@DecimalMin/MaxDouble& Float。但它们不是精确的数字,只是近似值,取决于验证实现,可能会有一些错误的结果。

验证的最佳想法是使用BigDecimal带有@DecimalMin@DecimalMax验证注释的类型。

于 2021-06-10T06:55:19.847 回答