1. 소개

사용자 입력의 유효성을 검사하는 것은 모든 응용 프로그램의 일반적인 요구 사항입니다. 이 예제에서는 객체 List 을 Spring 컨트롤러에 대한 매개변수로 검증하는 방법을 살펴볼 것 입니다.

사용자 지정 데이터가 지정된 조건을 충족하는지 확인하기 위해 컨트롤러 계층에 유효성 검사를 추가합니다.

2. 필드에 제약 조건 추가

우리의 예에서는 영화 데이터베이스를 관리하는 간단한 Spring 컨트롤러를 사용할 것입니다. 우리는 영화 List을 수락하고 List에 대한 유효성 검사를 수행한 후 데이터베이스에 추가하는 방법에 중점을 둘 것입니다.

따라서 javax 유효성 검사  를 사용하여 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 객체 List을 검증할 컨트롤러 메서드를 작성해 보겠습니다 .

영화 List에 @NotEmpty 어노테이션을 추가 하여 List에 하나 이상의 요소가 있어야 하는지 확인합니다. 동시에 Movie 객체 자체가 유효한지 확인하기 위해 @Valid 어노테이션을 추가합니다.

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

영화 List 입력으로 컨트롤러 메서드를 호출하면 @NotEmpty 어노테이션으로 인해 유효성 검사가 실패하고 다음 메시지가 표시됩니다.

Input movie list cannot be empty.

@Valid 어노테이션은 Movie 클래스 에 지정된 제약 조건이 List의 각 객체에 대해 평가되는지 확인 합니다 . 따라서 List에 빈 이름으로 Movie 를 전달하면 다음 메시지와 함께 유효성 검사가 실패합니다.

Movie name cannot be empty.

4. 사용자 정의 유효성 검사기

입력 List 에 사용자 지정 제약 조건 유효성 검사기 를 추가할 수도 있습니다 .

이 예에서 사용자 지정 제약 조건은 입력 List 크기가 최대 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 는 입력의 크기를 검증합니다. 따라서 입력 List에 4개 이상의 Movie 객체를 전달하면 유효성 검사가 실패합니다.

5. 예외 처리

유효성 검사 중 하나라도 실패하면 ConstraintViolationException 이 발생합니다. 이제 이 예외를 catch하기 위해 예외 처리 구성 요소를 추가하는 방법을 살펴보겠습니다 .

@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 응답을 확인합니다.

빈 List을 시도해 보겠습니다.

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

이 시나리오에서는 HTTP 상태 400 응답을 받습니다. 이는 입력이 @NotEmpty 제약 조건을 충족하지 않기 때문입니다.

Input movie list cannot be empty.

다음으로 List에 있는 5개의 Movie 객체를 전달해 보겠습니다 .

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

@MaxSizeConstraint 제약 조건 에 실패했기 때문에 HTTP 상태 400 응답도 발생합니다 .

The input list cannot contain more than 4 movies.

7. 결론

이 빠른 기사에서 우리는 Spring에서 객체 List의 유효성을 검사하는 방법을 배웠습니다.

항상 그렇듯이 예제의 전체 소스 코드는 GitHub에서 끝났습니다 .

REST footer banner