📚 공부한 책 : 코드로배우는 스프링 부트 웹프로젝트
❤️ github 주소 : https://github.com/qkralswl689/LearnFromCode/tree/main/board2022
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));
}
}
/borad/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>
<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>
게시물 등록 처리시 반드시 작성자는 member 테이블에 존재하는 이메일 일 경우 등록 처리한다
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";
}
}
<!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>
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);
}
}
<!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>
- 수정을 위해 GET 방식으로 게시물을 조회하는것은 read()와 동일하다
-> read()메서드에 "/modify"를 추가해 사용한다- POST 방식의 처리는 boardService의 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";
}
}
★ 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>