본문 바로가기

Study

[JSP] 게시판 만들기 - 게시글 목록 조회 + 페이징 처리


 

BoardListController

/**
 * Servlet implementation class BoardListController
 */
@WebServlet("/list.bo")
public class BoardListController extends HttpServlet {
	private static final long serialVersionUID = 1L;
       
    /**
     * @see HttpServlet#HttpServlet()
     */
    public BoardListController() {
        super();
        // TODO Auto-generated constructor stub
    }

	/**
	 * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
	 */
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		// --------------- 페이징 처리 ---------------
		
		int listCount;		// 현재 총 게시글 개수
		int currentPage;	// 현재 페이지 (즉, 사용자가 요청한 페이지)
		int pageLimit;		// 페이지 하단에 보여질 페이징바의 페이지 최대 개수 (몇개 단위씩 배치) 1 2 3 4 ....
		int boardLimit;		// 한 페이지 내에 보여질 게시글 최대 개수 (몇개 단위씩)
		
		// 몇 번 페이지(currentPage)를 요청했냐에 따라서 시작 숫자, 끝 숫자 달라짐
		// 4번 선택시 1~10 | 12번 선택시 11~20
		
		// 위의 4개의 변수를 가지고 아래 3개의 값을 구해낼거임		
		int maxPage;		// 가장 마지막 페이지 (총 페이지 수)
		int startPage;		// 페이징바의 시작 수 (현재 페이지 페이징바의 시작 수)
		int endPage;		// 페이징바의 끝 수 (현재 페이지 페이징바의 마지막 수)
		
		// * listCount : 총 게시글 개수
		listCount = new BoardService().selectListCount();
		
		// * curretPage : 현재 페이지 (즉, 사용자가 요청한 페이지)
		currentPage = Integer.parseInt(request.getParameter("cpage"));
		
		// * pageLimit : 페이징바의 페이지 최대 개수 (단위)
		pageLimit = 10; // 10개씩 보여줄 거임
		
		// * boardLimit : 게시글 최대 개수 (단위)
		boardLimit = 10; // 10개
		
		/*
		 *  * maxPage : 제일 마지막 페이지 수 (총 페이지 수)
		 *  
		 *  listCount, boardLimit의 영향을 받음
		 *  
		 *  ** 더블로 바꾸고 나누고 올림 처리
		 *  listCount를 더블형으로 바꿔준다
		 *  listCount를 boardLimit로 나누고 올림 처리해주면 그게 maxPage가 됨
		 *  
		 *  ex) 게시글이 10개 단위씩 보여진다는 가정하에
		 *  listCount	boardLimit			maxPage
		 *   100.0			10 => 10.0			10
		 *   101.0			10 => 10.1			11	
		 *   105.0			10 => 10.5			11	
		 *   110.0			10 => 11.0			11
		 *  
		 *  ex) 게시글이 5개 단위씩 보여진다는 가정하에
		 *  listCount	boardLimit			maxPage
		 *   10.0			5 => 2.0			2
		 *   11.0			5 => 2.1			3
		 *   14.0			5 => 2.4			3
		 *   
		 *  ** maxPage = 올림처리(총게시글 개수(실수형) / BoardLimit)
		 */
		
		maxPage = (int)Math.ceil((double)listCount / boardLimit);
		
		/*
		 *  * startPage : 페이징바의 시작수
		 *  
		 *  pageLimit, currentPage의 영향을 받음
		 *  
		 *  ex) 페이징바의 목록이 10개 단위씩이라는 가정하에 (pageLimit = 10)
		 *  	startPage : 1, 11, 21, 31, ....
		 *  				=> n * pageLimit + 1
		 *  
		 *  currentPage	startPage
		 *  	1			1		=> 0 * pageLimit + 1	=> n = 0
		 *  	5			1		=> 0 * pageLimit + 1	=> n = 0
		 *  	10			1		=> 0 * pageLimit + 1	=> n = 0
		 *  	11			11		=> 1 * pageLimit + 1	=> n = 1
		 *  	15			11		=> 1 * pageLimit + 1	=> n = 1
		 *  	20			11		=> 1 * pageLimit + 1	=> n = 1
		 *  
		 *  	1~10	=> n = 0
		 *  	11~20	=> n = 1
		 *  	21~30	=> n = 2
		 *  
		 *  currentPage - 1 / pageLimit => n
		 *  	0~9
		 *  	10~19
		 *  	20~29
		 *  
		 *  ** StartPage = 					n			 * pageLimit + 1
		 *  			   (currentPage - 1) / pageLimit * pageLimit + 1
		 */
		
