2019. 10. 3. 13:45ㆍProject B (SPMS)/Project B 파트3
페이징 화면 처리 단계 과정
- 브라우저 주소창에 페이지 번호를 전달해서 결과를 확인하는 단계
- JSP에서 페이지 번호를 출력하는 단계
- 각 페이지 번호에 클릭 이벤트 처리
- 전체 데이터 개수를 반영해서 페이지 번호 조절
목록 페이지에서 조회/수정/삭제 페이지 페이지 번호가 계속해서 유지되어야만 하기때문에 신경써야 하는 부분이 많다.
페이징 처리 시 필요 정보들
현재 페이지 번호
이전 (prev) 과 다음 (next) 으로 이동 가능한 링크 표시 여부
화면에서 보여지는 페이지의 시작번호 (startPage) 와 끝번호 (endPage)
페이징 처리 클래스 설계
src/main/java
com.spms.domain
PageDTO.java
package com.spms.domain;
import lombok.Getter;
import lombok.ToString;
@Getter
@ToString
public class PageDTO {
private int startPage;
private int endPage;
private boolean prev, next;
private int total;
private Criteria cri;
public PageDTO(Criteria cri, int total) {
this.cri = cri;
this.total = total;
this.endPage = (int) (Math.ceil(cri.getPageNum() / 10.0)) * 10;
this.startPage = this.endPage - 9;
int realEnd = (int) (Math.ceil((total * 1.0) / cri.getAmount()));
if (realEnd <= this.endPage) {
this.endPage = realEnd;
}
this.prev = this.startPage > 1;
this.next = this.endPage < realEnd;
}
}
Criteria 와 전체 데이터 수를 파라미터로 지정한다.
Criteria 내부에는 페이지에서 보여주는 데이터 수와 현재 페이지 번호를 갖고있기때문에 이를 이용해서 모든 내용을 계산할 수 있다.
페이징의 끝 번호 계산
this.endPage = (int) (Math.ceil(cri.getPageNum() / 10.0)) * 10;
페이지 계산 시 끝 번호부터 먼저 계산하는게 수월하다.
페이지 번호는 10개씩 표시
Math.ceil()
소수점을 올림으로 처리한다.
- 1페이지의 경우 : Math.ceil(0.1) * 10 = 10
- 10페이지의 경우 : Math.ceil(0.1) * 10 = 10
- 11페이지의 경우 : Math.ceil(0.1) * 10 = 20
만약 전체 데이터 수가 적으면, 10페이지로 끝나면 안되는 상황이 생길 수도 있기때문에
마지막 번호를 먼저 계산하는 이유는 시작 번호를 계산하기 수월하기 때문이다.
만일 화면에 10개씩 보여준다면 시작 번호는 무조건 끝 번호에서 9라는 값을 뺀 값이 된다.
페이징의 시작 번호 계산
this.startPage = this.endPage - 9;
레코드 전체 건수에 의한 마지막 페이지 재계산
int realEnd = (int) (Math.ceil((total * 1.0) / cri.getAmount()));
if (realEnd <= this.endPage) {
this.endPage = realEnd;
}
끝 번호는 전체 데이터 건수에 의해 영향을 받는다.
예를 들어 10개씩 보여주는 경우 전체 데이터 수가 80개라고 가정하면 끝 번호는 10이 아닌 8 이 되어야만 한다.
만약 끝 번호와 한 페이지당 출력되는 데이터 수의 곱이 전체 데이터 수보다 크면 끝 번호는 다시 total을 이용해서 다시 계산되어야 한다.
먼저 전체 데이터 수를 이용해서 진짜 끝 페이지가 몇 번까지 되는지 계산한다.
만약 진짜 끝 페이지가 구해놓은 끝 번호보다 작으면 끝 번호는 작은 값이 되어야만 한다.
이전 계산
this.prev = this.startPage > 1;
시작 번호가 1보다 큰 경우이면 존재
다음 계산
this.next = this.endPage < realEnd;
realEnd가 끝 번호보다 큰 경우이면 존재
게시판 컨트롤러 수정
src/main/java
com.spms.controller
BoardController.java
@GetMapping list()
package com.spms.controller;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;
import com.spms.domain.BoardVO;
import com.spms.domain.Criteria;
import com.spms.domain.PageDTO;
import com.spms.service.BoardService;
import lombok.AllArgsConstructor;
import lombok.extern.log4j.Log4j;
@Controller
@Log4j
@RequestMapping("/board/*")
@AllArgsConstructor
public class BoardController {
private BoardService boardService;
@GetMapping("/list")
public void list(Criteria cri, Model model) {
log.info("list" + cri);
boardService.getList(cri).forEach(board -> log.info(board));
model.addAttribute("list", boardService.getList(cri));
model.addAttribute("pageMaker", new PageDTO(cri, 111));
}
@GetMapping("/register")
public void register() {
}
@PostMapping("/register")
public String register(BoardVO board, RedirectAttributes rttr) {
log.info("register : " + board);
boardService.register(board);
rttr.addFlashAttribute("result", board.getBno());
return "redirect:/board/list";
}
@GetMapping({"/get", "/modify"})
public void get(@RequestParam("bno") Long bno, Model model) {
log.info("/get or modify");
model.addAttribute("board", boardService.get(bno));
}
@PostMapping("/modify")
public String modify(BoardVO board, RedirectAttributes rttr) {
log.info("modify:" + board);
if (boardService.modify(board)) {
rttr.addFlashAttribute("result", "success");
}
return "redirect:/board/list";
}
@PostMapping("/remove")
public String remove(@RequestParam("bno") Long bno, RedirectAttributes rttr) {
log.info("remove..." + bno);
if (boardService.remove(bno)) {
rttr.addFlashAttribute("result", "success");
}
return "redirect:/board/list";
}
}
JSP에서의 페이지네이션 (페이지 번호 출력)
views/board
list.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"%>
<%@ include file="../includes/header.jsp"%>
<div class="row">
<div class="col-lg-12">
<h1 class="page-header">게시판 목록</h1>
</div>
<!-- /.col-lg-12 -->
</div>
<!-- /.row -->
<div class="row">
<div class="col-lg-12">
<div class="panel panel-default">
<div class="panel-heading">게시글 목록 페이지<button id='regBtn' type="button" class="btn btn-xs pull-right btn-primary">게시글 등록</button></div>
<!-- /.panel-heading -->
<div class="panel-body">
<table class="table table-striped table-bordered table-hover">
<tbody>
<c:forEach items="${list }" var="board">
<tr>
<td>
<font color="Gray">
<c:out value="${board.bno}"/> /
<c:out value="${board.writer}"/> /
<fmt:formatDate value="${board.regdate}" pattern="yyyy-MM-dd"/> /
<fmt:formatDate value="${board.updateDate}" pattern="yyyy-MM-dd"/>
</font><br />
<font size="3px">
<a href="/board/get?bno=<c:out value="${board.bno}"/>"><c:out value="${board.title}"></c:out></a>
</font>
</td>
</tr>
</c:forEach>
</tbody>
</table>
<!-- 페이지네이션 시작 -->
<div class='pull-right'>
<ul class="pagination">
<!-- 이전 -->
<c:if test="${pageMaker.prev}">
<li class="paginate_button previous"><a
href="${pageMaker.startPage -1}">Previous</a></li>
</c:if>
<!-- 현재 -->
<c:forEach var="num" begin="${pageMaker.startPage}" end="${pageMaker.endPage}">
<li class='paginate_button ${pageMaker.cri.pageNum == num ? "active":""} '>
<a href="${num}">${num}</a>
</li>
</c:forEach>
<!-- 다음 -->
<c:if test="${pageMaker.next}">
<li class="paginate_button next"><a
href="${pageMaker.endPage +1 }">Next</a></li>
</c:if>
</ul>
</div>
<!-- 페이지네이션 끝 -->
<!-- 이전 현재 다음 버튼의 a 태그동작을 막기위한 폼 태그 -->
<form id='actionForm' action="/board/list" method='get'>
<input type='hidden' name='pageNum' value='${pageMaker.cri.pageNum}'>
<input type='hidden' name='amount' value='${pageMaker.cri.amount}'>
</form>
<!-- 폼 태그 종료 -->
<!-- Modal 추가 -->
<div class="modal fade" id="myModal" tabindex="-1" role="dialog"
aria-labelledby="myModalLabel" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
<h4 class="modal-title" id="myModalLabel">게시글 처리 결과</h4>
</div>
<div class="modal-body">처리가 완료되었습니다.</div>
<div class="modal-footer">
<button type="button" class="btn btn-default"
data-dismiss="modal">Close</button>
<button type="button" class="btn btn-primary">Save changes</button>
</div>
</div>
<!-- /.modal-content -->
</div>
<!-- /.modal-dialog -->
</div>
<!-- /.panel-body -->
</div>
<!-- /.panel -->
</div>
<!-- /.col-lg-12 -->
</div>
<!-- /.row -->
</div>
<!-- /#page-wrapper -->
<%@ include file="../includes/footer.jsp"%>
<script type="text/javascript">
$().ready(function() {
var result = '<c:out value="${result}"/>';
checkModal(result);
history.replaceState({}, null, null);
function checkModal(result) {
if (result === '' || history.state) {
return;
}
if (parseInt(result) > 0) {
$(".modal-body").html(
"게시글 " + parseInt(result) + " 번이 등록되었습니다."
);
}
$("#myModal").modal("show");
}
$("#regBtn").on("click", function() {
self.location = "/board/register";
});
var actionForm = $("#actionForm");
$(".paginate_button a").on("click", function(e) {
e.preventDefault();
console.log('click');
actionForm.find("input[name='pageNum']").val($(this).attr("href"));
actionForm.submit();
});
});
</script>
페이지네이션 코드를 작성
테이블 종료 태그 밑에 작성하고, 페이지네이션 구성은 부트스트랩 예제를 보면서 기본 페이지네이션 샘플 소스를 가지고 활용한다.
PageDTO를 사용할 수 있도록 모델에 담아서 화면에 전달한다.
PageDTO 를 구성하기 위해 전체 데이터 건수가 필요한데, 일단, 임의의 값으로 대충 111 건을 지정한다.
자바단에서 만들어놓은 모델 pageMaker 를 가지고 화면에 페이지 번호들을 출력한다.
a 태그의 직접 링크 처리 방식의 경우 검색 조건이 붙고 난 후의 처리가 복잡하게 되므로 자바스크립트를 통해 처리하는 방식을 이용한다.
페이지와 관련된 a 태그의 href 속성값으로 페이지 번호를 갖도록 수정한다.
액션 폼 폼태그를 추가해서 a 태그가 원래의 동작을 못하도록 자바스크립트를 처리하고, URL 의 이동을 처리하도록 변경한다.
자바스크립트에서는 a 태그를 클릭해도 페이지 이동이 없도록 preventDefault() 처리로 막고, 폼 태그 내의 pageNum 값은 href 속성값으로 변경 후 마지막으로 submit() 한다.
페이지네이션이 적용된 게시판 목록 페이지
'Project B (SPMS) > Project B 파트3' 카테고리의 다른 글
[B -2-23] 페이징 화면 처리 4 (0) | 2019.10.03 |
---|---|
[B -2-22] 페이징 화면 처리 3 (0) | 2019.10.03 |
[B -2-21] 페이징 화면 처리 2 (0) | 2019.10.03 |
[B -2-19] 마이바티스와 스프링에서의 페이징 처리 (0) | 2019.10.03 |