[Spring] 22.SpringProject-페이징 처리(4)
페이징 처리 - 컨트롤러, 프리젠테이션 계층
저번 장까지 페이징 처리를 위해 해왔던 작업을 정리하면 다음과 같습니다.
- boardMapper 수정(현재 페이지에 해당하는 게시물을 조회하는 쿼리와 전체 게시물 수 구하는 쿼리 작성)
- Criteria 생성(page와 perPageNum 를 속성으로 가짐)
- BoardService, BoardDAO 수정 (쿼리 실행해서 데이터 가져오는 것까지 셋팅)
- PageMaker 생성(listPage.jsp에서 페이지 번호를 출력하기 위한 클래스)
- PageMaker, Criteria에 makeQuery 추가(URI 생성)
아직까지 눈에 확확 보이는 작업이 아니여서 어렵고 지루하게 느껴질 수도 있는데요ㅜㅜ
드디어 컨트롤러와 프리젠테이션 계층을 구현해보겠습니다~!
- BoardController에 페이징 기능을 하는 listPage 메소드 추가 (컨트롤러)
- listPage.jsp 생성 (프리젠테이션 계층)
BoardController 수정
BoardController에 페이지 기능을 수행하는 listPage 메소드를 다음과 같이 추가하겠습니다!
package com.gguri.swp.controller;
...
@Controller
@RequestMapping("/board/*")
public class BoardController {
private static final Logger logger = LoggerFactory.getLogger(BoardController.class);
@Inject
private BoardService service;
...
@RequestMapping(value = "/listPage", method = RequestMethod.GET)
public void listPage(Criteria cri, Model model) throws Exception{
logger.info("listPage");
//현재 페이지에 해당하는 게시물을 조회해 옴
List<BoardVO> boards = service.listPage(cri);
//모델에 추가
model.addAttribute("list",boards);
//PageMaker 객체 생성
PageMaker pageMaker = new PageMaker(cri);
//전체 게시물 수를 구함
int totalCount = service.getTotalCount(cri);
//pageMaker로 전달 -> pageMaker는 startPage, endPage, prev, next를 계산함
pageMaker.setTotalCount(totalCount);
//모델에 추가
model.addAttribute("pageMaker", pageMaker);
}
}
구체적인 설명은 주석을 참고 하시면 되구요!
listPage 메소드에 의해 현재 페이지에 해당하는 게시물과 PageMaker가 모델에 담겨서 listPage.jsp로 전달됩니다!
listPage.jsp 작성
다음과 같이 listPage.jsp를 작성해줍니다!
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt" %>
<%@ page session="false" %>
<%@include file="../include/header.jsp" %>
<div id="registerOK" class="alert alert-info hidden" role="alert">새 글이 등록되었습니다.</div>
<div id="removeOK" class="alert alert-danger hidden" role="alert">글이 삭제되었습니다.</div>
<div class="row">
<div class="col-md-11"></div>
<div class="col-md-1 text-right">
<!-- perPageNum의 값을 정하는 select 박스 -->
<select class="form-control" id="perPageSel">
<option value="10">10</option>
<option value="15">15</option>
<option value="20">20</option>
</select>
</div>
</div>
<!-- 데이터 출력 -->
<table class="table table-bordered">
<tr>
<th style="width: 10px">BNO</th>
<th>TITLE</th>
<th>WRITER</th>
<th>REGDATE</th>
<th style="width: 40px">VIEWCNT</th>
</tr>
<c:forEach items="${list}" var="boardVO">
<tr>
<td>${ boardVO.bno }</td>
<!-- PageMaker의 makeQuery 메소드 이용해서 URI 생성 -->
<td><a href="/board/read${pageMaker.makeQuery(pageMaker.cri.page)}&bno=${boardVO.bno}">${boardVO.title}</a></td>
<td>${ boardVO.writer}</td>
<td><fmt:formatDate pattern="YYYY-MM-dd HH:mm:ss" value="${ boardVO.regdate}"/></td>
<td>${ boardVO.viewcnt}</td>
</tr>
</c:forEach>
</table>
<!-- 등록, dummy 버튼 -->
<div>
<a href="/board/register"><button class="btn btn-primary">새글등록</button></a>
<a href="/board/dummy"><button class="btn btn-danger">dummy생성</button></a>
</div>
<!-- 페이지 번호 -->
<div class="text-center">
<nav aria-label="pagination">
<ul class="pagination">
<!-- prev 버튼 -->
<li id="page-prev">
<a href="listPage${pageMaker.makeQuery(pageMaker.startPage-1)}" aria-label="Prev">
<span aria-hidden="true">«</span>
</a>
</li>
<!-- 페이지 번호 (시작 페이지 번호부터 끝 페이지 번호까지) -->
<c:forEach begin="${pageMaker.startPage}" end="${pageMaker.endPage}" var="idx">
<li id="page${idx}">
<a href="listPage${pageMaker.makeQuery(idx)}">
<!-- 시각 장애인을 위한 추가 -->
<span>${idx}<span class="sr-only">(current)</span></span>
</a>
</li>
</c:forEach>
<!-- next 버튼 -->
<li id="page-next">
<a href="listPage${pageMaker.makeQuery(pageMaker.endPage + 1)}" aria-label="Next">
<span aria-hidden="true">»</span>
</a>
</li>
</ul>
</nav>
</div>
<script>
$(function(){
//perPageNum select 박스 설정
setPerPageNumSelect();
//등록, 삭제 후 문구 처리
var result = '${result}';
$(function(){
if(result === 'registerOK'){
$('#registerOK').removeClass('hidden');
$('#registerOK').fadeOut(2000);
}
if(result === 'removeOK'){
$('#removeOK').removeClass('hidden');
$('#removeOK').fadeOut(2000);
}
})
//prev 버튼 활성화, 비활성화 처리
var canPrev = '${pageMaker.prev}';
if(canPrev !== 'true'){
$('#page-prev').addClass('disabled');
}
//next 버튼 활성화, 비활성화 처리
var canNext = '${pageMaker.next}';
if(canNext !== 'true'){
$('#page-next').addClass('disabled');
}
//현재 페이지 파란색으로 활성화
var thisPage = '${pageMaker.cri.page}';
//매번 refresh 되므로 다른 페이지 removeClass 할 필요는 없음->Ajax 이용시엔 해야함
$('#page'+thisPage).addClass('active');
})
function setPerPageNumSelect(){
var perPageNum = "${pageMaker.cri.perPageNum}";
var $perPageSel = $('#perPageSel');
var thisPage = '${pageMaker.cri.page}';
$perPageSel.val(perPageNum).prop("selected",true);
//PerPageNum가 바뀌면 링크 이동
$perPageSel.on('change',function(){
//pageMarker.makeQuery 사용 못하는 이유: makeQuery는 page만을 매개변수로 받기에 변경된 perPageNum을 반영못함
window.location.href = "listPage?page="+thisPage+"&perPageNum="+$perPageSel.val();
})
}
</script>
<%@include file="../include/footer.jsp" %>
설명은 주석을 참고하시면 됩니다!
한 번 접속해볼까요??