SpringBoot with JPAプロジェクト(N:1)6.投稿リスト、投稿登録、投稿ブラウズ、変更/削除



📚 勉強した本:コード学習を用いたSpring Boot Webプロジェクト
▼githubアドレス:https://github.com/qkralswl689/LearnFromCode/tree/main/board2022
1.投稿リストの印刷
1-1.コントローラの作成
import com.example.board2022.dto.PageRequestDTO;
import com.example.board2022.service.BoardService;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
@RequestMapping("/board")
@RequiredArgsConstructor // 자동주입
public class BoardController {

    private final BoardService boardService;

    @GetMapping("/list")
    public void list(@ModelAttribute PageRequestDTO pageRequestDTO, Model model){

        model.addAttribute("result",boardService.getList(pageRequestDTO));
    }
}
1-2.スクリーンの作成(html)
以下のhtmlは/borad/listパスで表示できます.
  • 画面では、タイトル、作成者、コメント数、公開日を表示できます.
  • 必要なページ番号をクリックすると、ページ
  • を移動できます.
    <!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>
    
            <table class="table table-striped">
                <thead>
                <tr>
                    <th scope="col">#</th>
                    <th scope="col">Title</th>
                    <th scope="col">Writer</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>
    
        </th:block>
    
    </th:block>
  • 運転結果
  • 2.新規投稿の登録
    投稿登録を処理する場合は、memberテーブルに存在する電子メールを登録する必要があります.
    -> register()インプリメンテーションの表示
    2-1.コントローラの作成
    GET方式で実行するリンクを追加し、POST方式で実際に処理する方法
    ->投稿にログインし、投稿リストページに移動
    import com.example.board2022.dto.BoardDTO;
    import com.example.board2022.service.BoardService;
    import lombok.RequiredArgsConstructor;
    import org.springframework.stereotype.Controller;
    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.RequestMapping;
    import org.springframework.web.servlet.mvc.support.RedirectAttributes;
    
    @Controller
    @RequestMapping("/board")
    @RequiredArgsConstructor // 자동주입
    public class BoardController {
    
        private final BoardService boardService;
    
        @GetMapping("/register")
        public void register(){
        }
    
        @PostMapping("/register")
        public String regesterPost(BoardDTO dto, RedirectAttributes redirectAttributes){
    
            Long bno = boardService.register(dto);
    
            redirectAttributes.addFlashAttribute("msg",bno);
    
            return "redirect:/board/list";
        }
    }
    2-2.スクリーンの作成(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="Writer Email ">
                </div>
    
                <button type="submit" class="btn btn-primary">Submit</button>
            </form>
    
        </th:block>
    
    </th:block>
  • 運転結果
  • 3.投稿の参照
    3-1.コントローラの作成
    import com.example.board2022.dto.BoardDTO;
    import com.example.board2022.dto.PageRequestDTO;
    import com.example.board2022.service.BoardService;
    import lombok.RequiredArgsConstructor;
    import org.springframework.stereotype.Controller;
    import org.springframework.ui.Model;
    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.RequestMapping;
    import org.springframework.web.servlet.mvc.support.RedirectAttributes;
    
    @Controller
    @RequestMapping("/board")
    @RequiredArgsConstructor // 자동주입
    public class BoardController {
    
        private final BoardService boardService;
    
        @GetMapping("/read")
        public void read(@ModelAttribute("requestDTO") PageRequestDTO pageRequestDTO,Long bno, Model model){
    
            BoardDTO boardDTO = boardService.get(bno);
    
            model.addAttribute("dto",boardDTO);
        }
    }
    3-2.スクリーンの作成(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="gno" 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" rows="5" name="content" 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.type}, keyword =${requestDTO.keyword})}">
                <button type="button" class="btn btn-info">List</button>
            </a>
    
    
        </th:block>
    
    </th:block>
    
  • 運転画面
  • 4.投稿の変更/削除
    4-1.コントローラの作成
  • を修正するには、read()と同じようにGETで投稿を表示します.
    ->read()メソッドに「/modify」を
  • に追加
  • POST方式の処理は、呼び出しボードサービスのmodify()およびremove()によって処理される
    import com.example.board2022.dto.BoardDTO;
    import com.example.board2022.dto.PageRequestDTO;
    import com.example.board2022.service.BoardService;
    import lombok.RequiredArgsConstructor;
    import org.springframework.stereotype.Controller;
    import org.springframework.ui.Model;
    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.RequestMapping;
    import org.springframework.web.servlet.mvc.support.RedirectAttributes;
    
    @Controller
    @RequestMapping("/board")
    @RequiredArgsConstructor // 자동주입
    public class BoardController {
    
        private final BoardService boardService;
    
    
    /*    @GetMapping("/read")
        public void read(@ModelAttribute("requestDTO") PageRequestDTO pageRequestDTO,Long bno, Model model){
    
            BoardDTO boardDTO = boardService.get(bno);
    
            model.addAttribute("dto",boardDTO);
        }*/
    
        @GetMapping({"/read","/modify"})
        public void read(@ModelAttribute("requestDTO")PageRequestDTO pageRequestDTO,Long bno,Model model){
    
            BoardDTO boardDTO = boardService.get(bno);
    
            model.addAttribute("dto",boardDTO);
        }
    
    
        @PostMapping("modify")
        public String modify(BoardDTO dto, @ModelAttribute("requestDTO") PageRequestDTO requestDTO,RedirectAttributes redirectAttributes){
    
            boardService.modify(dto);
    
            redirectAttributes.addAttribute("page",requestDTO.getPage());
            redirectAttributes.addAttribute("type",requestDTO.getType());
            redirectAttributes.addAttribute("keyword",requestDTO.getKeyword());
    
            redirectAttributes.addAttribute("bno",dto.getBno());
    
            return "redirect:/board/read";
        }
        
            @PostMapping("remove")
        public String remove(long bno,RedirectAttributes redirectAttributes){
    
            boardService.removeWithReplies(bno);
    
            redirectAttributes.addFlashAttribute("msg",bno);
    
            return "redirect:/board/list";
        }
    
    }
    4-2.スクリーンの作成(html)
    ★formタグにJavaScriptを使用し、このボタンをクリックしたときの動作制御
    <!DOCTYPE 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" rows="5" name="content">[[${dto.content}]]</textarea>
                </div>
                <div class="form-group">
                    <label >Writer</label>
                    <input type="text" class="form-control" name="writer" th:value="${dto.writerEmail}" 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"); //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 pageInfo = $("input[name='page']");
                    var page = $("input[name='page']");
                    var type = $("input[name='type']");
                    var keyword = $("input[name='keyword']");
    
                    actionForm.empty(); //form 태그의 모든 내용을 지우고
    
                    actionForm.append(page);
                    actionForm.append(type);
                    actionForm.append(keyword);
    
    
                    actionForm
                        .attr("action", "/board/list")
                        .attr("method","get");
    
                    actionForm.submit();
    
                })
    
            </script>
    
    
        </th:block>
    
    </th:block>
    
  • 運転画面