Spring Validator를 사용해서 검증하는 방법들

probsno·2021년 4월 14일
0

SpringCore

목록 보기
6/9

Intro

시작하기 전에 JSR-303 Validator(Validator 인터페이스의 구현체)를 적용하기 위해서는 아래의 dependencypom.xml에 추가해야 한다.

    <dependency>
        <groupId>javax.validation</groupId> 
        <artifactId>validation-api</artifactId> 
        <version>1.0.0.GA</version> 
    </dependency>
    
    <dependency>  
        <groupId>org.hibernate</groupId>  
        <artifactId>hibernate-validator</artifactId>  
        <version>4.2.0.Final</version>
    </dependency>

1. 직접 Validator 인터페이스를 상속받아서 객체 검증하기

Validator 인터페이스는 두가지 메서드를 정의하는데, supports메서드validate메서드이다.
supports메서드는 검증하고자 하는 객체가 validator에서 지원하는지 아닌지 확인하는 메서드이고, validate메서드는 실제 로직을 구현하는 메서드이다.

아무튼 코드로 Validator 인터페이스를 상속받아서 구현하자면,

public class EventValidator implements Validator {
    @Override
    public boolean supports(Class<?> aClass) {
        //해당 객체가 validator가 지원하는 객체인지 판단하기 위해서 override하는 메서드
        return Event.class.equals(aClass);
    }

    @Override
    public void validate(Object target, Errors errors) {
    	//ValidationUtils를 사용하여 validate을 구현하거나
        //rejectIfEmptyOrWhitespace 함수의 경우 해당 필드가 비어있거나 공백일 경우 발생시킴
        //1번인자 Error객체, 2번인자 필드이름, 3번인자 에러코드, 4번인자 디폴트 메세지
        ValidationUtils.rejectIfEmptyOrWhitespace(errors, "title", "NOT_EMPTY", "DEFALT_MESSAGE");

        //또는 직접 Error 객체에 접근해서 validate을 구현할 수도 있음
        Event event = (Event) target;
        if(event.getClass()==null){
            //객체 전반의 에러라면 reject 메서드
            errors.reject("Error Message");

            //특정 필드의 에어라면 rejectValue 메서드
            //첫번째 인자가 필드 이름, 두번째 인가자 에러코드드
           errors.rejectValue("fieldName", "ErrorMessage");
        }

    }
}

그리고 검증받을 객체는,,,

public class Event {

    private Integer id;

    private String title;

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }
}

Validator상속받은 클래스를 생성하고 validate매서드를 실행시키는 것임.
validate메서드검증할 객체Errors객체를 받아서 검증처리를 하고 Errors객체의 메서드를 통해서 e.g. errors.hasErrors() 또는 errors.getAllErrors()등의 메서드를 활용해서 검증 내용을 확인함.
직관적을 코드로 보자면,,

@Component
public class AppRunner implements ApplicationRunner {

    @Autowired
    Validator validator;

    @Override
    public void run(ApplicationArguments args) throws Exception {
       Event event = new Event();
       EventValidator eventValidator = new EventValidator();
		
        //Errors는 인터페이스이고 이를 구현한 구현체는 BeanPropertyBindingResult
        // 파라미터로 검증할 객체와 객체의 이름을 String으로 넘김
       Errors errors = new BeanPropertyBindingResult(event, "event");

       eventValidator.validate(event, errors);
       System.out.println(errors.hasErrors());

       errors.getAllErrors().forEach(error->{
           System.out.println("----error code------");
           Arrays.stream(error.getCodes()).forEach(System.out::println);
           System.out.println(error.getDefaultMessage());
       });

    }
}

그리고 검증결과는...

이처럼 실행되기 때문에

if(erros.hasError){
	//예외처리 내용
}

등으로 예외처리를 하면 된답

2. Validator 인터페이스의 구현체 빈 사용하기

Validator인터페이스를 상속받아 직접 validator를 구현해도 되지만, 갓갓 스프링은 이미 validator인터페이스를 구현해 놓은 LocalValidatorFactoryBean 클래스를 빈으로 등록해 놓았기 때문에


@Component
public class AppRunner implements ApplicationRunner {

    @Autowired
    Validator validator;

    @Override
    public void run(ApplicationArguments args) throws Exception {
       Event event = new Event();
		
        //Errors는 인터페이스이고 이를 구현한 구현체는 BeanPropertyBindingResult
        // 파라미터로 검증할 객체와 객체의 이름을 String으로 넘김
       Errors errors = new BeanPropertyBindingResult(event, "event");

       eventValidator.validate(event, errors);

    }
}

이렇게 빈으로 주입받아서 사용할 수 있도록 되어 있다.
Validator 인터페이스를 직접 구현해서 사용할 때처럼 validate.validate()메서드에 검증할 객체와 Errors객체를 넣고 errro.hasErorr()등의 메서드로 확인함.

그런데 말입니다? 그럼 무엇을 어떻게 검증할건지 어떻게 아나요?
정답은 검증받을 객체의 필드에 여러가지 어노테이션을 필드에 붙여서 확인하게 된다.
예를들면...

public class Event {
	
    @Min(1) //최소값이 1이라는거, 즉, 0이나 음수를 가질 수 없음
    private Integer id;
	
    @NotEmpty //Null이나 ""빈 물자열을 가질 수 없음
    private String title;

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }
}

3. 어노테이션 정리

이제 검증할 객체의 필드에 붙이는 어노테이션들을 하나하나 아라보자!

  • Anotation 제약조건
    • @NotNull - Null 불가
    • @Null - Null만 입력 가능
    • @NotEmpty - Null, 빈 문자열 불가
    • @NotBlank - Null, 빈 문자열, 스페이스만 있는 문자열 불가
    • @Size(min=,max=) - 문자열, 배열등의 크기가 만족하는가?
    • @Pattern(regex=) - 정규식을 만족하는가?
    • @Max(숫자) - 지정 값 이하인가?
    • @Min(숫자) - 지정 값 이상인가
    • @Future - 현재 보다 미래인가?
    • @Past - 현재 보다 과거인가?
    • @Positive - 양수만 가능
    • @PositiveOrZero - 양수와 0만 가능
    • @Negative - 음수만 가능
    • @NegativeOrZero - 음수와 0만 가능
    • @Email - 이메일 형식만 가능
    • @Digits(integer=, fraction = ) - 대상 수가 지정된 정수와 소수 자리 수 보다 작은가?
    • @DecimalMax(value=) - 지정된 값(실수) 이하인가?
    • @DecimalMin(value=) - 지정된 값(실수) 이상인가?
    • @AssertFalse - false 인가?
    • @AssertTrue - true 인가?
profile
3개국어 쌉가능한 주니어 개발자

0개의 댓글