스프링 부트 게시판 프로젝트 - 10 | 게시글 수정, 삭제 기능 개발

seren-dev·2022년 8월 30일
0

게시글 수정 및 삭제 기능 개발

게시판 컨트롤러 수정 및 추가

BoardController

package hello.board.controller.board;

import hello.board.controller.SessionConst;
import hello.board.entity.Board;
import hello.board.entity.User;
import hello.board.service.BoardService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;

import javax.validation.Valid;

@Controller
@Slf4j
@RequiredArgsConstructor
@RequestMapping("/board")
public class BoardController {

    private final BoardService boardService;

    @GetMapping
    public String postList(Model model) {
        model.addAttribute("list", boardService.findAll());
        return "board/postList";
    }

    @GetMapping("/{postId}")
    public String postView(@PathVariable Long postId, Model model) {
        log.info("postView");

        Board post = boardService.findOne(postId).orElseThrow();
        model.addAttribute("post", post);

        return "board/post";
    }

    @GetMapping("/register")
    public String registerForm(@ModelAttribute PostForm postForm) {
        return "board/registerForm";
    }

    @PostMapping("/register")
    public String register(@Valid @ModelAttribute PostForm postForm, BindingResult bindingResult, @SessionAttribute(name = SessionConst.LOGIN_USER, required = false) User loginUser, RedirectAttributes redirectAttributes) {

        if (bindingResult.hasErrors()) {
            log.info("errors = {}", bindingResult);
            return "board/registerForm";
        }

        Long registerId = boardService.register(postForm.getTitle(), postForm.getContent(), loginUser.getId());
        redirectAttributes.addAttribute("postId", registerId);

        return "redirect:/board/{postId}";
    }

    @GetMapping("/{postId}/edit")
    public String editForm(@PathVariable Long postId, Model model) {

        Board post = boardService.findOne(postId).orElseThrow();

        PostForm postForm = new PostForm();
        postForm.setTitle(post.getTitle());
        postForm.setContent(post.getContent());

        model.addAttribute("postForm", postForm);
        model.addAttribute("postId", postId);

        return "board/editForm";
    }

    @PostMapping("/{postId}/edit")
    public String edit(@PathVariable Long postId, @Valid @ModelAttribute PostForm postForm, BindingResult bindingResult) {

        if (bindingResult.hasErrors()) {
            log.info("errors = {}", bindingResult);
            return "board/editForm";
        }

        boardService.updateBoard(postId, postForm.getTitle(), postForm.getContent());

        return "redirect:/board/{postId}";
    }

    @PostMapping("/{postId}/delete")
    public String delete(@PathVariable Long postId) {
        boardService.deleteById(postId);
        return "redirect:/board";
    }
}
  • register() 게시글 등록 메서드 수정
    • RedirectAttributes를 사용하여 새로 만들어진 게시글의 상세 조회 화면으로 redirect하도록 한다.
  • editForm() : 게시글 수정 폼
    • @PathVariable로 URL에서 게시글 id(postId)를 가져온다.
    • boardService.findOne(postId).orElseThrow()로 해당 게시글을 가져온다.
    • 새로운 PostForm 객체를 생성 후, 제목과 내용을 설정하고, modelpostForm, postId를 넣고 뷰 화면으로 넘긴다.
  • edit() : 게시글 수정
    • Bean Validation 기술을 사용하여 postForm 객체를 검증한다. 에러가 있으면 board/editForm 뷰 화면을 다시 보여준다.
    • 검증에 통과하면 boardService.updateBoard()를 호출하여 게시글을 수정하고, 게시글 상세 조회 화면으로 redirect한다.
  • delete() : 게시글 삭제
    • @PathVariable로 URL에서 게시글 id(postId)를 가져온다.
    • boardService.deleteById(postId);로 해당 게시글을 삭제한다.
    • 게시글 조회 화면으로 redirect 한다.

