728x90
320x100
[참고]
김영한님 스프링 강의를 바탕으로 진행되는 토이프로젝트의 과정을 기록하는 글입니다.
둥근 피드백은 언제나 환영입니다.
[오늘의 개발내용]
1. 타임라인 컨트롤러 수정하기
2. 로그인시 로그인 아이디 세션에 추가하기
3. 타임라인 등록 Html 수정하기
[서론]
회원가입 화면 구현한김에 이어서 타임라인 등록 부분 수정하기
수정할 부분이 많고 오래걸려서 이번 일지에는 레이아웃만 수정할 예정.
1. 타임라인 컨트롤러 수정하기
TimelineController.java
package toyproject.bookbookclub.web.timeline;
//////생략//////
@Controller
@RequiredArgsConstructor
@RequestMapping("/timeline")
public class TimelineController {
private final TimelineValidator timelineValidator;
private final TimeLineRepository timeLineRepository;
private final MemberRepository memberRepository;
private final FileStore fileStore;
//////생략//////
@GetMapping("/add")
public String addForm(HttpServletRequest request, Model model) throws IOException {
String loginId = (String) request.getSession().getAttribute("loginId");
Member member = memberRepository.findById(loginId);
UploadFile profileImage = member.getProfileImage();
Timeline timeline = new Timeline();
timeline.setMemberId(loginId);
model.addAttribute("timeline", timeline);
model.addAttribute("member", member);
model.addAttribute("profileImage", profileImage);
return "timeline/addForm";
}
//////생략//////
}
- 타임라인 등록 폼을 띄울 때 멤버 아이디와 닉네임은 보일 수 있도록 세션에 저장된 로그인 아이디로 멤버 객체를 가져온다. (그러다보니 멤버 레파지토리도 주입해줌)
- 프로필 이미지도 멤버 객체에 있는 프로필 이미지를 UpoladFIle 형태로 가져와서 일단 Model에 넣어주었다. (이 부분을 어떻게 구현해야 할지 몰라서 지피티한테 많이 물어보고 삽질함...)
- 근데 보면 request.getSession().getAttribute("loginId")를 가져오는 부분이 있는데 이 부분은 로그인 시에 세션에 추가하도록 했다. (아래 소스 참조)
2. 로그인시 세션에 로그인 아이디 추가하기
LoginController.java
package toyproject.bookbookclub.web.login;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpSession;
import jakarta.validation.Valid;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
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.RequestParam;
import toyproject.bookbookclub.domain.Members.Member;
import toyproject.bookbookclub.domain.Login.LoginForm;
import toyproject.bookbookclub.domain.Login.LoginService;
import toyproject.bookbookclub.web.SessionConst;
@Slf4j
@Controller
@RequiredArgsConstructor
public class LoginController {
private final LoginService loginService;
@GetMapping("/login")
public String loginForm(@ModelAttribute("loginForm") LoginForm form) {
return "login/loginForm";
}
@PostMapping("/login")
public String login(@Valid @ModelAttribute LoginForm form, BindingResult bindingResult
,@RequestParam(defaultValue = "/") String redirectURL,
HttpServletRequest request) {
if (bindingResult.hasErrors()) {
return "login/loginForm";
}
Member loginMember = loginService.login(form.getLoginId(),
form.getPassword());
log.info("login? {}", loginMember);
if (loginMember == null) {
bindingResult.reject("loginFail", "아이디 또는 비밀번호가 맞지 않습니다.");
return "login/loginForm";
}
//세션이 있으면 있는 세션을 반환, 없으면 신규 세션 생성
HttpSession session = request.getSession();
session.setAttribute(SessionConst.LOGIN_MEMBER, loginMember);
session.setAttribute("loginId", form.getLoginId()); //로그인 아이디 세션에 추가!
//redirectUrl 적용
return "redirect:" + redirectURL;
}
}
3. 타임라인 등록 Html 수정하기
addForm.html
<!DOCTYPE HTML>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="utf-8">
<link href="../css/bootstrap.min.css"
th:href="@{/css/bootstrap.min.css}" rel="stylesheet">
<script th:src="@{/js/timeline/addForm.js}"></script>
<style>
.container {
max-width: 560px;
}
.field-error {
border-color: #dc3545;
color: #dc3545;
}
#profileImagePreview {
border-radius: 70%;
overflow: hidden;
}
</style>
</head>
<body>
<div class="container">
<div class="py-5 text-center">
<h2 th:text="#{page.addTimeline}">타임라인 등록</h2>
</div>
<div th:if="${profileImage}" style="margin-bottom: 10px;">
<img id="profileImagePreview" th:src="|/basic/members/images/${profileImage.getStoreFileName()}|" width="16" height="16"/>
<span class="h5" th:text="${member.nickName}"></span>
<span class="h5" style="color: gray;" th:text="'@' + ${member.id}"></span>
</div>
<form action="timeline.html" id="addForm" th:action th:object="${timeline}" method="post">
<div th:unless="${profileImage}">
<svg xmlns="http://www.w3.org/2000/svg" width="30" height="30" fill="currentColor" class="bi bi-person-circle" viewBox="0 0 16 16" style="color: gray;">
<path d="M11 6a3 3 0 1 1-6 0 3 3 0 0 1 6 0"/>
<path fill-rule="evenodd" d="M0 8a8 8 0 1 1 16 0A8 8 0 0 1 0 8m8-7a7 7 0 0 0-5.468 11.37C3.242 11.226 4.805 10 8 10s4.757 1.225 5.468 2.37A7 7 0 0 0 8 1"/>
</svg>
<span class="h6" style="color: gray;" th:text="'@' + ${member.id}"></span>
</div>
<div style="margin-bottom: 10px;">
<span class="h6">내가 읽은 책 / </span>
<span class="h6" th:if="*{bookId}" th:text="*{bookId}"></span>
<span class="h6" style="color: red;" th:unless="*{bookId}">읽은 책을 검색해주세요.</span>
<button type="button" class="btn btn-outline-info btn-sm">읽은 책 찾기</button>
</div>
<div style="width: 100%; height: 150px;">
<div style="float: left; width: 20%; text-align: center;">
<svg xmlns="http://www.w3.org/2000/svg" width="100" height="100" fill="currentColor" class="bi bi-book" viewBox="0 0 16 16" style="color: gray; padding-right: 10px;">
<path d="M1 2.828c.885-.37 2.154-.769 3.388-.893 1.33-.134 2.458.063 3.112.752v9.746c-.935-.53-2.12-.603-3.213-.493-1.18.12-2.37.461-3.287.811zm7.5-.141c.654-.689 1.782-.886 3.112-.752 1.234.124 2.503.523 3.388.893v9.923c-.918-.35-2.107-.692-3.287-.81-1.094-.111-2.278-.039-3.213.492zM8 1.783C7.015.936 5.587.81 4.287.94c-1.514.153-3.042.672-3.994 1.105A.5.5 0 0 0 0 2.5v11a.5.5 0 0 0 .707.455c.882-.4 2.303-.881 3.68-1.02 1.409-.142 2.59.087 3.223.877a.5.5 0 0 0 .78 0c.633-.79 1.814-1.019 3.222-.877 1.378.139 2.8.62 3.681 1.02A.5.5 0 0 0 16 13.5v-11a.5.5 0 0 0-.293-.455c-.952-.433-2.48-.952-3.994-1.105C10.413.809 8.985.936 8 1.783"/>
</svg>
<input type="text" id="bookImg" th:field="*{bookImg}" class="form-control" placeholder="이미지를 입력하세요" style="display: none;">
</div>
<div style="float: right; width: 80%;">
<div class="form-floating">
<textarea class="form-control" id="content" th:field="*{content}" th:errorclass="is-invalid"
placeholder="느낀점을 공유해주세요." style="height: 120px; resize: none;"></textarea>
<label for="content">소개글</label>
<div id="contentCounter" style="font-size: 0.87em; color: gray; text-align: right;">0/120</div>
<div class="is-invalid" th:errors="*{content}">내용 오류</div>
<div class="is-invalid" id="contentError" style="display: none;">글자수 제한</div>
</div>
</div>
</div>
<div style="width: 100%;">
<div class="row">
<div class="col">
<button class="w-100 btn btn-primary btn-lg" type="submit" id="saveBtn"
th:text="#{button.timeline.save}">타임라인 등록</button>
</div>
<div class="col">
<button class="w-100 btn btn-secondary btn-lg" onclick="location.href='allTimeline.html'"
th:onclick="|location.href='@{/timeline}'|" type="button" th:text="#{button.cancel}">취소</button>
</div>
</div>
</div>
</form>
</div> <!-- /container -->
</body>
</html>
전체적인 레이아웃이 싹 바뀌었는데
- 로그인 후에만 타임라인 등록이 가능하니까 프로필 이미지와 프로필 아이디를 띄우도록 했고
- 내가 읽은책은 '읽은 책 찾기'를 통해서 책 이름, 책 아이디, 책 이미지를 불러올껀데 그건 나중에 구현 예정.
- 그리고 글 내용을 입력하면 회원 소개글과 같이 120자가 초과되면 입력되지 않고 경고문이 뜬다.
그 밖에 수정할 부분이 많은데 너무 늘어지는 것 같아서 끊어서 커밋하려고 함.
(+) 로그인 화면 수정
<div class="col">
<button class="w-100 btn btn-secondary btn-lg" type="button"
th:onclick="|location.href='@{/basic/members/join}'|">
회원 가입
</button>
</div>
- 이건 번외인데 로그인 할 때 회원가입, 취소 보다는 회원가입 / 로그인이 나을 것 같아서 회원가입 버튼을 추가했다.
728x90
320x100
'💻 뚝딱뚝딱 > (구) 북북클럽' 카테고리의 다른 글
[개발일지#028] 로그인 화면 수정하기 (레이아웃 변경 및 아이디 기억하기 기능 구현) (0) | 2024.03.20 |
---|---|
[개발일지#027] 회원 컬럼 추가하기 / 회원가입 화면 수정 (유효성검사 등) (0) | 2024.03.19 |
[개발일지#026] 파일첨부 기능 만들기 (회원 프로필 이미지) (+) 피드백 반영 (2) | 2024.03.15 |
[개발일지#024] 인터셉터를 활용하여 로그인 구현하기 (3) | 2024.03.11 |
[개발일지#023] Validation 설정하기 (서버검증) (0) | 2024.03.08 |