Validator?

Validator?

Validator는 컨트롤러에서 매핑된 객체의 값을 확인하기 위해서 사용하는 인터페이스이다. Validator를 통한 검증과정으로 BindingResult에 그 값을 저장하고, hasErrors() 메소드를 통해 검증값을 확인할 수 있다.

Validator를 구현하는 방법은 두 가지가 존재하는데, 다음과 같다.

  • Validator인터페이스를 구현한 클래스 생성
  • @Valid애노테이션을 사용한 값 검증


Validator 구현

Validator 인터페이스는 다음 두 가지의 메소드를 정의하고 있다.

1
2
3
4
5
6
7
8
package org.springframework.validation;

public interface Validator {

	boolean supports(Class<?> clazz);

	void validate(Object target, Errors errors);
}

supports()는 구현체에서 검증할 객체의 타입으로 class 참조하도록 하면 된다.

1
2
3
public boolean supports(Class<?> clazz) {
	return (Board.class.isAssignableForm(clazz));
}

validate()메소드는 실제 어떠한 검증할 할 것인지를 정의하고 있는 메소드이다. 주로 String값의 검증이나 객체가 null인지 등의 검증을 수행한다. rejectValue()에 인자로 들어가는 값들 중 error.invalid는 properties에 있는 값이다.

1
2
3
4
5
6
7
8
9
public void validate(Object target, Errors errors) {
	Board board = (Board) target;

	if(StringUtils.isBlank(board.getBoardName())) {
		errors.rejectValue("boardCode", "error.invalid", "error.invalid");
	}

	...
}

실제로 이 validator를 컨트롤러에서 사용하기 위해서는 Validator를 구현한 구현체를 빈으로 등록하고 컨트롤러에서 @Autowired해서 검증하는 방식으로 사용하면 된다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
// 구현체
@Component
public class BoardValidator implements Validator {

	public boolean supports(Class<?> clazz) {
		...
	}

	public void validate(Object target, Errors errors) {
		...
	}
}


// 컨트롤러
@Controller
public class BoardController {
	...
	
	@Autowired
	private BoardValidator validator;


	@RequestMapping(value="/add")
	public void add(Board board, BindingResult bindingResult) {
		...
		validator.validate(board, bindingResult);

		if(bindingResult.hasErrors()){
			// 에러가 있는 경우
		} else {
			// 에러가 없고 정상인 경우
		}	
	}
}


@Valid 애노테이션을 이용한 값 검증

Validator 인터페이스를 구현하는 방식 이외에도 스프링에서 제공하는 @Valid 애노테이션을 사용해서 검증을 하는 방식도 존재한다. @Valid 애노테이션을 사용하기 위해서는 사용할 Validator를 Bind 해주어야 한다. 이를 위해서 @InitBinder 애노테이션을 사용한다. @InitBinder를 통해 validator를 bind 해주면 컨트롤러에서 자동으로 검증을 수행한다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
@Controller
public class BoardController {
	...

	@Autowired
	private BoardValidator validator;

	@InitBinder
	public void initBinder(WebDataBinder dataBinder) {
		dataBinder.setValidator(validator);
	} 

	@RequestMapping(value="/add")
	public void add(@Valid Board board, BindingResult bindingResult) {
		...

		if(bindingResult.hasErrors()){
			// 에러가 있는 경우
		} else {
			// 에러가 없고 정상인 경우
		}	
	}
}

따라서 위와 같이 @Valid 애노테이션을 붙이면 메소드 내부에서는 이미 bindingResult에 검증을 한 결과가 들어있게 된다. 참고로 하나의 컨트롤러에서 여러 Model에 대한 Validator를 생성하기 위해서는 @InitBinder애노테이션에 해당 모델의 이름(타입이름)을 써주어야 한다.

1
2
3
4
5
6
7
8
9
10
// Model이 Board인 경우
@InitBinder("board")

// Model이 Project인 경우
@InitBinder("project")

// Model이 Array나 List인 경우, 타입 + List 형태로 작성
// List<Member>인 경우
@InitBinder("memberList")