회원 가입 뷰
> 회원 가입 폼 검증
>> JSR 303 어노테이션 검증
>>> 값의 길이, 필수 값
>> 커스텀 검증
>>> 중복 이메일, 닉네임 여부 확인
>> 폼 에러 읶을 시, 폼 다시 보여주기
> 회원 가입 처리
>> 회원 정보 저장
>> 인증 이메일 발송
>> 처리 후 첫 페이지로 리다이렉트(Post-Redirect-Get 패턴)
>실습
>> 시작 커밋 : fbf1423165272310274e6975d779f690ee3bdc8f
>> 완료 커밋 : 5ff6d7bdca59f1ca7de4ec0bf4135184cc18bb28
회원가입 후 이동할 경로를 설정
AccountController.class
@PostMapping("/sign-up")
public String signUpSubmit(@Valid SignUpForm signUpForm, Errors errors){
if (errors.hasErrors()){
return "account/sign-up";
}
// TODO : 회원가입 처리
return "redirect:/";
}
SignUpForm.class
/**
* 회원가입할 때 받아올 데이터
*/
@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;
}
프론트에도 제약을 걸어도 백엔드에서도 무조건 제약을 걸어줘야 안전하다. 아래는 서버에서 특수문자를 제약하여 발생한 오류처리 문구이다.
Spring IoC 컨테이너에 의한 의존성 주입은 빈(Bean) 끼리만 가능하다.
@RequiredArgsConstructor를 설정하면 private final ~ ~:로 선언한 객체들은 자동으로 생성자 만들어줌
initBinder()와 signUpSubmit()추가
@InitBinder란? 특정 컨트롤러에서 바인딩 또는 검증 설정을 변경하고 싶을 때 사용
AccountController.class
@Controller
@RequiredArgsConstructor
public class AccountController {
private final SignUpFormValidator signUpFormValidator;
/**
* SignUpForm데이터를 받을때 바인더를 설정
* public String signUpSubmit(@Valid SignUpForm signUpForm, Errors errors)
* @Valid SignUpForm이랑 매핑
*/
@InitBinder("signUpForm")
public void initBinder(WebDataBinder webDataBinder){
webDataBinder.addValidators(signUpFormValidator);
}
@GetMapping("/sign-up")
public String signUpForm(Model model){
model.addAttribute(new SignUpForm());
return "account/sign-up";
}
@PostMapping("/sign-up")
public String signUpSubmit(@Valid SignUpForm signUpForm, Errors errors){
if (errors.hasErrors()){
return "account/sign-up";
}
// TODO : 회원가입 처리
return "redirect:/";
}
}
signUpFormValidator.class
@Component
@RequiredArgsConstructor
public class SignUpFormValidator implements Validator {
private final AccountRepository accountRepository;
@Override
public boolean supports(Class<?> clazz) {
return clazz.isAssignableFrom(SignUpForm.class);
}
@Override
public void validate(Object target, Errors errors) {
SignUpForm signUpForm = (SignUpForm) errors;
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()}, "이미 사용중인 닉네임입니다.");
}
}
}
rejectValue() 메소드 형태
errors.rejectValue ( String field, String errorCode, String, @Nullable Object[] errorArgs, @Nullable String defaultMessage);
AccountRepository.interface
@Transactional(readOnly = true)
public interface AccountRepository extends JpaRepository<Account, Long> {
boolean existsByEmail(String email);
boolean existsByNickname(String nickname);
}
참고
'Dot Programming > Spring Clone' 카테고리의 다른 글
[스프링 웹앱 프로젝트 #7]회원가입 : 리팩토링 및 테스트 (0) | 2020.11.18 |
---|---|
[스프링 웹앱 프로젝트 #6]회원가입 폼 서브밋 처리 (0) | 2020.11.05 |
[스프링 웹앱 프로젝트 #4]회원 가입 뷰 (0) | 2020.11.03 |
[스프링 웹앱 프로젝트 #3]회원 가입 컨트롤러 (0) | 2020.11.02 |
[스프링 웹앱 프로젝트 #2]계정 도메인 생성 (0) | 2020.11.02 |