Spring - WebDataBinder (Validator 구현)

박민수·2023년 11월 14일
0

Spring

목록 보기
3/46
post-thumbnail

WebDataBinder

WebDataBinder는 매개변수 바인딩의 역할을 한다. 또한 내부에 검증 기능을 포함하고 있다. 먼저 타입 변환을 해주고 그 후에 데이터 검증을 실시 하며, 변환 결과나 에러는 Errors에 저장한다.

특정 컨트롤에만 적용

AccountController.class

  1. @InitBinder 어노테이션을 이용해서 WebDataBinder 객체에 직접 구현한 Validator를 추가한다.
  2. Validator를 적용하고자 하는 메서드 파라미터에 @Valid 또는 @Validator 어노테이션을 적용해준다.
@Controller
@RequiredArgsConstructor
public class AccountController {

    ...
    
    @InitBinder("signUpForm")
    public void initBinder(WebDataBinder webDataBinder) {
        webDataBinder.addValidators(signUpFormValidator);
    }

	...

    @PostMapping("/sign-up")
    public String signUpSubmit(@Valid @ModelAttribute SignUpForm signUpForm, Errors errors, Model model) {
        if (errors.hasErrors()) {
            return "account/sign-up";
        }
        
        ...
        
    }
}

SignUpFormValidator.class

  1. @InitBinder 어노테이션을 이용해서 WebDataBinder 객체에 직접 구현한 Validator를 추가한다.
  2. Validator를 적용하고자 하는 메서드 파라미터에 @Validated 어노테이션을 적용해준다.
package com.example.account;

import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Component;
import org.springframework.validation.Errors;
import org.springframework.validation.Validator;

@Component
@RequiredArgsConstructor
public class SignUpFormValidator implements Validator {

    private final AccountRepository accountRepository;

    @Override
    public boolean supports(Class<?> clazz) {
        //SignUpForm == clazz
        //SignUpForm == subItem 자손 객체도 넘어올 수 있음
        return clazz.isAssignableFrom(SignUpForm.class);
    }

    @Override
    public void validate(Object target, Errors errors) {
        SignUpForm signUpForm = (SignUpForm) target;
        if (accountRepository.existsByEmail(signUpForm.getEmail())) {
            errors.rejectValue("email", "invalid.email", new Object[]{signUpForm.getEmail()}, "이미 사용중인 이메일입니다.");
        }

        if (accountRepository.existsByNickname(signUpForm.getNickname())) {
            errors.rejectValue("nickname", "invalid.nickname", new Object[]{signUpForm.getNickname()}, "이미 사용중인 닉네임입니다.");
        }
    }
}

글로벌 설정

App.class

모든 컨트롤러에 적용하고 싶으면 WebMvcConfigurer 인터페이스를 구현하면 된다.

@SpringBootApplication
public class App implements WebMvcConfigurer {

    public static void main(String[] args) {
    	SpringApplication.run(ItemServiceApplication.class, args);
    }
    
    @Override
    public Validator getValidator() {
    	return new SignUpFormValidator();
    }
}

SignUpForm.class

package com.example.account;

import lombok.Data;
import org.hibernate.validator.constraints.Length;

import javax.validation.constraints.Email;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.Pattern;

@Data
public class SignUpForm {

    @NotBlank
    @Length(min = 3, max = 20)
    @Pattern(regexp = "^[ㄱ-ㅎ가-힣a-z0-9_-]{3,20}$")
    private String nickname;

    @Email
    @NotBlank
    private String email;

    @NotBlank
    @Length(min = 8, max = 50)
    private String password;
}

sign-up.html

<div class="form-group">
    <label for="nickname">닉네임</label>
    <input id="nickname" type="text" th:field="*{nickname}" class="form-control">
    <small class="form-text text-danger" th:if="${#fields.hasErrors('nickname')}" th:errors="*{nickname}">Nickname Error</small>
</div>

참조
https://www.inflearn.com/course/%EC%8A%A4%ED%94%84%EB%A7%81-mvc-2

profile
안녕하세요 백엔드 개발자입니다.

0개의 댓글