[코드로 배우는 스프링부트 웹 프로젝트] - 연관관계(5) : 컨트롤러 생성

Jongwon·2023년 1월 9일
0
post-thumbnail

이전 guestbook 예제의 템플릿을 먼저 가져오겠습니다.

그리고 BoardController를 생성한 뒤, 목록화면에 접근을 처리하는 메서드까지 생성해두겠습니다.
BoardController

package org.zerock.board.controller;

import lombok.RequiredArgsConstructor;
import lombok.extern.log4j.Log4j2;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.zerock.board.dto.PageRequestDTO;
import org.zerock.board.service.BoardService;

@Controller
@Log4j2
@RequestMapping("/board")
@RequiredArgsConstructor
public class BoardController {
    
    @Autowired
    private final BoardService boardService;
    
    @GetMapping("/list")
    public void list(PageRequestDTO pageRequestDTO, Model model) {
        
        log.info("list......." + pageRequestDTO);
        
        model.addAttribute("result", boardService.getList(pageRequestDTO));

    }
}

다음으로는 list 페이지를 생성하겠습니다.

list.html

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">

<th:block th:replace="~{/layout/basic::setContent(~{this::content})}">
    <th:block th:fragment="content">
        <h1 class="mt-4">Board List Page
            <span>
                <a th:href="@{/board/register}">
                    <button type="button" class="btn btn-outline-primary">REGISTER</button>
                </a>
            </span>
        </h1>

        <form action="/board/list" method="get" id="searchForm">
            <div class="input-group">
                <input type="hidden" name="page" value="1">
                <div class="input-group-prepend">
                    <select class="custom-select" name="type">
                        <option th:selected="${pageRequestDTO.type == null}">------</option>
                        <option value="t" th:selected="${pageRequestDTO.type == 't'}">제목</option>
                        <option value="c" th:selected="${pageRequestDTO.type == 'c'}">내용</option>
                        <option value="w" th:selected="${pageRequestDTO.type == 'w'}">작성자</option>
                        <option value="tc" th:selected="${pageRequestDTO.type == 'tc'}">제목 + 내용</option>
                        <option value="tcw" th:selected="${pageRequestDTO.type == 'tcw'}">제목 + 내용 + 작성자</option>
                    </select>
                </div>
                <input class="form-control" name="keyword" th:value="${pageRequestDTO.keyword}">
                <div class="input-group-append" id="button-addon4">
                    <button class="btn btn-outline-secondary btn-search" type="button">Search</button>
                    <button class="btn btn-outline-secondary btn-clear" type="button">Clear</button>
                </div>
            </div>
        </form>

        <table class="table table-striped">
            <thead>
            <tr>
                <th scope="col">#</th>
                <th scope="col">Title</th>
                <th scope="col">Content</th>
                <th scope="col">Regdate</th>
            </tr>
            </thead>

            <tbody>
            <tr th:each="dto : ${result.dtoList}">
                <th scope="row">
                    <a th:href="@{/board/read(bno=${dto.bno}, page=${result.page}, type=${pageRequestDTO.type}, keyword=${pageRequestDTO.keyword})}">
                        [[${dto.bno}]]
                    </a>
                </th>
              //수정
                <td>[[${dto.title}]] ----------- [<b th:text="${dto.replyCount}"></b>]</td>
                <td>[[${dto.writerName}]] <small>[[${dto.writerEmail}]]</small></td>
                <td>[[${#temporals.format(dto.regDate, 'yyyy/MM/dd')}]]</td>
            </tr>
            </tbody>
        </table>

        <ul class="pagination h-100 justify-content-center align-items-center">
            <li class="page-item" th:if="${result.prev}">
                <a class="page-link" th:href="@{/board/list(page=${result.start - 1}, type=${pageRequestDTO.type}, keyword=${pageRequestDTO.keyword})}" tabindex="-1">Previous</a>
            </li>

            <li th:class=" 'page-item ' + ${result.page == page ? 'active' : ''} " th:each="page: ${result.pageList}">
                <a class="page-link" th:href="@{/board/list(page=${page}, type=${pageRequestDTO.type}, keyword=${pageRequestDTO.keyword})}">
                    [[${page}]]
                </a>
            </li>

            <li class="page-item" th:if="${result.next}">
                <a class="page-link" th:href="@{/board/list(page=${result.end + 1}, type=${pageRequestDTO.type}, keyword=${pageRequestDTO.keyword})}">Next</a>
            </li>
        </ul>

        <div class="modal" tabindex="-1" role="dialog">
            <div class="modal-dialog" role="document">
                <div class="modal-content">
                    <div class="modal-header">
                        <h5 class="modal-title">Modal title</h5>
                        <button type="button" class="close" data-dismiss="modal" aria-label="Close">
                            <span aria-hidden="true">&times;</span>
                        </button>
                    </div>
                    <div class="modal-body">
                        <p>Modal body text goes here.</p>
                    </div>
                    <div class="modal-footer">
                        <button type="button" class="btn btn-primary">Save changes</button>
                        <button type="button" class="btn btn-secondary close" data-dismiss="modal">Close</button>
                    </div>
                </div>
            </div>
        </div>

        <script th:inline="javascript">
            var msg = [[${msg}]];

            console.log(msg);

            const $modal = $(".modal")

            if(msg) {
               $('.modal').show();
            }

            $(".close").on("click", () => {
                $modal.hide()
            });

            var searchForm = $("#searchForm");

            $('.btn-search').click(function(e) {
                searchForm.submit();
            });

            $('.btn-clear').click(function(e) {
                searchForm.empty().submit();
            });


        </script>
    </th:block>
</th:block>

guestbook 예제의 list.html에서 Ctrl + Fguestbook을 찾아 board로 바꾸고, gnobno로만 바꿉니다. 그리고 리스트의 내용에 해당하는 table을 위와 같이 수정하면 동작합니다.

제목 옆에 댓글 개수가 보입니다.



다음으로는 등록 화면을 만들겠습니다. 컨트롤러에 GET, POST 메서드를 추가합니다.

BoardController

	@GetMapping("/register")
    public void register() {
        log.info("register get.........");

    }

    @PostMapping("/register")
    public String registerPost(BoardDTO dto, RedirectAttributes redirectAttributes) {
        log.info("dto....." + dto);

        Long bno = boardService.register(dto);

        log.info("BNO: " + bno);

        redirectAttributes.addFlashAttribute("msg", bno);
        
        return "redirect:/board/list";
    }

register 페이지도 guestbook 예제와 거의 동일하고, guestbookboard로, writer부분을 writer email을 입력받을 수 있도록 변경합니다.

register.html

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">

<th:block th:replace="~{/layout/basic :: setContent(~{this::content})}">
    <th:block th:fragment="content">
        <h1 class="mt-4">Board Register Page</h1>

        <form th:action="@{/board/register}" th:method="post">
            <div class="form-group">
                <label>Title</label>
                <input type="text" class="form-control" name="title" placeholder="Enter Title">
            </div>
            <div class="form-group">
                <label>Content</label>
                <textarea class="form-control" rows="5" name="content"></textarea>
            </div>
            <div class="form-group">
                <label>Writer Email</label>
                <input type="email" class="form-control" name="writerEmail" placeholder="Enter Writer Email">
            </div>
            <button type="submit" class="btn btn-primary">Submit</button>
        </form>
    </th:block>
</th:block>

이제 생성하면 정상적으로 등록됩니다. 여기서 Writer의 이메일이 데이터베이스에 존재하지 않는다면 에러가 발생하므로, 존재하는 이메일로 등록해야 합니다.



마찬가지로 게시물 조회 페이지도 처리해줍니다.

read.html

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<th:block th:replace="~{/layout/basic :: setContent(~{this::content})}">

    <th:block th:fragment="content">

        <h1 class="mt-4">Board Read Page</h1>

        <div class="form-group">
            <label>Bno</label>
            <input type="text" class="form-control" name="bno" th:value="${dto.bno}" readonly>
        </div>

        <div class="form-group">
            <label>Title</label>
            <input type="text" class="form-control" name="title" th:value="${dto.title}" readonly>
        </div>

        <div class="form-group">
            <label>Content</label>
            <textarea class="form-control" name="content" rows="5" readonly>[[${dto.content}]]</textarea>
        </div>

        <div class="form-group">
            <label>Writer</label>
            <input type="text" class="form-control" name="writer" th:value="${dto.writerName}" readonly>
        </div>

        <div class="form-group">
            <label>RegDate</label>
            <input type="text" class="form-control" name="regDate" th:value="${#temporals.format(dto.regDate, 'yyyy/MM/dd HH:mm:ss')}" readonly>
        </div>

        <div class="form-group">
            <label>ModDate</label>
            <input type="text" class="form-control" name="modDate" th:value="${#temporals.format(dto.modDate, 'yyyy/MM/dd HH:mm:ss')}" readonly>
        </div>

        <a th:href="@{/board/modify(bno=${dto.bno}, page=${requestDTO.page}, type=${requestDTO.type}, keyword=${requestDTO.keyword})}">
            <button type="button" class="btn btn-primary">Modify</button>
        </a>

        <a th:href="@{/board/list(page=${requestDTO.page}, type=${requestDTO.page}, keyword=${requestDTO.keyword})}">
            <button type="button" class="btn btn-info">List</button>
        </a>
    </th:block>
</th:block>

마찬가지로 read 페이지도 이전 예제에서 몇가지만 수정해서 적용합니다.

BoardController

    @GetMapping("/read")
    public void read(@ModelAttribute("requestDTO") PageRequestDTO pageRequestDTO, Long bno, Model model) {
        log.info("bno: " + bno);
        BoardDTO boardDTO = boardService.get(bno);

        log.info(boardDTO);

        model.addAttribute("dto", boardDTO);
    }


수정 페이지에 삭제 버튼까지 있으므로 둘을 한번에 처리하겠습니다. 수정의 GET은 read와 동일하므로 @GetMapping/modify를 추가합니다. POST는 아래와 같이 작성합니다.

BoardController

	@PostMapping("/modify")
    public String modify(BoardDTO dto, @ModelAttribute("requestDTO") PageRequestDTO pageRequestDTO, RedirectAttributes redirectAttributes) {
        log.info("post modify..........");
        log.info("dto: " + dto);
        
        boardService.modify(dto);
        
        redirectAttributes.addAttribute("page", pageRequestDTO.getPage());
        redirectAttributes.addAttribute("type", pageRequestDTO.getType());
        redirectAttributes.addAttribute("keyword", pageRequestDTO.getKeyword());
        
        redirectAttributes.addAttribute("bno", dto.getBno());
        
        return "redirect:/board/read";
    }
    
    @PostMapping("/delete")
    public String delete(long bno, RedirectAttributes redirectAttributes) {
        log.info("bno: " + bno);
        
        boardService.removeWithReplies(bno);
        
        redirectAttributes.addFlashAttribute("msg", bno);
        
        return "redirect:/board/list";
    }

modify.html

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<th:block th:replace="~{/layout/basic :: setContent(~{this::content})}">

    <th:block th:fragment="content">

        <h1 class="mt-4">Board Modify Page</h1>

        <form action="/board/modify" method="post">
            <input type="hidden" name="page" th:value="${requestDTO.page}">
            <input type="hidden" name="type" th:value="${requestDTO.type}">
            <input type="hidden" name="keyword" th:value="${requestDTO.keyword}">

            <div class="form-group">
                <label>Bno</label>
                <input type="text" class="form-control" name="bno" th:value="${dto.bno}" readonly>
            </div>

            <div class="form-group">
                <label>Title</label>
                <input type="text" class="form-control" name="title" th:value="${dto.title}">
            </div>

            <div class="form-group">
                <label>Content</label>
                <textarea class="form-control" name="content" rows="5">[[${dto.content}]]</textarea>
            </div>

            <div class="form-group">
                <label>Writer</label>
                <input type="text" class="form-control" name="writer" th:value="${dto.writerName}" readonly>
            </div>

            <div class="form-group">
                <label>RegDate</label>
                <input type="text" class="form-control" th:value="${#temporals.format(dto.regDate, 'yyyy/MM/dd HH:mm:ss')}" readonly>
            </div>

            <div class="form-group">
                <label>ModDate</label>
                <input type="text" class="form-control" th:value="${#temporals.format(dto.modDate, 'yyyy/MM/dd HH:mm:ss')}" readonly>
            </div>
        </form>

        <button type="button" class="btn btn-primary modifyBtn">Modify</button>
        <button type="button" class="btn btn-info listBtn">List</button>
        <button type="button" class="btn btn-danger removeBtn">Remove</button>

        <script th:inline="javascript">
            var actionForm = $("form");

            $(".removeBtn").click(function(){
                actionForm
                    .attr("action", "/board/remove")
                    .attr("method","post");
                actionForm.submit();
            });

            $(".modifyBtn").click(function() {
                if(!confirm("수정하시겠습니까?")) {
                    return;
                }
                actionForm
                    .attr("action", "/board/modify")
                    .attr("method", "post")
                    .submit();
            });

            $(".listBtn").click(function() {
                var page = $("input[name='page']");
                var type = $("input[name='type']");
                var keyword = $("input[name='keyword']");

                actionForm.empty();

                actionForm.append(page);
                actionForm.append(type);
                actionForm.append(keyword);

                actionForm
                    .attr("action", "/board/list")
                    .attr("method", "get");

                actionForm.submit();
            })
        </script>
    </th:block>
</th:block>
profile
Backend Engineer

0개의 댓글