【问题标题】:How to validate that fromDate and toDate both exist or absent in get request with Spring Boot如何使用 Spring Boot 在获取请求中验证 fromDate 和 toDate 是否存在
【发布时间】:2021-03-15 16:55:36
【问题描述】:

我有获取请求

localhost:8080/company/{id}/resource?fromDate=2020-12-03T18:01:00Z&toDate=2020-12-03T18:12:00Z

在这个请求中fromDate和toDate是可选的,所以基本上我可以调用

localhost:8080/company/{id}/resource

它会为我返回响应。

现在我想以正确的方式验证 fromDate 和 toDate 是否都通过了,或者两者都没有通过。

@GetMapping(value = "/company/{id}/resource")
public String getParameterOverride(
@PathVariable String id,
@RequestParam(required = false) @DateTimeFormat(iso = ISO.DATE_TIME) ZonedDateTime fromDate,
@RequestParam(required = false) @DateTimeFormat(iso = ISO.DATE_TIME) ZonedDateTime toDate
) {
    // check dates logic
     return id;
}

问题是我不想写类似的东西

if(fromDate == null && toDate == null) {
 ...
}

我正在使用 Spring Boot。还有其他方法可以验证此字段吗?我的想法是创建新的 POJO,然后在那里验证它们,但我没有设法弄清楚如何去做。如何检查两个文件是否都存在于 POJO 中,反之亦然?还有From Date是之前到日期吗?

【问题讨论】:

  • 如果你拒绝做空检查,你想如何验证字段?
  • @f1sh 我想验证设置到 POJO 中的字段,我不拒绝这样做
  • 然后设置成pojo,有什么问题?然后你必须在 pojo 的方法中做空检查。您希望从中获得什么?
  • 如果你不喜欢语法,你可以用Objects.isNull(obj) 代替@BohdanMyslyvchuk

标签: java spring-boot validation


【解决方案1】:

好的,我找到了我正在寻找的解决方案。

只检查 if 语句中的这两个参数是非常简单的方法,我认为它是不可重用的。

我发现您可以将请求参数字段按名称直接映射到 POJO。然后使用验证,您可以创建约束,该约束将检查您喜欢的任何条件的两个依赖字段。

假设您有请求

http://localhost:8080/myresource?dateFrom=2020-01-01&dateTo=2020-01-02

然后你的控制器:

@GetMapping(value = "/myresource")
public String getMyResource(@Valid DateRangePojo dateRangePojo ) {
    return null;
}

我的问题是“如何验证您是否同时拥有 dateFrom 和 dateTo 或两者都没有”。

然后是波乔

@Data
@CheckDateRange
public class DateRangePojo {

    @DateTimeFormat(iso = ISO.DATE_TIME)
    private final ZonedDateTime dateFrom;

    @DateTimeFormat(iso = ISO.DATE_TIME)
    private final ZonedDateTime dateTo;
}

@CheckDateRange- 是用于检查两个日期是否存在的自定义注释。

@Target({ElementType.TYPE_USE})
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = CheckDatesValidator.class)
public @interface CheckDateRange{

    String message() default "";

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

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

}

public class CheckDatesValidator implements ConstraintValidator<CheckDateRange, DateRangePojo> {
    @Override
    public boolean isValid(final DateRangePojo value, final ConstraintValidatorContext context) {
   // your logic to check if valid
    }
  }

每当有新请求到来时,都会通过 isValid 方法进行验证。

【讨论】:

    【解决方案2】:

    如果请求参数是可选的,您可以使用Optional 声明它们

    @RequestParam(required = false) @DateTimeFormat(iso = ISO.DATE_TIME) Optional<ZonedDateTime> fromDate,
    @RequestParam(required = false) @DateTimeFormat(iso = ISO.DATE_TIME) Optional<ZonedDateTime> toDate
    

    然后在不需要多次检查的代码中,Optional.map 只有在Optional 不为空时才会执行

    if(fromDate.isPresent() && toDate.isPresent()) {
         return //value
      }
    
     fromDate.map(/*call method*/).orElseGet(()-> toDate.map(/*call method*/).orElse(/*default value*/));
    

    【讨论】:

    • 感谢您的评论,但我将获得什么好处?如何验证例如 toDate 已通过而 fromDate 未通过并抛出异常?还是我应该检查每个参数?
    • 我确实更新了代码如何使用可选和它的优势@BohdanMyslyvchuk
    【解决方案3】:

    使用@Valid 注释来检查数据类型是否像非常基本的一样有效

    @GetMapping(value = "/company/{id}/resource")
    public String getParameterOverride(
    @PathVariable String id,
    @RequestParam(required = false) @DateTimeFormat(iso = ISO.DATE_TIME) @Valid ZonedDateTime fromDate,
    @RequestParam(required = false) @DateTimeFormat(iso = ISO.DATE_TIME) @Valid ZonedDateTime toDate
    ) {
        // check dates logic
         return id;
    }
    

    更个性化的可以找ConstraintValidator

    【讨论】:

    • 感谢您的评论。好的 fromDate 已通过,它是有效的。但我只能使用两个参数运行服务方法。如何通知失踪者?
    • 没有开箱即用的注释向您发送缺少参数的错误,您必须使用 ControllerAdvice。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-04-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-03-21
    • 2021-07-11
    相关资源
    最近更新 更多