-
[김영한 스프링] 32. 로그인 처리1 쿠키, 세션 - 홈 화면 & 회원 가입Spring/스프링 MVC 2편 - 백엔드 웹 개발 활용 기술 2023. 9. 12. 03:37
홈 화면
HomeController - home() 수정
package hello.login.web; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.GetMapping; @Slf4j @Controller public class HomeController { @GetMapping("/") public String home() { return "home"; } }
templates/home.html 추가
<!DOCTYPE HTML> <html xmlns:th="http://www.thymeleaf.org"> <head> <meta charset="utf-8"> <link th:href="@{/css/bootstrap.min.css}" href="css/bootstrap.min.css" rel="stylesheet"> </head> <body> <div class="container" style="max-width: 600px"> <div class="py-5 text-center"> <h2>홈 화면</h2> </div> <div class="row"> <div class="col"> <button class="w-100 btn btn-secondary btn-lg" type="button" th:onclick="|location.href='@{/members/add}'|"> 회원 가입 </button> </div> <div class="col"> <button class="w-100 btn btn-dark btn-lg" onclick="location.href='items.html'" th:onclick="|location.href='@{/login}'|" type="button"> 로그인 </button> </div> </div> <hr class="my-4"> </div> <!-- /container --> </body> </html>
main/resources/templates/home.html 생성
실행
회원 가입
Member
package hello.login.domain.member; import lombok.Data; import javax.validation.constraints.NotEmpty; @Data public class Member { private Long id; @NotEmpty private String loginId; // 로그인 id @NotEmpty private String name; // 사용자 이름 @NotEmpty private String password; }
main/java/hello/login/domain/member/Member 생성
MemberRepository
main/java/hello/login/domain/member/MemberRepository 생성
package hello.login.domain.member; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Repository; import java.util.*; /** * 동시성 문제가 고려되어 있지 않음, 실무에서는 ConcurrentHashMap, AtomicLong 사용 고려 */ @Slf4j @Repository public class MemberRepository { private static Map<Long, Member> store = new HashMap<>(); // static 사용 private static long sequence = 0L; // static 사용 public Member save(Member member) { member.setId(++sequence); log.info("save : member={}", member); store.put(member.getId(), member); return member; } public Member findById(Long id) { return store.get(id); } // public Member findByLoginId(String loginId) { // List<Member> all = findAll(); // for (Member m : all) { // if (m.getLoginId().equals(loginId)) { // return m; // } // } // // return null; // } public Optional<Member> findByLoginId(String loginId) { // List<Member> all = findAll(); // for (Member m : all) { // if (m.getLoginId().equals(loginId)) { // return Optional.of(m); // } // } // // return Optional.empty(); return findAll().stream().filter(m -> m.getLoginId().equals(loginId)).findFirst(); } public List<Member> findAll() { return new ArrayList<>(store.values()); } public void clearStore() { store.clear(); } }
MemberController
main/java/hello/login/web/member/MemberRepository 생성
package hello.login.web.member; import hello.login.domain.member.Member; import hello.login.domain.member.MemberRepository; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Controller; import org.springframework.validation.BindingResult; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.ModelAttribute; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestMapping; import javax.validation.Valid; @Controller @RequiredArgsConstructor @RequestMapping("/members") public class MemberController { private final MemberRepository memberRepository; @GetMapping("/add") public String addForm(@ModelAttribute("member") Member member) { return "members/addMemberForm"; } @PostMapping("/add") public String save(@Valid @ModelAttribute Member member, BindingResult bindingResult) { if (bindingResult.hasErrors()) { return "members/addMemberForm"; } memberRepository.save(member); return "redirect:/"; } }
@ModelAttribute("member")를 @ModelAttribute로 변경해도 결과는 같다. 여기서는 IDE에서 인식 문제가 있어서 적용했다.
회원 가입 뷰 템플릿 - addMemberForm.html
<!DOCTYPE HTML> <html xmlns:th="http://www.thymeleaf.org"> <head> <meta charset="utf-8"> <link th:href="@{/css/bootstrap.min.css}" href="../css/bootstrap.min.css" rel="stylesheet"> <style> .container { max-width: 560px; } .field-error { border-color: #dc3545; color: #dc3545; } </style> </head> <body> <div class="container"> <div class="py-5 text-center"> <h2>회원 가입</h2> </div> <h4 class="mb-3">회원 정보 입력</h4> <form action="" th:action th:object="${member}" method="post"> <div th:if="${#fields.hasGlobalErrors()}"> <p class="field-error" th:each="err : ${#fields.globalErrors()}" th:text="${err}">전체 오류 메시지</p> </div> <div> <label for="loginId">로그인 ID</label> <input type="text" id="loginId" th:field="*{loginId}" class="form-control" th:errorclass="field-error"> <div class="field-error" th:errors="*{loginId}" /> </div> <div> <label for="password">비밀번호</label> <input type="password" id="password" th:field="*{password}" class="form-control" th:errorclass="field-error"> <div class="field-error" th:errors="*{password}" /> </div> <div> <label for="name">이름</label> <input type="text" id="name" th:field="*{name}" class="form-control" th:errorclass="field-error"> <div class="field-error" th:errors="*{name}" /> </div> <hr class="my-4"> <div class="row"> <div class="col"> <button class="w-100 btn btn-primary btn-lg" type="submit">회원 가입</button> </div> <div class="col"> <button class="w-100 btn btn-secondary btn-lg" onclick="location.href='items.html'" th:onclick="|location.href='@{/}'|" type="button">취소</button> </div> </div> </form> </div> <!-- /container --> </body> </html>
main/resources/templates/member/addMemberForm.html 생성
실행
결과
회원용 테스트 데이터 추가
편의상 테스트용 회원 데이터를 추가하자.
- loginId : test
- password : test!
- name : 테스터
TestDataInit
package hello.login; import hello.login.domain.item.Item; import hello.login.domain.item.ItemRepository; import hello.login.domain.member.Member; import hello.login.domain.member.MemberRepository; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Component; import javax.annotation.PostConstruct; @Component @RequiredArgsConstructor public class TestDataInit { private final ItemRepository itemRepository; private final MemberRepository memberRepository; /** * 테스트용 데이터 추가 */ @PostConstruct public void init() { itemRepository.save(new Item("itemA", 10000, 10)); itemRepository.save(new Item("itemB", 20000, 20)); Member member = new Member(); member.setLoginId("test"); member.setPassword("test!"); member.setName("테스터"); memberRepository.save(member); } }
실행
출처 : https://www.inflearn.com/course/%EC%8A%A4%ED%94%84%EB%A7%81-mvc-2
'Spring > 스프링 MVC 2편 - 백엔드 웹 개발 활용 기술' 카테고리의 다른 글
[김영한 스프링] 34. 로그인 처리1 쿠키, 세션 - 로그인 처리하기(세션 동작 방식 & 세션 직접 만들기 & 직접 만든 세션 적용) (0) 2023.09.15 [김영한 스프링] 33. 로그인 처리1 쿠키, 세션 - 로그인 기능 & 쿠키 사용 & 보안 문제 (0) 2023.09.12 [김영한 스프링] 31. 로그인 처리1 쿠키, 세션 - 로그인 요구사항 & 프로젝트 생성 & 세팅 (0) 2023.09.08 [김영한 스프링] 30. 검증2 Bean Validation - HTTP 메시지 컨버터 (0) 2023.09.07 [김영한 스프링] 29. 검증2 Bean Validation - Form 전송 객체 분리 프로젝트 준비 V4 & 소개 & 개발 (0) 2023.09.07