在 Spring 控制器中驗證列表

REST,Spring MVC
Remote
0
09:00 AM · Dec 01 ,2025

1. 引言

驗證用户輸入是任何應用程序中的常見需求。在本教程中,我們將介紹如何將一個包含 列表 的對象作為參數傳遞給 Spring 控制器進行驗證。

我們將為控制器層添加驗證,以確保用户提供的的數據滿足指定的條件。

2. 為字段添加約束

對於我們的示例,我們將使用一個簡單的 Spring 控制器,該控制器管理電影數據庫。我們將重點關注一個接受電影列表的方法,並在對列表執行驗證後將其添加到數據庫。

因此,我們首先應該 使用 javax validation 為 Movie 類添加約束

public class Movie {

    private String id;

    @NotEmpty(message = "Movie name cannot be empty.")
    private String name;

    // standard setters and getters
}

3. 在控制器中添加驗證註釋

讓我們看一下我們的控制器。首先,我們將@Validated註解添加到控制器類中:

@Validated
@RestController
@RequestMapping("/movies")
public class MovieController {

    @Autowired
    private MovieService movieService;

    //...
}

接下來,讓我們編寫控制器方法,其中我們將對傳入的Movie對象列表進行驗證。

我們將@NotEmpty註解添加到我們的Movie對象列表中,以驗證列表中至少應包含一個元素。同時,我們還將@Valid註解添加到它以確保Movie對象本身有效。

@PostMapping
public void addAll(
  @RequestBody 
  @NotEmpty(message = "Input movie list cannot be empty.")
  List<@Valid Movie> movies) {
    movieService.addAll(movies);
}

如果我們調用控制器方法,並傳入一個空Movie列表,那麼由於@NotEmpty註解,驗證將會失敗,我們將會看到以下消息:

Input movie list cannot be empty.

@Valid註解將會確保Movie類中指定的約束對於列表中的每個對象進行評估。因此,如果在列表中傳入一個Movie對象,如果該對象的名稱為空,驗證將會失敗,並顯示以下消息:

Movie name cannot be empty.

4. 自定義驗證器

我們還可以將自定義約束驗證器添加到輸入列表。

對於我們的示例,自定義約束將驗證輸入列表的大小限制為最多四個元素。讓我們創建此自定義約束註釋:

@Constraint(validatedBy = MaxSizeConstraintValidator.class)
@Retention(RetentionPolicy.RUNTIME)
public @interface MaxSizeConstraint {
    String message() default "The input list cannot contain more than 4 movies.";
    Class<?>[] groups() default {};
    Class<? extends Payload>[] payload() default {};
}

現在,我們將創建一個驗證器來應用上述約束:

public class MaxSizeConstraintValidator implements ConstraintValidator<MaxSizeConstraint, List<Movie>> {
    @Override
    public boolean isValid(List<Movie> values, ConstraintValidatorContext context) {
        return values.size() <= 4;
    }
}

最後,我們將@MaxSizeConstraint註釋添加到我們的控制器方法:

@PostMapping
public void addAll(
  @RequestBody
  @NotEmpty(message = "Input movie list cannot be empty.")
  @MaxSizeConstraint
  List<@Valid Movie> movies) {
    movieService.addAll(movies);
}

在這裏,@MaxSizeConstraint將驗證輸入的大小。因此,如果我們將超過四個Movie對象傳遞到輸入列表中,驗證將失敗。

5. 處理異常

如果任何驗證失敗,ConstraintViolationException將會被拋出。現在,讓我們看看如何添加一個異常處理組件來捕獲這個異常。

@ExceptionHandler(ConstraintViolationException.class)
public ResponseEntity handle(ConstraintViolationException constraintViolationException) {
    Set<ConstraintViolation<?>> violations = constraintViolationException.getConstraintViolations();
    String errorMessage = "";
    if (!violations.isEmpty()) {
        StringBuilder builder = new StringBuilder();
        violations.forEach(violation -> builder.append(" " + violation.getMessage()));
        errorMessage = builder.toString();
    } else {
        errorMessage = "ConstraintViolationException 發生了。";
    }
    return new ResponseEntity<>(errorMessage, HttpStatus.BAD_REQUEST);
}

6. 測試 API

現在,我們將使用有效和無效的輸入測試我們的控制器。

首先,讓我們向 API 提供有效輸入:

curl -v -d '[{"name":"Movie1"}]' -H "Content-Type: application/json" -X POST http://localhost:8080/movies 

在這種情況下,我們將收到 HTTP 狀態碼 200 的響應:

...
HTTP/1.1 200
...

接下來,我們將檢查在傳遞無效輸入時 API 的響應。

讓我們嘗試一個空列表:

curl -d [] -H "Content-Type: application/json" -X POST http://localhost:8080/movies

在這種情況下,我們將收到 HTTP 狀態碼 400 的響應。這是因為輸入不滿足 @NotEmpty 約束。

電影列表不能為空。

接下來,讓我們嘗試在列表中傳遞五個 Movie 對象:

curl -d '[{"name":"Movie1"},{"name":"Movie2"},{"name":"Movie3"},{"name":"Movie4"},{"name":"Movie5"}]'\
  -H "Content-Type: application/json" -X POST http://localhost:8080/movie

這將導致 HTTP 狀態碼 400 的響應,因為我們違反了 @MaxSizeConstraint 約束:

輸入列表不能包含超過 4 部電影。

7. 結論

在本文中,我們學習瞭如何驗證 Spring 中對象的列表。

user avatar
0 位用戶收藏了這個故事!
收藏

發佈 評論

Some HTML is okay.