참조 :
★스프링부트 JPA 페이징 및 검색 처리, Jsp ,Thymeleaf
controller
//상세보기 @GetMapping("/board/{id}") public String findById(@PathVariable Long id, @AuthenticationPrincipal PrincipalDetails principal, @RequestParam(value = "page",defaultValue ="1", required = false) Optional<Integer> page, Model model) { int pageSize=5; Pageable pageable= PageRequest.of(page.isPresent()? page.get()-1 :0, pageSize); Page<Reply> replyList= replyService.replyList(pageable); Pagination pagination =new Pagination((int)replyList.getTotalElements(), page.get(), pageSize , 5); model.addAttribute("auth", principal.getUser()); model.addAttribute("board", boardService.boardDetail(id)); model.addAttribute("replyList", replyList); model.addAttribute("pagination", pagination); return "board/detail"; }
service
@Service @RequiredArgsConstructor @Transactional public class ReplyService { private final ReplyRepository replyRepository; public Page<Reply> replyList(Pageable pageable) { return replyRepository.findAll(pageable); } }
view
<!DOCTYPE html> <html xmlns:th="http://www.thymeleaf.org" xmlns:layout=http://www.ultraq.net.nz/thymeleaf/layout layout:decorate="~{layouts/layout1}" xmlns:sec="http://www.thymeleaf.org/extras/spring-security"> <div layout:fragment="content"> <div class="container"> <button type="button" class="btn btn-secondary" onclick="history.back()">돌아가기</button> <!-- 인증시 사용된 객체에 대한 정보 <b>Authenticated DTO:</b> <div sec:authentication="principal"></div> 인증시 사용된 객체의 Username (ID) <b>Authenticated username:</b> <div sec:authentication="name"></div> 객체의 권한te <b>Authenticated user role:</b> <div sec:authentication="principal.authorities"></div> --> <th:block th:if="${board.user.username ==auth.Username}"> <a th:href="@{'/board/'+${board.id}+'/updateForm'}" class="btn btn-warning">수정</a> <button id="btn-delete" class="btn btn-danger">삭제</button> </th:block> <br><br> <div class="mb-5"> 글번호 : <span id="id" class="mr-5"><i>[[${board.id}]]</i></span> 작성자 : <span><i>[[${board.user.username}]]</i></span> </div> <div class="form-group mb-5"> [[${board.title}]] </div> <hr> <div class="form-group"> <th:block th:utext="${board.content}"></th:block> </div> <hr> <div class="card"> <div class="card-body"> <textarea id="reply-content" class="form-control" rows="1" cols=""></textarea> </div> <div class="card-footer text-center"> <input type="hidden" name="boardId" id="boardId" th:value="${board.id}" > <button id="btn-reply-save" class="btn btn-primary">등록</button> </div> </div> <hr> <div class="card mt-5"> <div class="card-header">댓글 총 [[${pagination.listCnt}]] 개</div> <ul id="reply--box" class="list-group"> <th:block th:each ="reply, status : ${replyList.content}" > <li th:id="'reply-'+${reply.id}" class="list-group-item d-flex justify-content-between"> <div>[[${reply.content}]]</div> <div class="d-flex "> <div>작성자 : [[${reply.user.username}]]</div> <th:block th:if="${reply.user.id ==auth.id}"> <div class="ml-3"> <button th:data-boardId='${board.id}' th:data-replyId='${reply.id}' class="btn btn-danger btn-sm replyDelete">삭제</button> </div> </th:block> </div> </li> </th:block> </ul> </div> <ul class="pagination justify-content-center mt-5" th:if="${pagination.listCnt>0}"> <th:block th:if="${not replyList.first}"> <li class="page-item" ><a class="page-link" th:href="@{&page=1}">≪</a></li> <li class="page-item" ><a class="page-link" th:href="@{'?page='+${pagination.prevPage}}"><</a></li> </th:block> <li class="page-item" th:each="page : ${ #numbers.sequence(pagination.startPage, pagination.endPage) }" th:classappend="${page eq pagination.curPage} ? 'active':'' "> <a class="page-link" th:href="@{'?page=' +${page}}">[[${page}]]</a> </li> <th:block th:if="${not replyList.last}"> <li class="page-item"><a class="page-link" th:href="@{'?page=' + ${pagination.nextPage}}">></a></li> <li class="page-item"><a class="page-link" th:href="@{'?page=' + ${replyList.totalPages}}">≫</a></li> </th:block> </ul> </div> </div> <th:block layout:fragment="script"> <script th:src="@{/js/board.js}"></script> <script> $('.summernote').summernote({ placeholder: '내용을 입력해 주세요.', tabsize: 3, height: 300, }); </script> </th:block> </html>
Pagination
@Data @ToString public class Pagination { /** 한 페이지당 게시글 수 **/ private int pageSize = 10; /** 한 블럭(range)당 페이지 수 **/ private int rangeSize = 10; /** 현재 페이지 **/ private int curPage = 1; /** 현재 블럭(range) **/ private int curRange = 1; /** 총 게시글 수 **/ private int listCnt; /** 총 페이지 수 **/ private int pageCnt; /** 총 블럭(range) 수 **/ private int rangeCnt; /** 시작 페이지 **/ private int startPage = 1; /** 끝 페이지 **/ private int endPage = 1; /** 시작 index **/ private int startIndex = 0; /** 이전 페이지 **/ private int prevPage; /** 다음 페이지 **/ private int nextPage; public Pagination(int listCnt, int curPage, int pageSize , int rangeSize ) { this.pageSize=pageSize; this.rangeSize=rangeSize; /** * 페이징 처리 순서 1. 총 페이지수 2. 총 블럭(range)수 3. range setting */ // 총 게시물 수와 현재 페이지를 Controller로 부터 받아온다. /** 현재페이지 **/ setCurPage(curPage); /** 총 게시물 수 **/ setListCnt(listCnt); /** 1. 총 페이지 수 **/ setPageCnt(listCnt); /** 2. 총 블럭(range)수 **/ setRangeCnt(pageCnt); /** 3. 블럭(range) setting **/ rangeSetting(curPage); } public void setPageCnt(int listCnt) { this.pageCnt = (int) Math.ceil(listCnt * 1.0 / pageSize); } public void setRangeCnt(int pageCnt) { this.rangeCnt = (int) Math.ceil(pageCnt * 1.0 / rangeSize); } public void rangeSetting(int curPage) { setCurRange(curPage); this.startPage = (curRange - 1) * rangeSize + 1; this.endPage = startPage + rangeSize - 1; if (endPage > pageCnt) { this.endPage = pageCnt; } this.prevPage = curPage - 1; this.nextPage = curPage + 1; } public void setCurRange(int curPage) { this.curRange = (int) ((curPage - 1) / rangeSize) + 1; } }
소스 :
https://github.com/braverokmc79/Springboot-JPA-Blog
2번째 예
BoardRepository
import com.godcoder.myhome.model.Board; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; import org.springframework.data.jpa.repository.JpaRepository; import java.util.List; public interface BoardRepository extends JpaRepository<Board, Long> { Page<Board> findByTitleContainingOrContentContaining(String title, String content, Pageable pageable); }
Controller
@GetMapping("/list") public String list(Model model, @RequestParam(value = "page",defaultValue ="1", required = false) Optional<Integer> page, @RequestParam(required = false, defaultValue = "") String searchText ){ // List<Board> boards= boardRepository.findAll(Sort.by(Sort.Direction.DESC, "id")); int pageSize=3; Sort sort1=Sort.by("id").descending(); Pageable pageable=PageRequest.of(page.isPresent() ? page.get()-1 :0, pageSize, sort1); //Page<Board> boards= boardRepository.findAll(pageable); Page<Board> boards= boardRepository.findByTitleContainingOrContentContaining(searchText, searchText,pageable); int startPage=Math.max(1, boards.getPageable().getPageNumber() - 4); int endPage=Math.min(boards.getTotalPages(), boards.getPageable().getPageNumber()+4); model.addAttribute("startPage", startPage); model.addAttribute("endPage", endPage); model.addAttribute("num", boards.getTotalElements()- ((page.get()-1)*pageSize )); model.addAttribute("boards" , boards); return "board/list"; }
html
<main role="main" class="container"> <div class="starter-template"> <h1>게시판</h1> </div> <div>총 건수 : <span th:text="${boards.getTotalElements}"></span></div> <form class="form-inline d-flex justify-content-end"> <div class="form-group mx-sm-3 mb-2"> <label for="searchText" class="sr-only">검색</label> <input type="search" class="form-control" id="searchText" name="searchText" th:value="${param.searchText}"> </div> <button type="submit" class="btn btn-light mb-2">검색</button> </form> <table class="table table-striped"> <thead> <tr> <th scope="col">번호</th> <th scope="col">제목</th> <th scope="col">내용</th> </tr> </thead> <tbody> <tr th:each="board , status:${boards}" > <th th:text="${num - status.index}">아이디</th> <td> <a th:href="@{/board/form(id=${board.id})}" th:text="${board.title}"> </a> </td> <td th:text="${board.content}">Otto</td> </tr> </tbody> </table> <nav aria-label="Page navigation example"> <ul class="pagination justify-content-center"> <li class="page-item" th:classappend="${1 == boards.pageable.pageNumber+1} ?'disabled':''" > <a class="page-link" th:href="@{/board/list(page=${boards.pageable.pageNumber}, searchText=${param.searchText} ) }">Previous</a> </li> <li class="page-item" th:classappend="${i == boards.pageable.pageNumber+1} ?'disabled':''" th:each="i : ${#numbers.sequence(startPage, endPage)}" > <a class="page-link" th:href="@{/board/list(page=${i} , searchText=${param.searchText} ) }" th:text="${i}">1</a> </li> <li class="page-item" th:classappend="${boards.totalPages == boards.pageable.pageNumber+1} ?'disabled':''" > <a class="page-link" th:href="@{/board/list(page=${boards.pageable.pageNumber + 2} , searchText=${param.searchText} ) }" >Next</a> </li> </ul> </nav> <div class="text-right"> <a type="button" class="btn btn-primary" th:href="@{/board/form}" >쓰기</a> </div> </main><!-- /.container -->
소스 :https://github.com/braverokmc79/spring-boot-jpa-web-release
댓글 ( 5)
댓글 남기기