본문 바로가기

개발/Web

[Java] Sevlet/JSP - 일반게시판 - 게시글 리스트 조회 / 페이징 처리

일반게시판

 

< 게시글 리스트 조회(+ 페이징 처리) >

 

* BOARD 테이블

- BOARD_TYPE(게시글 타입)으로 일반게시판과 사진게시판을 구분 

 

1. 리스트 조회 요청

- 리스트 조회 요청하는 버튼 생성

- 요청 시 쿼리스트링으로 페이지값을 전달함 

<div class="menu"><a href="<%= contextPath %>/list.bo?cpage=1">일반게시판</a></div>

 

2. BoardListController.java (Servlet)

- 매핑값 : /list.bo

- 요청 시 페이지 번호를 넘겨줘야 함 (쿼리스트링 ?cpage=숫자)

- Service단으로 두 번 요청 (총 게시글 수 카운트 / 페이징처리에 맞춰 화면에 보여질 게시글리스트 조회)

페이징 처리에 필요한 변수들
int listCount 현재 일반게시판 게시글 총 개수 (DB의 테이블 조회)
int pageLimit 페이지 하단에 보여질 페이징바 최대 개수
int boardLimit 한 페이지에 보여질 게시글의 최대 개수
int currentPage 현재 페이지. 사용자가 요청한 페이지 (cpage 키로 넘겨받은 값)
int maxPage 가장 마지막 페이지번호. 총 페이지 개수
int startPage 페이지 하단에 보여질 페이징바의 시작 번호
int endPage 페이지 하단에 보여질 페이징바의 마지막 번호
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

    // ----------------- 페이징 처리 -------------
    int listCount;
    int pageLimit; 
    int boardLimit; 
    int currentPage; 
    int maxPage;
    int startPage; 
    int endPage;  

    listCount = new BoardService().selectListCount(); // 총 게시글 수
    pageLimit = 10;  // 페이징바에 노출할 최대 페이지 수
    boardLimit = 10; // 한 페이지에 노출할 최대 게시글 수 
    currentPage = Integer.parseInt(request.getParameter("cpage")); // 현재 요청한 페이지
    maxPage = (int)Math.ceil((double)listCount / boardLimit); // 총 페이지 개수
    startPage = (currentPage - 1) / pageLimit * pageLimit + 1; // 현재 페이지에 따른 페이징바의 시작페이지
    endPage = startPage + pageLimit - 1; // 현재 페이지에 따른 페이징바의 끝 페이지
    if(endPage > maxPage) { // 페이징바의 마지막 페이지가 총 페이지 개수보다 커지면 조절
      endPage = maxPage;
    }
    // 가공처리
    PageInfo pi = new PageInfo(listCount, currentPage, pageLimit, boardLimit, maxPage, startPage, endPage);
    //-----------------------------------------------
    
    // DB에서 현재 지정한 페이징규칙에 맞게 리스트를 저장
    ArrayList<Board> list = new BoardService().selectList(pi);
   
    // 응답화면
    request.setAttribute("list", list);
    request.setAttribute("pi", pi);
    request.getRequestDispatcher("views/board/boardListView.jsp").forward(request, response);
 }

 

3. BoardService.java (자바클래스)

- 두 개의 메소드 작성

- selectListCount() : 총 게시글 수 반환

public int selectListCount() {

    Connection conn = getConnection();

    int listCount = new BoardDao().selectListCount(conn);
    // SELECT문을 실행하지만 게시글 총 수인 정수값으로 돌아옴
    
    close(conn);

    return listCount;		
}

- selectList() : 페이징규칙에 맞는 게시글 리스트 저장한 ArrayList반환

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

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

    close(conn);

    return list;
}

 

4. BoardDao.java (자바클래스)

- DAO기본

- DB접속정보와 SQL문 담은 XML파일 읽어오기

public class BoardDao {
	// 필드
	private Properties prop = new Properties();
	// 기본생성자
	public BoardDao() {
		String fileName = BoardDao.class.getResource("/sql/board/board-mapper.xml").getPath();
		try {
			prop.loadFromXML(new FileInputStream(fileName));
		} catch (IOException e) {
			e.printStackTrace();
		}		
	}
}

- 두 개의 SQL문 실행 = 두 개의 메소드 작성

- selectListCount() : 총 게시글 수 반환

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);

        rset = pstmt.executeQuery();

        if(rset.next()) {
            listCount = rset.getInt("COUNT(*)");
        }

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

- SQL문 (SELECT - COUNT(*))

<entry key="selectListCount">
    SELECT
           COUNT(*)
      FROM
           BOARD
     WHERE
           STATUS = 'Y'
       AND
           BOARD_TYPE = 1
</entry>

- selectList() : 페이징규칙에 맞는 게시글 리스트 저장한 ArrayList반환

