我们如何以及应该在 Spring REST 控制器中验证可选查询参数

问题描述 投票:0回答:1

我有一个 Spring REST API 端点定义如下:

@GetMapping("/books")
public List<Book> getBooks(
        @RequestParam @NotNull Long id,
        @RequestParam(required = false) String category) {
    return libraryService.getBooks(id, category);
}

category
参数是可选的,但是当提供它时,我想确保它不为空或为空。

我尝试使用:

@RequestParam(required = false) @NotNull String category

因为我读到:https://stackoverflow.com/a/57818215/12769096

@required = false
仅代表param本身的存在,而不代表其值。 这意味着它会验证 url 中是否存在“&category”,但不会继续检查分配给它的值,该值可以是有效的、null 或空的或其他任何值。

但是它引起了冲突,所以我删除了它,现在它运行了,显然没问题,但没有我想要的验证。

问题是,目前,请求如下:

  • https://library:8080/books?id=1234&category=
  • https://library:8080/books?id=1234&category=""
  • https://library:8080/books?id=1234&category

由于 category 值无效,所有结果都会导致 500 内部服务器错误

我希望这些请求导致 400 Bad Request (或者由于不回答参数约束而引发的任何异常),因为类别参数存在但其值无效。 没有类别的请求应该仍然可以顺利通过,就像现在一样,因为它是可选的。

如何正确验证类别参数以实现此行为,而无需显式检查代码中的空字符串或空字符串,而是使用辅助 Spring 注释和工具?

java spring-boot spring-mvc model-view-controller controller
1个回答
0
投票

您可以编写自定义验证器

@Constraint(validatedBy = NotEmptyIfPresentValidator.class)
@Target({ ElementType.PARAMETER })
@Retention(RetentionPolicy.RUNTIME)
public @interface NotEmptyIfPresent {
    String message() default "Category must not be empty if present";
    Class<?>[] groups() default {};
    Class<? extends Payload>[] payload() default {};
}


public class NotEmptyIfPresentValidator implements ConstraintValidator<NotEmptyIfPresent, String> {

    @Override
    public void initialize(NotEmptyIfPresent constraintAnnotation) {
    }

    @Override
    public boolean isValid(String value, ConstraintValidatorContext context) {
        return value == null || !value.trim().isEmpty();
    }
}

//controller
@GetMapping("/books")
public List<Book> getBooks(
        @RequestParam @NotNull Long id,
        @RequestParam(required = false) @NotEmptyIfPresent String category) {
    return libraryService.getBooks(id, category);
}

确保使用

@Validated

注释你的控制器
© www.soinside.com 2019 - 2024. All rights reserved.