JSP 페이징 번호 - JSP peijing beonho

category JSP-HTML-CSS/SOURCECODE 2019. 10. 26. 17:06 by I's

//페이지 글번호 따로 처리하려고 쿼리 수정하는 것보다 //화면에서 직접 처리 하는 것이 더 나을때도 있다 <c:forEach var="...." items="${....}" varStatus="i"> ${전체게시글수 - (현재페이지-1)*페이지당 보여지는 게시물수 - i.index} </c:forEach>

'JSP-HTML-CSS > SOURCECODE' 카테고리의 다른 글

크롬 자동완성 로직이해 & 처리 꼼수  (0)[JSTL] eq, ne, lt, gt, le, ge 문법  (0)[HTML] 이미지 겹치기  (0)
2021.10.26
2019.10.27
2019.10.26

tag foreach, JSP, jstl, Paging, varstatus

댓글 0 , 엮인글

댓글을 달아 주세요

댓글을 남겨주세요

이름 NICK*

비밀번호*

홈페이지

공개 비공개

    이번에는 JSP 환경에서 페이징 을 알아 봅시다.

    페이징

    페이징은 아래와 같이, 게시판의 글이 많으면 나눠서 보여주는 것을 말하는 데요

    ※ 페이징을 구현하기 전에, 글의 개수를 늘렸습니다.

    페이징의 특성

    1. 반드시 GET 방식으로만 처리한다

    2. 이동할 때 페이지 번호, 보여줄 페이지 개수 를 가지고 다녀야 한다 -> 목록 으로 나올 때 현재 페이지를 유지하기 위해

    3. 페이징 처리하는 로직을 클래스로 분류한다 -> PageVO클래스는 페에징 관련 모든 페이지를 계산한다

    먼저, 페이징을 구현하기 위해서는 각각의 페이지에서 몇개의 게시판 목록을 보여줄지 에 대한 메서드를 먼저 구현해야 합니다.

    페이징 구현

    그러기 위해서는 게시판의 특성을 잘 생각해 봅시다.

    게시판은 최신글이 위에 나타나는 특성을 가지고 있습니다. ( 내림차순 )

    각각의 페이지에서는 보여지는 글 목록 ( 글번호 ) 가 다릅니다.

    그러면, sql 문을 생각 해 봅시다.

    어떠한 기준으로 내림차순을 한 후 번호를 매겨서 원하는 번호만 가져오는 방법. ROWNUM 을 이용하면 되겠죠?

    위의 쿼리문 처럼  3중 쿼리문을 작성해주면 됩니다.

    그리고 WHERE 조건에 있는 숫자를 조정하면 되겠죠?

    물음표에 들어가는 숫자에 따라서 화면에서 보여지는 각각의 페이지 마다 글개수 가 달라지겠습니다.

    그러면, 물음표에 들어가는 숫자를 어떻게 넣어주면 될까요?

    예를 들어서 1 페이지 마다 10개씩 보여진다고 생각을 해보면,

    1 페이지 = 1 ~ 10   -> rn > 0 and rn <= 10

    2 페이지 = 11 ~ 20  -> rn > 10 and rn <= 20

    3 페이지 = 21 ~ 30   -> rn > 20 and rn <= 30

    이런 식으로 나오겠죠?

    첫번째 물음표 = (현재 페이지 - 1) * 보여줄 게시글 개수

    두번째 물음표 = 현재 페이지 * 보여줄 게시글 개수

    가 되겠네요

    그러면 pageNum(페이지 번호) 와 amount(보여줄 게시글 수) 를 매개변수로 받아서 뿌려주면 되겠습니다.

    public List<BoardVO> getList(int pageNum, int amount){ List<BoardVO> list = new ArrayList<>(); String sql = "select * " + "from (select rownum rn," + " a.* " + "from (select *" + " from board order by bno desc) a ) " + "where rn > ? and rn <= ?"; try { conn = ds.getConnection(); // 연결 pstmt = conn.prepareStatement(sql); // sql준비 pstmt.setInt(1, (pageNum - 1) * amount); pstmt.setInt(2, pageNum * amount); rs = pstmt.executeQuery(); // sql문 실행 while(rs.next()) { // 한바퀴 회전당 VO를 하나씩 생성 BoardVO vo = new BoardVO(); vo.setBno(rs.getInt("bno")); vo.setWriter(rs.getString("writer")); vo.setTitle(rs.getString("title")); vo.setContent(rs.getString("content")); vo.setRegdate(rs.getTimestamp("regdate")); // 날짜형은 Timestamp() or Date() vo.setHit(rs.getInt("hit")); list.add(vo); } } catch (SQLException e) { e.printStackTrace(); } finally { JdbcUtil.close(conn, pstmt, rs); } return list; }

    자 이제, 원하는 개수만큼 잘라서 화면에 나타내 주었습니다.

    그러면, 페이지를 구분 지을 수 있도록 해주어야 겠죠? ( PageVO 라는 클래스를 만듭니다. )

    페이지를 나타낼 때 필요한 변수들을 생각해 봅시다.

    먼저, 화면에 보여질 시작 페이지번호 와 끝 페이지 번호. 이전 , 다음 여부.

    현재 조회하는 페이지번호 , 화면에 보여질 게시글 수 , 총 게시글 수 가 필요합니다.

    그리고 계산이 좀 필요한데요.

    pageNum, amout, total 은 매개변수로 넘겨 받아서 저장을 해주면 됩니다.

    하지만, startPage , endPage, prev , next 는 계산을 해주어야 하죠.

    1. endPage

    ex) 조회하는 페이지 1 -> 끝번호 10
    ex) 조회하는 페이지 9 -> 끝번호 10
    ex) 조회하는 페이지 11 -> 끝번호 20

    공식 = (int)Math.ceil(페이지번호 / 페이지네이션개수) * 페이지네이션개수

    2. startPage

    공식 = 끝페이지 - 페이지네이션개수 + 1

    3. realEnd(진짜 끝번호) 구해서 endPage의 값을 다시 결정

    ex) 만약 게시글이 52개라면 -> 진짜 끝번호 6
    ex) 만약 게시글이 105개라면 -> 진짜 끝번호 11

    공식 = (int)Math.ceil( 전체게시글 수 / 화면에 보여질 게시글 수 )

    마지막페이지 도달했을 때 보여져야 하는 끝번호가 달라집니다.
    ex) 131개 게시물
    1번 페이지 클릭시 -> endPage = 10, realEnd = 14 ( endPage로 세팅 )
    11번 페이지 클릭시 -> endPage = 20, realEnd = 14 ( realEnd로 세팅 )

    4. prev 결정 ( 이전 글이 있을 경우에만 활성화 )

    5. next 결정 ( 다음 글이 있을 경우에만 활성화 )

    ex) 131개 게시물
    1~10 클릭시 endPage = 10, realEnd = 14 -> 다음버튼 true
    11 클릭시 endPage = 14 , realEnd = 14 -> 다음버튼 false

    그리고 데이터들이 private 처리 되어 있기 때문에, setter 와 getter 를 만들어 줍니다.

    PageVO

    public class PageVO { /* * 화면에 그려질 pageNation을 계산하는 클래스 ( pageNum, amount값을 가지고 다님 ) */ private int startPage; // 게시글 화면에 보여질 첫번째 번호 private int endPage; // 게시글 화면에 보여질 마지막 번호 private boolean prev, next; // 이전버튼, 다음버튼 활성화여부 private int pageNum; // 현재 조회하는 페이지번호 private int amount = 10; // 화면에 그려질 데이터 private int total; // 전체게시글 수 // 생성자에서는 객체가 생성될때 계산을 처리 public PageVO(int pageNum, int amount, int total) { this.pageNum = pageNum; this.amount = amount; this.total = total; // 1. endPage결정 // ex) 조회하는 페이지 1 -> 끝번호 10 // ex) 조회하는 페이지 9 -> 끝번호 10 // ex) 조회하는 페이지 11 -> 끝번호 20 // 공식 = (int)Math.ceil(페이지번호 / 페이지네이션개수) * 페이지네이션개수 this.endPage = (int)Math.ceil(this.pageNum * 0.1) * 10; // 2. startPage결정 // 공식 = 끝페이지 - 페이지네이션개수 + 1 this.startPage = this.endPage - 10 + 1; // 3. realEnd(진짜 끝번호) 구해서 endPage의 값을 다시 결정 // 만약 게시글이 52개라면 -> 진짜 끝번호 6 // 만약 게시글이 105개라면 -> 진짜 끝번호 11 // 공식 = (int)Math.ceil(전체게시글수 / 화면에보여질데이터개수) int realEnd = (int)Math.ceil(this.total / (double)this.amount); // 마지막페이지 도달했을 때 보여져야 하는 끝번호가 달라집니다. // ex) 131개 게시물 // 1번 페이지 클릭시 -> endPage = 10, realEnd = 14 ( endPage로 세팅 ) // 11번 페이지 클릭시 -> endPage = 20, realEnd = 14 ( realEnd로 세팅 ) if(this.endPage > realEnd) { this.endPage = realEnd; } // 4. prev결정 ( startPage의 번호는 1, 11, 21... ) this.prev = this.startPage > 1; // 5. next결정 // ex: 131개 게시물 // 1~10 클릭시 endPage = 10, realEnd = 14 -> 다음버튼 true // 11 클릭시 endPage = 14 , realEnd = 14 -> 다음버튼 false this.next = this.endPage < realEnd; // 확인 System.out.println("시작페이지:" + this.startPage + ", 끝페이지:" + this.endPage); // GetListService에서 페이지VO 계산처리 코드작성... }

    만들어진 PageVO 를 보면, 전체 게시글 수가 필요하기 때문에, DAO 에 전체 게시글 수를 구하는 메서드를 구합니다.

    // 전체 게시글 수 public int getTotal() { int result = 0; String sql = "select count(*) as total from board"; try { conn = ds.getConnection(); pstmt = conn.prepareStatement(sql); rs = pstmt.executeQuery(); if(rs.next()) { result = rs.getInt("total"); } } catch (SQLException e) { e.printStackTrace(); } finally { JdbcUtil.close(conn, pstmt, rs); } return result; }

    이제 페이징을 구현하기 위한, 모든 준비는 끝이 났습니다.

    list.board 로 넘어갈 때, 처리를 해주어야 겠죠?

    파일명 : GetListServiceImpl.java

    public class GetListServiceImpl implements IBoardService{ @Override public void execute(HttpServletRequest request, HttpServletResponse response) { // 1. 화면전환 시에 조회하는 페이지번호 and 화면에 그려질 데이터개수 2개를 전달받음 // 첫 페이지 경우 int pageNum = 1; int amount = 10; // 페이지번호를 클릭하는 경우 if(request.getParameter("pageNum") != null && request.getParameter("amount") != null) { pageNum = Integer.parseInt(request.getParameter("pageNum")); amount = Integer.parseInt(request.getParameter("amount")); } // DAO생성 BoardDAO dao = BoardDAO.getInstance(); // 2. pageVO생성 List<BoardVO> list = dao.getList(pageNum, amount); int total = dao.getTotal(); // 전체게시글수 PageVO pageVO = new PageVO(pageNum, amount, total); // 3. 페이지네이션을 화면에 전달 request.setAttribute("pageVO", pageVO); // 화면에 가지고 나갈 list를 request에 저장 !! request.setAttribute("list", list); } }

    위의 코드를 보면 알겠지만, pageNum 과 amount 는 클릭했을 때 그 값이 넘겨져 와야 합니다.

    위의 <a> 태그를 보면 pageNum 과 amount 를 get 방식으로 넘겨주고 있습니다.

    이전 버튼과 다음 버튼도 조건에 따라 활성화 밑 구현 시켜 주어야 겠죠?

    이렇게, 페이징에 대해서 알아 보았습니다.

    고생하셨습니다.

    ※ 아래는 해당하는 게시판 목록 화면의 .jsp 파일 입니다.

    <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <%@ taglib uri="//java.sun.com/jsp/jstl/core" prefix="c" %> <%@ taglib uri="//java.sun.com/jsp/jstl/fmt" prefix="fmt" %> <%@ include file="../include/header.jsp" %> <style> .btn { border: 0; border-radius: 0; /*윤곽 0*/ padding: 5px 10px; margin: 20px 0px; } </style> <div class="container"> <h3>My Web게시판</h3> <div> <select onchange="change(this)"> <option value="10" ${pageVO.amount eq 10 ? 'selected' : '' }>10개씩 보기</option> <option value="20" ${pageVO.amount eq 20 ? 'selected' : '' }>20개씩 보기</option> <option value="50" ${pageVO.amount eq 50 ? 'selected' : '' }>50개씩 보기</option> <option value="100" ${pageVO.amount eq 100 ? 'selected' : '' }>100개씩 보기</option> </select> </div> <table class="table table-bordered"> <thead> <tr> <th>글 번호</th> <th>작성자</th> <th>제목</th> <th>날짜</th> <th>조회수</th> </tr> </thead> <tbody> <c:forEach var="vo" items="${list }"> <tr> <td>${vo.bno }</td> <td>${vo.writer}</td> <td><a href="getContent.board?bno=${vo.bno }">${vo.title }</a></td> <td><fmt:formatDate value="${vo.regdate }" pattern="yyyy년 MM월dd일 HH시 mm분 ss초" /></td> <td>${vo.hit }</td> </tr> </c:forEach> </tbody> <tbody> <tr> <td colspan="5" align="center"> <ul class="pagination pagination-sm"> <!-- 2. 이전버튼 활성화 여부 --> <c:if test="${pageVO.prev }"> <li><a href="list.board?pageNum=${pageVO.startPage - 1 }&amount=${pageVO.amount}">이전</a></li> </c:if> <!-- 1. 페이지번호 처리 --> <c:forEach var="num" begin="${pageVO.startPage }" end="${pageVO.endPage }"> <li class="${pageVO.pageNum eq num ? 'active' : '' }"> <a href="list.board?pageNum=${num }&amount=${pageVO.amount}">${num }</a></li> </c:forEach> <!-- 3. 다음버튼 활성화 여부 --> <c:if test="${pageVO.next }"> <li><a href="list.board?pageNum=${pageVO.endPage + 1 }&amount=${pageVO.amount}">다음</a></li> </c:if> </ul> <input type="button" value="글 작성" class="btn btn-default pull-right" title="location.href='write.board'"> </td> </tr> </tbody> </table> </div> <%@ include file="../include/footer.jsp" %> <script> function change(a){ //console.log(a); //console.log(a.value); location.href="list.board?pageNum=1&amount=" + a.value; } </script>

    Toplist

    최신 우편물

    태그