		startPage = (currentPage - 1) / pageLimit * pageLimit + 1;
		
		/*
		 *  * endPage : 페이징바의 끝 수
		 *  
		 *  startPage, pageLimit의 영향을 받음 (단, maxPage에도 영향을 받긴함)
		 *  
		 *  ex) pageLimit이 10이라는 가정하에 (1 2 3 4 5 6 7 8 9 10)
		 *  startPage : 1	=> endPage : 10
		 *  startPage : 11	=> endPage : 20
		 *  startPage : 21	=> endPage : 30
		 */
		
		endPage = startPage + pageLimit - 1;
		
		// startPage가 11이어서 endPage 20으로 됨 (근데 maxPage가 고작 13 밖에 안되면?)
		if (endPage > maxPage) {
			endPage = maxPage;
		}
		
		// 페이징 처리 자주 사용할거기 때문에 객체로 만들어둘거임
		// com.common.model.vo.PageInfo
		// * 페이징바를 만들 때 필요한 객체
		PageInfo pi = new PageInfo(listCount, currentPage, pageLimit, boardLimit, maxPage, startPage, endPage);
		
		// * 현재 요청한 페이지(currentPage)에 보여질 게시글 리스트 boardLimit 수만큼 조회
		ArrayList<Board> list = new BoardService().selectList(pi);
		
		request.setAttribute("pi", pi);
		request.setAttribute("list", list);
		
		request.getRequestDispatcher("views/board/boardListView.jsp").forward(request, response);
	}

	/**
	 * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
	 */
	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		// TODO Auto-generated method stub
		doGet(request, response);
	}

}

 

 

BoardService

// 총 게시글 개수 조회
public int selectListCount() {
    Connection conn = getConnection();

    int listCount = new BoardDao().selectListCount(conn);

    // 그냥 조회만 하기 때문에 트랜젝션 처리(커밋 롤백) 필요 없음

    close(conn);

    return listCount;
}
public ArrayList<Board> selectList(PageInfo pi) {
    Connection conn = getConnection();

    ArrayList<Board> list = new BoardDao().selectList(conn, pi);

    close(conn);

    return list;
}

 

BoardDao

public int selectListCount(Connection conn) {
    // select문 => ResultSet 객체 (한행조회) => int형 변수에 넣기
    int listCount = 0;

    PreparedStatement pstmt = null;
    ResultSet rset = null;

    String sql = prop.getProperty("selectListCount");

    try {
        pstmt = conn.prepareStatement(sql); // 완성된 sql문 => rset에 바로 담기
        rset = pstmt.executeQuery();

        if (rset.next()) {
            listCount = rset.getInt("COUNT"); // COUNT(*) => 별칭써주자
        }

    } catch (SQLException e) {
        e.printStackTrace();
    } finally {
        close(rset);
        close(pstmt);
    }

    return listCount;
}
public ArrayList<Board> selectList(Connection conn, PageInfo pi) {
    // select문 => ResultSet 객체 (여러행) => ArrayList<Board>
    ArrayList<Board> list = new ArrayList<Board>();

    PreparedStatement pstmt = null;
    ResultSet rset = null;

    String sql = prop.getProperty("selectList");

    try {
        pstmt = conn.prepareStatement(sql);

        /*
         *  currentPage(현재페이징번호) : 1 => 시작값 : 1  | 끝값 : 10
         *  currentPage(현재페이징번호) : 2 => 시작값 : 11 | 끝값 : 20
         *  currentPage(현재페이징번호) : 3 => 시작값 : 21 | 끝값 : 30
         *  
         *  시작값 : (currentPage - 1) * boardLibit + 1
         *  끝값  : 시작값 + boardLimit - 1 
         */

        int startRow = (pi.getCurrentPage() - 1) * pi.getBoardLimit() + 1;
        int endRow = startRow + pi.getBoardLimit() - 1;

        pstmt.setInt(1, startRow);
        pstmt.setInt(2, endRow);

        rset = pstmt.executeQuery();

        while (rset.next()) { // if문으로 하면 하나 밖에 안 나옴
            list.add(new Board(rset.getInt("board_no"),
                               rset.getString("category_name"),
                               rset.getString("board_title"),
                               rset.getString("user_id"),
                               rset.getInt("count"),
                               rset.getString("create_date")
                               ));
        }

    } catch (SQLException e) {
        e.printStackTrace();
    } finally {
        close(rset);
        close(pstmt);
    }

    return list;
}

 

