Web/Spring
[Spring] 스프링부트 + JPA + thymeleaf + Spring Security로 회원가입 + 게시판(수정, 삭제, 등록, 조회, 댓글, 좋아요) + 로그인 구현하기 #8 게시물 수정하기
poopooreum
2024. 8. 29. 20:30
반응형
✏️ 게시물 수정 로직
- 로그인 한 유저가 자신의 게시물에서 내용만 수정할 수 있다.
- 수정한 내용을 입력하면 컨트롤러가 UpdateDTO를 통해 게시물의 번호와 수정 내용을 받아온다.
- 컨트롤러는 유저가 로그인이 되어 있는지, boardService을 통해 게시물의 번호가 Board DB에 존재하는지 그리고 입력한 유저가 그 게시물의 주인인지 확인 후 게시물을 Board DB에 저장한다.
- 위의 조건들을 만족시키지 못하면 게시물을 수정할 수 없다
✏️ UpdateDTO 클래스
@Getter
@Setter
@Builder
public class UpdateDTO {
private Long idx;
private String content;
}
✏️ modify.html 생성
<!DOCTYPE HTML>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<title>Hello</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<link rel="stylesheet" th:href="@{/css/main.css}">
</head>
<body>
<h1>게시물 수정하기</h1>
<table class="table">
<thead class="thead-light">
<tr class="text-center">
<th scope="col">글번호</th>
<th scope="col">글제목</th>
<th scope="col">내용</th>
<th scope="col">작성자</th>
</tr>
</thead>
<tbody>
<form method="post" action="/member/update">
<tr th:each="board : ${board}">
<td scope="row" width="10%">
<input th:type="text" th:value="${board.idx}" readonly>
</td>
<td scope="row" width="20%">
<input th:type="text" th:value="${board.title}" readonly>
</td>
<td scope="row" width="10%">
<input th:type="text" th:value="${board.content}" th:name="content">
</td>
<td scope="row" width="10%">
<input th:type="text" th:value="${board.member.id}" readonly>
</td>
<td>
<input type="submit" name="modify" value="변경하기">
<input th:type="hidden" th:name="idx" th:value="${board.idx}">
</td>
</tr>
</form>
</tbody>
</table>
</body>
</html>
✏️ Api Controller 클래스
@PostMapping("/update") // 글 수정하기
public String update(UpdateDTO updateDTO, HttpServletRequest httpServletRequest) {
HttpSession session = httpServletRequest.getSession(false);
Optional<Object> idOptional = Optional.ofNullable(session.getAttribute("userId"));
if (idOptional.isEmpty()) {
log.error("로그인을 하지 않으면 글을 수정할 수 없습니다.");
return "home";
}
String id = idOptional.get().toString();
boolean isBoardExist = boardService.checkBoardExist(updateDTO.getIdx());
if (!isBoardExist) { // 게시물 수정 불가능
log.error("게시글이 존재하지 않습니다.");
return "redirect:/member/list";
}
boolean isOwner = boardService.checkIsOwner(updateDTO.getIdx(),id);
if(!isOwner){
log.error("주인이 아닙니다.");
return "redirect:/member/list";
}
boardService.update(updateDTO);
log.info("글이 수정되었습니다.");
return "redirect:/member/list";
}
로그인 되어 있는지 확인하고 되어 있지 않다면 로그인 화면으로 이동시킨다
UpdateDTO의 idx가 Board DB에 있는지 검사 후 없는 idx라면 메인 화면으로 이동(로그인은 되어있으므로)
수정하는 사람이 게시물의 주인인지 확인 한다
위의 3가지 조건을 다 만족시킨다면 boardService를 통해 수정한 게시물을 저장한다.
✏️ WebController 클래스
@GetMapping("/member/post")
public String post(Model model, HttpServletRequest httpServletRequest) {
HttpSession session = httpServletRequest.getSession(false);
Optional<Object> idOptional = Optional.ofNullable(session.getAttribute("userId"));
if(idOptional.isEmpty()){
log.error("권한 없음");
return "redirect:/login";
}
String id = idOptional.get().toString();
model.addAttribute("id", id);
return "post";
}
로그인 되어 있지 않다면 로그인 화면으로 이동시킨다
로그인 되어 있다면 세션에서 id를 얻어서 post.html에 넘겨준다
✏️ BoardRepository 인터페이스
long countByIdxAndMemberId(Long idx, String memberId);
JpaRepository에는 없는 쿼리문이지만 이런식으로 규칙있게 작성하여 쿼리문을 만들 수 있다.
전달받은 idx와 memberI가 Board DB에 있는지 검사 후 있는 게시물의 개수를 리턴해준다.
✏️ BoardService 인터페이스
boolean checkBoardExist(Long idx);
boolean checkIsOwner(Long idx, String id);
void update(UpdateDTO updateDTO);
idx를 가진 게시물이 존재하는지, idx와 id를 동시에 만족시키는 게시물이 존재하는지 검사
✏️ BoardServiceImp 클래스
@Override
public boolean checkBoardExist(Long idx) {
Optional<Board> board = boardRepository.findById(idx);
if (board.isEmpty()) { // 존재하지 않음
return false;
} else // 존재함
return true;
}
@Override
public boolean checkIsOwner(Long idx, String id) {
long count = boardRepository.countByIdxAndMemberId(idx,id);
return count != 0;
}
@Override
public void update(UpdateDTO updateDTO) {
Optional<Board> board = boardRepository.findById(updateDTO.getIdx());
if (board.isPresent()) {
Board boardEntity = board.get();
boardEntity.setContent(updateDTO.getContent());
boardRepository.save(boardEntity);
}
}
반응형