public ArrayList<Board> selectList(Connection conn, PageInfo pi) {
    // SELECT문 => ResultSet => 여러 행이므로 ArrayList<Board>
    ArrayList<Board> list = new ArrayList();
    PreparedStatement pstmt = null;
    ResultSet rset = null;
    String sql = prop.getProperty("selectList");

    try {
        pstmt = conn.prepareStatement(sql);

        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()) {
        	// VO에 해당 매개변수 생성자 작성
            list.add(new Board(rset.getInt("BOARD_NO"),
                               rset.getString("CATEGORY_NAME"),
                               rset.getString("BOARD_TITLE"),
                               rset.getString("USER_ID"),
                               rset.getInt("COUNT"),
                               rset.getDate("CREATE_DATE")));
        }
    } catch (SQLException e) {
        e.printStackTrace();
    } finally {
        close(rset);
        close(pstmt);
    }

    return list;
}

- SQL문           * 실행순서 중요!

1) ORDER BY(정렬)한 SELECT문 서브쿼리로 FROM절에 넣기

 2) ROWNUM 별칭 위해 전체 SELECT절을 FROM절에 넣기

<entry key="selectList">
    SELECT *
      FROM (SELECT 
                   ROWNUM RNUM, 
                   A.*
              FROM 
                   (SELECT
                           BOARD_NO,
                           CATEGORY_NAME,
                           BOARD_TITLE,
                           USER_ID,
                           COUNT,
                           CREATE_DATE
                      FROM 
                           BOARD B
                      JOIN
                           CATEGORY USING(CATEGORY_NO)
                      JOIN     
                           MEMBER ON(BOARD_WRITER = USER_NO)
                     WHERE 
                           BOARD_TYPE = 1
                       AND 
                           B.STATUS = 'Y'
                     ORDER 
                        BY 
                           CREATE_DATE DESC) A)
      WHERE 
            RNUM BETWEEN ? AND ?
</entry>

 

5. boardListView.jsp (JSP)

- 페이징처리한 게시글 리스트를 보여주는 화면

- 넘겨받은 게시글 리스트(list)와 페이징처리값(pi) 변수로 저장

<%@ page import="java.util.ArrayList, com.kh.board.model.vo.Board, com.kh.common.model.vo.PageInfo" %>
<%
	ArrayList<Board> list = (ArrayList<Board>)request.getAttribute("list");
	PageInfo pi = (PageInfo)request.getAttribute("pi");
	
	// 페이징바 만들 때 필요한 변수 미리 세팅
	int currentPage = pi.getCurrentPage();
	int startPage = pi.getStartPage();
	int endPage = pi.getEndPage();
	int maxPage = pi.getMaxPage();	
%>

- 게시글 리스트 보여줄 테이블태그 작성

<table class="list-area" align="center">
    <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>
        <!-- 게시글 출력 : 게시글이 있는지 없는지 => inEmpty()이용해서 없는 경우 조건 부여  -->
        <% if(list.isEmpty()) { %>
            <tr>
                <td colspan="6">조회된 게시글이 없습니다.</td>
            </tr>			
        <% } else { %>
            <!-- 반복 : list에 있는 값을 순차적으로 접근해서 뽑아오기 -->
            <% for (Board b : list) { %>
                <tr>
                    <td><%= b.getBoardNo() %></td>
                    <td><%= b.getCategory() %></td>
                    <td><%= b.getBoardTitle() %></td>
                    <td><%= b.getBoardWriter() %></td>
                    <td><%= b.getCount() %></td>
                    <td><%= b.getCreateDate() %></td>
                </tr>
            <% } %>
        <% } %>
    </tbody>
</table>

- 가져온 페이징규칙에 맞춰 페이징바 작성

<div align="center" class="paging-area">
    <!-- 이전 페이지로 가기 버튼 -->
    <% if(currentPage != 1) { %>
        <button class="btn btn-sm btn-info" onclick="location.href='<%= contextPath %>/list.bo?cpage=<%= currentPage - 1 %>'">&lt;</button>
    <% } %>
    <!-- 페이지 숫자 버튼 -->
    <% for(int i = startPage; i <= endPage; i++) { %>
        <% if(currentPage != i) { %>
            <button class="btn btn-sm btn-info" onclick="location.href='<%= contextPath %>/list.bo?cpage=<%= i %>'"><%= i %></button>
        <% } else { %>
            <button class="btn btn-sm btn-info" disabled><%= i %></button>
        <% } %>
    <% } %>
    <!-- 다음 페이지로 가기 버튼 -->
    <% if(maxPage != currentPage) { %>
        <button class="btn btn-sm btn-info" onclick="location.href='<%= contextPath %>/list.bo?cpage=<%= currentPage + 1 %>'">&gt;</button>
    <% } %>
</div>