boardListView.jsp

<%@page import="com.board.model.vo.Board"%>
<%@page import="java.util.ArrayList"%>
<%@page import="com.common.model.vo.PageInfo"%>
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%
	PageInfo pi = (PageInfo)request.getAttribute("pi");
	ArrayList<Board> list = (ArrayList<Board>)request.getAttribute("list");
	
	int currentPage = pi.getCurrentPage();
	int startPage = pi.getStartPage();
	int endPage = pi.getEndPage();
	int maxPage = pi.getMaxPage();
%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>

    <div class="outer">
        <br>
        <h2 align="center">일반게시판</h2>
        <br>

        <!-- 로그인한 회원만 보여지는 div -->
        <% if (loginUser != null) { %>
        <div align="right" style="width: 860px;">
            <a href="<%= contextPath %>/enrollForm.bo" class="btn btn-sm btn-secondary">글작성</a>
            <br><br>
        </div>
		<% } %>
		
        <table align="center" class="list-area">
            <thead>
                <tr>
                    <th width="70">글번호</th>
                    <th width="80">카테고리</th>
                    <th width="300">제목</th>
                    <th width="100">작성자</th>
                    <th width="50">조회수</th>
                    <th width="100">작성일</th>
                </tr>
            </thead>
            <tbody>
            	<% if (list.isEmpty()) { %>
                <!-- case1. 게시글이 없을 경우 -->
                <tr>
                    <td colspan="6">조회된 게시글이 없습니다.</td>
                </tr>
                <% } else { %>
                <!-- case2. 게시글이 있을 경우 -->
                	<% for (Board b : list) { %>
                <tr>
                    <td><%= b.getBoardNo() %></td>
                    <td><%= b.getCategoryNo() %></td>
                    <td><%= b.getBoardTitle() %></td>
                    <td><%= b.getBoardWriter() %></td>
                    <td><%= b.getCount() %></td>
                    <td><%= b.getCreateDate() %></td>
                </tr>
                	<% } %>
                <% } %>
            </tbody>
        </table>

		// 목록 클릭시 상세 페이지로 이동하는 스크립트
		<script>
			$(function() {
				$(".list-area>tbody>tr").click(function() {
					location.href='<%= contextPath %>/detail.bo?bno=' + $(this).children().eq(0).text();
				})
			})
		</script>
		
        <br><br>

		// 페이징 처리
        <div class="paging-area" align="center">
        
        	<% if (currentPage != 1) { %>
            	<button onclick="location.href = '<%= contextPath %>/list.bo?cpage=<%= currentPage - 1 %>'">&lt;</button>
            <% } %>
            
            <% for (int p = startPage; p <= endPage; p++) { %>
            	<% if (p == currentPage) { %>
            		<button style="background: #A28AA6" disabled><%= p %></button>
            	<% } else { %>
            		<button onclick="location.href = '<%= contextPath %>/list.bo?cpage=<%= p %>'"><%= p %></button>
            	<% } %>
            <% } %>
            
            <% if (currentPage != maxPage) { %>
            <button onclick="location.href = '<%= contextPath %>/list.bo?cpage=<%= currentPage + 1 %>'">&gt;</button>
       		<% } %>
        </div>
    </div>
</body>
</html>