[Spring / BootStrap] Spring Legacy MVC Project로 게시판 및 채팅 기능 구현 - 7 (게시판 list 페이징처리)

리트리버J

·

2021. 1. 13. 16:50

728x90

1. 게시글을 10개 단위로 다음 페이지로 넘기고 싶다.

13개가 되어버린 게시판

2. PageInfo VO 만들기

2-1.

    private int currentPage;  // 현재 페이지

    private int listCount;      // 총 게시글의 수 [ SELECT COUNT(*) FROM BOARD ]

    private int pageLimit;    // 한 페이지에 보여질 페이징 수 ex) 총 페이지가 13개면, 1 ~ 10 / 11 ~ 13

    private int maxPage;     // 총 페이지    (1 ~ 50)

    private int startPage;    // 시작 페이지  (1    11    21    31    41)

    private int endPage;     // 끝 페이지    (10    20    30    40    50)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
package com.bootstrap.tutorial.board.model.vo;
 
public class PageInfo {
    
    private int currentPage; // 현재 페이지
    private int listCount;   // 총 게시글의 수 [ SELECT COUNT(*) FROM BOARD ]
    private int pageLimit;   // 한 페이지에 보여질 페이징 수 ex) 총 페이지가 13개면, 1 ~ 10 / 11 ~ 13
    private int maxPage;     // 총 페이지    (1 ~ 50)
    private int startPage;   // 시작 페이지  (1    11    21    31    41)
    private int endPage;     // 끝 페이지    (10    20    30    40    50)
    
    private int boardLimit;
    
    public PageInfo() {
        super();
    }
 
    public PageInfo(int currentPage, int listCount, int pageLimit, int maxPage, int startPage, int endPage, int boardLimit) {
        super();
        this.currentPage = currentPage;
        this.listCount = listCount;
        this.pageLimit = pageLimit;
        this.maxPage = maxPage;
        this.startPage = startPage;
        this.endPage = endPage;
        this.boardLimit = boardLimit;
    }
 
    public int getCurrentPage() {
        return currentPage;
    }
 
    public void setCurrentPage(int currentPage) {
        this.currentPage = currentPage;
    }
 
    public int getListCount() {
        return listCount;
    }
 
    public void setListCount(int listCount) {
        this.listCount = listCount;
    }
 
    public int getPageLimit() {
        return pageLimit;
    }
 
    public void setPageLimit(int pageLimit) {
        this.pageLimit = pageLimit;
    }
 
    public int getMaxPage() {
        return maxPage;
    }
 
    public void setMaxPage(int maxPage) {
        this.maxPage = maxPage;
    }
 
    public int getStartPage() {
        return startPage;
    }
 
    public void setStartPage(int startPage) {
        this.startPage = startPage;
    }
 
    public int getEndPage() {
        return endPage;
    }
 
    public void setEndPage(int endPage) {
        this.endPage = endPage;
    }
 
    public int getBoardLimit() {
        return boardLimit;
    }
 
    public void setBoardLimit(int boardLimit) {
        this.boardLimit = boardLimit;
    }
 
    @Override
    public String toString() {
        return "PageInfo [currentPage=" + currentPage + ", listCount=" + listCount + ", pageLimit=" + pageLimit
                + ", maxPage=" + maxPage + ", startPage=" + startPage + ", endPage=" + endPage + ", boardLimit="
                + boardLimit + "]";
    }
}
 
cs

3. Pagination 클래스 생성

3-1.

        // * maxPage :

        /*

         * 1. (총 게시글 수 / 한 페이지 게시글 수) => 실수형이 나오고, + 0.9

         * => ex) 26 / 10 = 2.6, 

         * =>     2.6 + 0.9 = 3.5

         * =>     (int)3.5 = 3

         *       총 페이지 = 1 2 3

         */

        maxPage = (int)((double)listCount / boardLimit + 0.9);

