[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" %>




설명은 주석을 참고하시면 됩니다!


한 번 접속해볼까요??


image




image




페이징 처리가 제대로 됐음을 알 수 있습니다!