Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/350.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 在Spring中使用验证将ZonedDateTime字段限制为毫秒3位_Java_Spring_Validation_Hibernate Validator - Fatal编程技术网

Java 在Spring中使用验证将ZonedDateTime字段限制为毫秒3位

Java 在Spring中使用验证将ZonedDateTime字段限制为毫秒3位,java,spring,validation,hibernate-validator,Java,Spring,Validation,Hibernate Validator,我想验证Spring MVC请求中的输入DTO,特别是ZonedDateTime字段在毫秒级最多应包含3位数字,即它不能是完整的纳秒精度。除此之外,输入请求应遵循ISO日期时间格式。我可以将该字段设置为字符串,然后使用正则表达式对其进行限制,但我更喜欢将其保留为ZonedDateTime,这样就不需要再次解析它 该对象如下所示: @Data public class MeasurementDTO { private ZonedDateTime date; @Digits(int

我想验证Spring MVC请求中的输入DTO,特别是ZonedDateTime字段在毫秒级最多应包含3位数字,即它不能是完整的纳秒精度。除此之外,输入请求应遵循ISO日期时间格式。我可以将该字段设置为字符串,然后使用正则表达式对其进行限制,但我更喜欢将其保留为ZonedDateTime,这样就不需要再次解析它

该对象如下所示:

@Data
public class MeasurementDTO {

    private ZonedDateTime date;
    @Digits(integer = 20, fraction = 8) private BigDecimal value;

}
这是一个嵌套的DTO,其中父对象以@RequestBody和@Valid注释的形式出现

我尝试过@JsonFormat,但似乎无法限制毫秒部分。 有没有办法做到这一点,或者我应该自己将其解析为一个字符串,然后处理它?或者干脆把它放在ZoneDateTime,然后检查纳秒组件,看看它是否在自定义验证器中


多亏了Tim的回答,我记得Java日期的精度并不比毫秒高,所以我更新了这个问题,使用了ZoneDateTimes,它的精度高达纳秒。我确实希望能够给用户一个警告,如果他们试图传递更高的精度,如果使用日期这个信息会被吞没。

< P>你可能不认为这是一个完整的答案,但是JavaUTILDATE只存储精度达毫秒,而不是超过此。看看Jon Skeet的,或者读一下,它显示出它除了毫秒存储之外什么都没有


因此,使用Hibernate验证将日期限制为毫秒精度是没有意义的,因为类型本身已经具有这种限制。

我使用自定义验证程序艰难地做到了这一点。不过,我仍然欢迎能以更简洁的方式做到这一点的答案

以下是我的解决方案:

我添加了一个注释@ValidMeasurementInput

@Documented
@Constraint(validatedBy = MeasurementValidator.class)
@Target({TYPE, FIELD, ANNOTATION_TYPE})
@Retention(RUNTIME)
public @interface ValidMeasurementInput {

    String message() default "Invalid measurement input";

    Class<?>[] groups() default {};

    Class<? extends Payload>[] payload() default {};
}

当然,我在DTO中添加了@validMeasureInput。

这实际上是一个很好的观点!我从一个python函数中移植了这段代码,当时我使用了一个庞大的正则表达式,但这里甚至不需要它。将问题保留一段时间,看看是否有任何答案允许部分时间进行验证,例如限制秒数。无论如何,我决定在DTO中使用ZonedDateTime,因为我不想默默地接受额外的精度。如果您想要大于毫秒的分辨率,使用java.time.Instant可以获得更高的分辨率。最好总是完全避免java.util.Date,因为它会被错误的设计选择所削弱。要在瞬间删除任何微秒或纳秒,请调用该方法。通过。@BasilBourque我已经在我的答案中编辑了Instant。实际上,我不希望这种情况下的分辨率大于毫秒,但如果用户试图通过它,我希望能够检测到它。
public class MeasurementValidator implements ConstraintValidator<ValidMeasurementInput, MetricsDTO> {

    @Override
    public boolean isValid(MetricsDTO metricsDTO, ConstraintValidatorContext context) {
        ...
    }
}
   int nano = measurementDTO.getDate().getNano();
   int remainderAfterMillis = nano % 1000000;
   if (remainderAfterMillis != 0)
       valid = false;