[김영한 스프링] 32. 로그인 처리1 쿠키, 세션 - 홈 화면 & 회원 가입
홈 화면
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
스프링 MVC 2편 - 백엔드 웹 개발 활용 기술 - 인프런 | 강의
웹 애플리케이션 개발에 필요한 모든 웹 기술을 기초부터 이해하고, 완성할 수 있습니다. MVC 2편에서는 MVC 1편의 핵심 원리와 구조 위에 실무 웹 개발에 필요한 모든 활용 기술들을 학습할 수 있
www.inflearn.com