Web/Spring

[Spring] 스프링부트 + JPA + thymeleaf + Spring Security로 회원가입 + 게시판(수정, 삭제, 등록, 조회, 댓글, 좋아요) + 로그인 구현하기 #8 게시물 수정하기

poopooreum 2024. 8. 29. 20:30
반응형

✏️ 게시물 수정 로직

  1. 로그인 한 유저가 자신의 게시물에서 내용만 수정할 수 있다.
  2. 수정한 내용을 입력하면 컨트롤러가 UpdateDTO를 통해 게시물의 번호와 수정 내용을 받아온다.
  3. 컨트롤러는 유저가 로그인이 되어 있는지, boardService을 통해 게시물의 번호가 Board DB에 존재하는지 그리고 입력한 유저가 그 게시물의 주인인지 확인 후 게시물을 Board DB에 저장한다.
  4. 위의 조건들을 만족시키지 못하면 게시물을 수정할 수 없다

✏️ 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);
    }
}

반응형