페이징 구현하는 거 별 거 아닌 줄 알았다가 ㅋㅋㅋ 과정이 안끝나서 ??? 했음 ㅋㅋㅋㅋ
메소드 위에 롬복 추가하면 메소드도 toString에 포함돼서 출력됨
private int p = 1;
private int size = 10;
@ToString.Include
public int endRow(){
return p * size;
}
@ToString.Include
public int startRow(){
return endRow() - (size - 1);
}
@RequestParam(required = false, defaultValue = "1") int p
VO에 현재 페이지 변수를 추가해 받아오도록 했는데, 목록 조회 메소드는 매개변수로 VO를 받고 있지 않아서 페이징이 적용되지 않음. 목록과 검색 결과 조회 메소드가 분리되어 있는데, 통합 조회 메소드를 새로 추가해서 해당 메소드에서 검색인지 목록인지를 구분해 각 메소드를 호출하도록 수정
//Dao
List<BoardDto> selectList(BoardListSearchVO vo);
List<BoardDto> list(BoardListSearchVO vo);
List<BoardDto> search(BoardListSearchVO vo);
//DaoImpl
public List<BoardDto> selectList(BoardListSearchVO vo) {
if(vo.isSearch()) {//검색이라면
return 검색메소드;
}else {
return 목록메소드;
}
}
model.addAttribute("list", boardDao.selectList(vo));
마지막 페이지 번호를 구하려면 총 데이터 개수를 알아야 함
//VO
//총 게시글 수
@ToString.Include
private int count;
//Dao
//검색과 목록의 총 결과 데이터 개수를 구하는 메소드
int count(BoardListSearchVO vo);
int searchCount(BoardListSearchVO vo);
int listCount(BoardListSearchVO vo);
//DaoImpl
@Override
public int count(BoardListSearchVO vo) {
if(vo.isSearch()) {
return searchCount(vo);
}else {
return listCount(vo);
}
}
@Override
public int searchCount(BoardListSearchVO vo) {
String sql = "select count(*) "
+ "from board "
+ "where instr(#1, ?) > 0";
sql = sql.replace("#1", vo.getType());
Object[] param = {vo.getKeyword()};
return jdbcTemplate.queryForObject(sql, int.class, param);
}
@Override
public int listCount(BoardListSearchVO vo) {
String sql = "select count(*) from board";
return jdbcTemplate.queryForObject(sql, int.class);
}
//list
//페이지 네비게이터를 위한 게시글 수 구하기
int count = boardDao.count(vo);
//count도 vo에 첨부 -> model로 자동으로 넘길 수 있도록
vo.setCount(count);
페이지 내비게이터에 있는 숫자 하나하나를 블록이라고 함
//화면에 표시할 page block 수(default=10)
private int blockSize = 10;
count + (size - 1) / size
현재 페이지(p)에 따른 시작/끝 블록(start/end Block) 설정이 필요함
(p + blockSize - 1) / blockSize * blockSize
endBlock - 9
//마지막 페이지
@ToString.Include
public int pageCount() {
return (count + size - 1) / size;
}
//시작 블록
public int StartBlock() {
return endBlock() - 9;
}
//끝 블록
public int endBlock() {
return (p + blockSize - 1) / blockSize * blockSize;
}
화면에 페이지 내비게이터 추가
<!-- 페이지 내비게이터 -->
<h3>
«
<
<c:forEach var="i" begin="${vo.startBlock}" end="${vo.endBlock}" step="1">
<a href="list?p=${i}">${i}</a>
</c:forEach>
>
»
</h3>
<a href="list?p=${vo.startBlock()-1}"></a>
이렇게 해도 되지만, 의미가 있으면 이름을 붙여 메소드로 만들고 호출해오는 객체지향 코드를 작성(유지보수 용이)
<a href="list?p=${vo.prevBlock()}"><</a>
//VO
@ToString.Include
public int prevBlock() {
return startBlock() - 1;
}
@ToString.Include
public int nextBlock() {
return endBlock() + 1;
}
@ToString.Include
public int firstBlock() {
return 1;
}
@ToString.Include
public int lastBlock() {
return pageCount();
}
<!-- 현재 첫 페이지가 아니라면: 메소드화
<c:when test="${vo.p > 1}">
-->
<!-- 현재 첫 페이지가 아니라면 -->
<c:when test="${not vo.isFirst()}">
<!-- 첫 페이지로 이동 -->
<a href="list?p=${vo.firstBlock()}">«</a>
</c:when>
<c:choose>
<!-- 현재 첫 구간이 아니라면 = startBlock이 1이 아니면 -->
<c:when test="${vo.startBlock() > 1}">
<!-- 이전을 누르면 이전 구간의 마지막 페이지로 안내 -->
<a href="list?p=${vo.prevBlock()}"><</a>
</c:when>
<c:otherwise>
<a href="#">«</a>
</c:otherwise>
</c:choose>
//첫 페이지 검사
@ToString.Include
public boolean isFirst() {
return p == 1;
}
//현재 구간 검사(이전 구간이 있는지)
@ToString.Include
public boolean hasPrev() {
return startBlock() > 1;
}
<!-- 다음을 누르면 다음 구간의 첫 페이지로 안내 -->
<c:choose>
<c:when test="${vo.hasNext()}">
<a href="list?p=${vo.nextBlock()}&${vo.parameter()}">></a>
</c:when>
<c:otherwise>
<a href="#">></a>
</c:otherwise>
</c:choose>
<c:choose>
<c:when test="${not vo.isLast()}">
<a href="list?p=${vo.lastBlock()}&${vo.parameter()}">»</a>
</c:when>
<c:otherwise>
<a href="#">»</a>
</c:otherwise>
</c:choose>
데이터가 존재하는 마지막 페이지를 끝페이지로 설정
Math.min(a, b)
활용endBlock을 기준으로 startBlock을 구하는 방식을 사용했던 것이 문제가 됨
@ToString.Include
public int startBlock() {
return (p - 1) / blockSize * blockSize + 1;
}
@ToString.Include
public int endBlock() {
int value = startBlock() + blockSize - 1;
return Math.min(value, lastBlock());
}
//마지막 페이지 검사
@ToString.Include
public boolean isLast() {
return endBlock() == lastBlock();
}
//현재 구간 검사(다음 구간이 있는지)
@ToString.Include
public boolean hasNext() {
return endBlock() < lastBlock();
}
검색 후 다음 페이지 넘어가면 검색 조건이 풀림
size 바꾸고 다음페이지 넘어가면 변경 size 설정 풀림
파라미터로 불러올 메소드 추가
//VO
public String parameter() {
if(isSearch()) {
return "size="+size+"&type="+type+"&keyword="+keyword;
}else {
return "size="+size;
}
}
모든 링크에 &${vo.parameter()}
추가
//list.jsp
//ex.
<a href="list?p=${vo.nextBlock()}&${vo.parameter()}">></a>