RedirectAttributes
RedirectAttributes를 사용하면 URL 인코딩도 해주고, pathVarible, 쿼리 파라미터까지 처리해준다.

  • 예시) redirectAttributes.addAttribute("postId", registerId);
    redirectAttributes.addAttribute("status", true);
  • redirect:/board/{postId}
    • pathVariable 바인딩: {postId}
  • 나머지는 쿼리 파라미터로 처리: ?status=true
    => 자동으로 pathVariable 바인딩을하며, 바인딩이 안되는 것은 쿼리 파라미터로 넘어간다.

수정용 폼 뷰 템플릿

board/editForm.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: 700px;
    }
    .field-error {
    border-color: #dc3545;
    color: #dc3545;
    }
    </style>
</head>
<body>
<div class="container">
    <div class="py-5 text-center">
        <h2>게시글 수정</h2>
    </div>
    <form th:action th:object="${postForm}" method="post">
        <div>
            <label for="title">제목</label>
            <input type="text" id="title" th:field="*{title}" class="form-control"
                   th:errorclass="field-error">
            <div class="field-error" th:errors="*{title}" />
        </div>
        <div class="mb-3">
            <label for="content">내용</label>
            <textarea class="form-control" rows="5"
                      id="content" name="content"
                      th:value="*{content}" th:text="*{content}"></textarea>
        </div>
        <hr class="my-4">

        <button class="btn btn-primary" type="submit">
            수정 완료
        </button>

        <button class="btn btn-secondary"
                th:onclick="|location.href='@{/board/{postId}(postId=${postId})}'|"
                type="button">취소
        </button>

    </form>

</div>
</body>

수정 화면


DB에도 반영된 것을 확인할 수 있다.

삭제 후 조회

DB에도 반영된 것을 확인할 수 있다.


게시글 상세 조회 뷰 템플릿 변경

board/post.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: 700px;
    }
    .field-error {
    border-color: #dc3545;
    color: #dc3545;
    }
    </style>
</head>
<body>
<div class="container">
    <div class="py-5 text-center">
        <h2>게시글</h2>
    </div>

    <button class="btn btn-dark pull-right"
            onclick="location.href='board/postList.html'"
            th:onclick="|location.href='@{/board}'|"
            type="button">목록으로
    </button>

    <div>
        <label for="postId">게시판번호</label>
        <input type="text" id="postId" name="postId" class="form-control"
               value="1" th:value="${post.id}" readonly>
    </div>

    <div>
        <label for="postTitle">제목</label>
        <input type="text" id="postTitle" name="postTitle" class="form-control"
               value="제목" th:value="${post.title}" readonly>
    </div>
    <div>
        <label for="postContent">내용</label>
        <textarea class="form-control" rows="5"
                  id="postContent" name="postContent"
                  th:value="${post.content}" th:text="${post.content}" readonly></textarea>
    </div>
    <div>
        <label for="writer">작성자</label>
        <input type="text" id="writer" name="writer" class="form-control"
               value="작성자" th:value="${post.user.loginId}" readonly>
    </div>
    <div>
        <label for="registerDate">작성일</label>
        <input type="text" id="registerDate" name="registerDate" class="form-control"
               value="작성자" th:value="${post.registerDate}" readonly>
    </div>
    <hr class="my-4">

    <form th:action="@{/board/{postId}/delete(postId=${post.id})}" method="post">

        <button class="btn btn-primary"
                th:onclick="|location.href='@{/board/{postId}/edit(postId=${post.id})}'|"
                type="button">수정</button>

        <button class="btn btn-danger" type="submit">삭제</button>
    </form>

</div> <!-- /container -->

</body>
  • 게시글을 삭제 기능을 구현하기 위해 form 태그를 새로 생성
  • <form th:action="@{/board/{postId}/delete(postId=${post.id})}" method="post">
  • <button class="btn btn-danger" type="submit">삭제</button>

0개의 댓글