3-2.

        // * startPage : 

        /*

         * 1. ( 클릭한 페이징 번호 / 페이지 버튼 수) => 실수형이 나오고, + 0.9

         * => ex) 5 / 10 = 0.5,

         * =>       0.5 + 0.9 = 1.4,

         * =>      (int)1.4 = 1,

         * =>      1 - 1 = 0,

         * =>      0 * 10 = 0,

         * =>      0 + 1 = 1;

         * 이로써, 5를 눌러도 1 ~ 10까지의 페이징이 표시된다. 5 ~ 14가 아니다. 

         */

        startPage = (((int)((double)currentPage / pageLimit + 0.9)) - 1* pageLimit + 1;

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
package com.bootstrap.tutorial.board.model.vo;
 
public class Pagination {
    
    // PageInfo 객체를 리턴하는 static 메소드
    // currentPage와 listCount를 파라미터로 받는다.
    public static PageInfo getPageInfo(int currentPage, int listCount) {
        
        // 페이지 정보를 담아줄 PageInfo 참조변수 선언
        PageInfo pi = null;
        
        int pageLimit = 10;     // 한 페이지에서 보여질 페이지 버튼 수
        int maxPage;            // 전체 페이지 중 가장 마지막 페이지
        int startPage;          // 현재 페이지에서 보여질 페이징 버튼의 시작 페이지
        int endPage;            // 현재 페이지에서 보여질 페이징 버튼의 끝 페이지
        
        int boardLimit = 10;    // 한 페이지에서 보여질 게시글 갯수
        
        // * maxPage :
        /*
         * 1. (총 게시글 수 / 한 페이지 게시글 수) => 실수형이 나오고, + 0.9
         * => ex) 26 / 10 = 2.6, 
         * =>     2.6 + 0.9 = 3.5
         * =>     (int)3.5 = 3
         *       총 페이지 = 1 2 3
         */
        maxPage = (int)((double)listCount / boardLimit + 0.9);
        
        // * startPage : 
        /*
         * 1. ( 클릭한 페이징 번호 / 페이지 버튼 수) => 실수형이 나오고, + 0.9
         * => ex) 5 / 10 = 0.5,
         * =>       0.5 + 0.9 = 1.4,
         * =>      (int)1.4 = 1,
         * =>      1 - 1 = 0,
         * =>      0 * 10 = 0,
         * =>      0 + 1 = 1;
         * 이로써, 5를 눌러도 1 ~ 10까지의 페이징이 표시된다. 5 ~ 14가 아니다. 
         */
        startPage = (((int)((double)currentPage / pageLimit + 0.9)) - 1* pageLimit + 1;
        
        // * endPage - 현재 페이지에서 보여질 마지막 페이지 수
        // endPage = 1 + 10 - 1 = 10
        endPage = startPage + pageLimit - 1;
        
        // 만약 페이징이 13까지 있다면, 20까지 표시되는 것이 아니라 13까지만 표시된다.
        if(maxPage < endPage) {
            endPage = maxPage;
        }
        
        // PageInfo 생성자를 이용하여 새로운 인스턴스를 생성한다.
        pi = new PageInfo(currentPage, listCount, pageLimit, maxPage, startPage, endPage, boardLimit);
        
        return pi;
    }
}
 
cs

4. 게시판 홈(목록) Controller 업데이트

4-1. @RequestParam 어노테이션을 붙여, value, required, defaultValue를 설정해주자.

4-2. value는 jsp 태그의 name값이다.

4-3. required="true"일 시, null이 들어오면 400에러가 나오므로, false로 지정하자.

4-4. 그 대신, defaultValue로, 처음 들어갔을 때의 페이지인(버튼 안눌렀을 때) 1을 넣어주면 된다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
    /**
     * 1. 게시판 홈(목록) 이동 메소드
     * @return
     */
    @RequestMapping
    public String Board(Model model, 
                        @RequestParam(value="currentPage"// 태그의 name값
                                      required = false,       // 파라미터 필수 입력 여부
                                      defaultValue = "1"   // null값 → 1 [ required=true일 시, 400에러 ]
                                     )int currentPage) {
 
        // 게시글 목록
        ArrayList<Board> boardList = service.getBoardList();
        
        // 게시글 총 갯수
        int listCount = service.getListCount();
        
        // 확인용
        System.out.println("총 게시글 수  : " + listCount);
        
        // 클릭한 페이지, 총 게시글 수 전달
        PageInfo paging = Pagination.getPageInfo(currentPage, listCount);
        
        // JSP로 전송
        model.addAttribute("boardList", boardList);
        model.addAttribute("paging", paging);
        
        return "board/board_home";
    }
cs

5. jstl태그를 이용하여 jsp 페이지 리뉴얼 

5-1. 이전 or 다음이 없을 경우, <a>태그의 href속성을 없애여, 클릭하지 못하게 만든다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
    <!-- 페이징 처리 -->
    <nav aria-label="Page navigation example">
        <ul class="pagination justify-content-center">
        
            <!-- 이전 -->
            <c:if test="${paging.currentPage eq 1}">
                <li class="page-item">
                      <a class="page-link no-before" tabindex="-1" aria-disabled="true">이전</a>
                  </li>
            </c:if>
            <c:if test="${paging.currentPage ne 1}">
                <c:url var="before" value="/tutorial/board">
                    <c:param name="currentPage" value="${paging.currentPage - 1}"/>
                </c:url>
                
                <li class="page-item">
                      <a class="page-link" tabindex="-1" href="${before}" aria-disabled="true">이전</a>
                  </li>
            </c:if>
            
            <!-- 페이지 -->
            <c:forEach var="page" begin="${paging.startPage}" end="${paging.endPage}">
                <c:if test="${page eq paging.currentPage }">
                    <li class="page-item"><a class="page-link bg-primary text-light">${page}</a></li>
                </c:if>
                
                <c:if test="${page ne paging.currentPage }">
                    <c:url var="pagination" value="/tutorial/board">
                        <c:param name="currentPage" value="${paging.currentPage + 1}"/>
                    </c:url>
                    
                    <li class="page-item"><a class="page-link" href="${pagination}">${page}</a></li>
                </c:if>
            </c:forEach>
            
            <!-- 다음 -->
             <c:if test="${paging.currentPage eq paging.maxPage}">
                <li class="page-item">
                      <a class="page-link no-before" tabindex="-1" aria-disabled="true">다음</a>
                  </li>
            </c:if>
            <c:if test="${paging.currentPage ne paging.maxPage}">
                <c:url var="after" value="/tutorial/board">
                    <c:param name="currentPage" value="${paging.currentPage + 1}"/>
                </c:url>
                
                <li class="page-item">
                      <a class="page-link" tabindex="-1" href="${after}" aria-disabled="true">다음</a>
                  </li>
            </c:if>
            
        </ul>
    </nav>
cs

결과 : 14개의 게시글이므로, 페이지가 2개 있다.

아직 끝나지 않았다.

DAO에서, RowBounds를 이용해야 한다.

미완성 페이징

6. Controller/Service의 selectList() 메소드의 파라미터로 Paging 넣어주기

7. Service / ServiceImpl도 바꿔준다.

Service
ServiceImpl

8. Dao에 RowBounds를 추가해준다.

(RowBounds에 관한 내용은 다음에 자세히 다루도록 하겠습니다.)

참고로 RowBounds는 소량의 데이터를 불러올 때 적절하다고 합니다!

1
2
3
4
5
6
7
8
9
10
11
12
13
    public ArrayList<Board> getBoardList(PageInfo paging) {
        
        // ex) 현재페이지 5, 한 페이지에 보여질 게시글 수 10개
        // 5 - 1 = 4,
        // 4 * 10 = 40
        int offset = (paging.getCurrentPage() - 1* paging.getBoardLimit();
        
        RowBounds rowBounds = new RowBounds(offset, paging.getBoardLimit());
        
        // sqlSession.selectList()의 return값이 List<T>이기 때문에 
        // (ArrayList)로 다운캐스팅 형변환을 해주어야 한다.
        return (ArrayList)sqlSession.selectList("BoardMapper.selectBoardList"null, rowBounds);
    }
cs

9. WARN : org.springframework.web.servlet.PageNotFound - No mapping found for HTTP request with URI [/tutorial/tutorial/board] in DispatcherServlet with name 'appServlet' 오류 발생

9-1. a태그의 href처럼 /tutorial/board로 넣으면 오류가 발생한다.

9-2. servelet-path를 제외한 /board만 입력하자.

9-3. 모든 <c:url>의 value를 /board로 바꿔주자.

<c:url>의 value의 url에 주의!!

10. 완성

 첫번째 페이지

 

두번째 페이지

728x90