知識庫 / Spring / Spring MVC RSS 訂閱

Spring 控制器中驗證列表

REST,Spring MVC
HongKong
4
03:50 AM · Dec 06 ,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 註解,以驗證列表中至少應包含一個元素。同時,我們還將添加 @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. 處理異常

如果任何驗證失敗,將會拋出 <a title="ConstraintViolationException javadoc" href="https://javaee.github.io/javaee-spec/javadocs/javax/validation/ConstraintViolationException.html">ConstraintViolationException</a> 異常。 接下來,讓我們看看如何添加一個異常處理組件來捕獲該異常。

@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 occured.";
    }
    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 約束。

Input movie list cannot be empty.

接下來,我們嘗試將五個 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 約束:

The input list cannot contain more than 4 movies.

7. 結論

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

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

發佈 評論

Some HTML is okay.