[Spring / BootStrap] Spring Legacy MVC Project로 게시판 및 채팅 기능 구현 - 7 (게시판 list 페이징처리)
리트리버J
·2021. 1. 13. 16:50
1. 게시글을 10개 단위로 다음 페이지로 넘기고 싶다.
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도 바꿔준다.
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로 바꿔주자.
10. 완성