✅ offset : 대상이 처음에서부터 떨어져있는 정도
✅ row_count : 읽어올 행(row)의 수
package com.fastcampus.ch4.domain;
public class PageHandler {
private int totalCnt; // 총 게시물 게수
private int pageSize; // 한 페이지의 크기
private int naviSize = 10; // 페이지 내비게이션의 크기
private int totalPage; // 전체 페이지의 개수
private int page; // 현제 페이지
private int beginPage; // 내비게이션의 첫번째 페이지
private int endPage; // 내비게이션의 마지막 페이지
// 이전 페이지로 이동하는 링크를 보여줄 것인지 여부. endPage==totalPage이면, showNext는 false
private boolean showPrev;
// 다음 페이지로 이동하는 링크를 보여줄 것인지 여부, beginPage==1이 아니면 showPrev는 false
private boolean showNext;
public PageHandler(int totalCnt, int page){
this(totalCnt,page, 10);
}
public PageHandler(int totalCnt, int page, int pageSize){
this.totalCnt = totalCnt;
this.page = page;
this.pageSize = pageSize;
// 올림/내림/반올림: Math.ceil / Math.floor / Math.round
totalPage = (int)Math.ceil(totalCnt / (double)pageSize);
totalPage = (int)Math.ceil(totalCnt / (double)pageSize); // Math.ceil 올림
beginPage = (page-1) / naviSize * naviSize + 1;
endPage = Math.min(beginPage + naviSize - 1, totalPage);
showPrev = beginPage != 1;
showNext = endPage != totalPage;
}
void print() {
System.out.println("page = "+ page);
System.out.print(showPrev? "[PREV] " : "");
for(int i=beginPage;i<=endPage;i++) {
System.out.print(i+" ");
}
System.out.println(showNext? " [NEXT]" : "");
}
@Override
public String toString() { 생략 }
package com.fastcampus.ch4.domain;
import org.junit.Test;
import static org.junit.Assert.*;
public class PageHandlerTest {
@Test
public void test(){
// page=1, beginPage=1, endpage=10, showPrev=false, showNext=true
PageHandler ph = new PageHandler(250,1);
ph.print();
System.out.println("ph = " + ph);
assertTrue(ph.getBeginPage() ==1);
assertTrue(ph.getEndPage() ==10);
}
@Test
public void test2(){
// page=11, beginPage=11, endpage=20, showPrev=true, showNext=true
PageHandler ph = new PageHandler(250,11);
ph.print();
System.out.println("ph = " + ph);
assertTrue(ph.getBeginPage()==11);
assertTrue(ph.getEndPage()==20);
}
@Test
public void test3(){
// page=25, beginPage=21, endpage=26, showPrev=true, showNext=false
PageHandler ph = new PageHandler(255,25);
ph.print();
System.out.println("ph = " + ph);
assertTrue(ph.getBeginPage()==21);
assertTrue(ph.getEndPage()==26);
}
}
✔️ BoardDaoImpl - refactor - Extract Interface
✔️ BoardDaoImpl - Go to - Test
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {"file:src/main/webapp/WEB-INF/spring/root-context.xml"})
public class BoardDaoImplTest {
@Autowired
private BoardDao boardDao;
@Test
public void insertTestData() throws Exception{
boardDao.deleteAll();
for (int i=1; i<=220; i++){
BoardDto boardDto = new BoardDto("title"+i,"no content", "asdf");
boardDao.insert(boardDto);
}
}
@Test
public void countTest() throws Exception {
boardDao.deleteAll();
assertTrue(boardDao.count()==0);
BoardDto boardDto = new BoardDto("no title", "no content", "asdf");
assertTrue(boardDao.insert(boardDto)==1);
assertTrue(boardDao.count()==1);
assertTrue(boardDao.insert(boardDto)==1);
assertTrue(boardDao.count()==2);
}
@Test
public void deleteAllTest() throws Exception {
boardDao.deleteAll();
assertTrue(boardDao.count()==0);
BoardDto boardDto = new BoardDto("no title", "no content", "asdf");
assertTrue(boardDao.insert(boardDto)==1);
assertTrue(boardDao.deleteAll()==1);
assertTrue(boardDao.count()==0);
boardDto = new BoardDto("no title", "no content", "asdf");
assertTrue(boardDao.insert(boardDto)==1);
assertTrue(boardDao.insert(boardDto)==1);
assertTrue(boardDao.deleteAll()==2);
assertTrue(boardDao.count()==0);
}
@Test
public void deleteTest() throws Exception {
boardDao.deleteAll();
assertTrue(boardDao.count()==0);
BoardDto boardDto = new BoardDto("no title", "no content", "asdf");
assertTrue(boardDao.insert(boardDto)==1);
Integer bno = boardDao.selectAll().get(0).getBno();
assertTrue(boardDao.delete(bno, boardDto.getWriter())==1);
assertTrue(boardDao.count()==0);
assertTrue(boardDao.insert(boardDto)==1);
bno = boardDao.selectAll().get(0).getBno();
assertTrue(boardDao.delete(bno, boardDto.getWriter()+"222")==0);
assertTrue(boardDao.count()==1);
assertTrue(boardDao.delete(bno, boardDto.getWriter())==1);
assertTrue(boardDao.count()==0);
assertTrue(boardDao.insert(boardDto)==1);
bno = boardDao.selectAll().get(0).getBno();
assertTrue(boardDao.delete(bno+1, boardDto.getWriter())==0);
assertTrue(boardDao.count()==1);
}
@Test
public void insertTest() throws Exception {
boardDao.deleteAll();
BoardDto boardDto = new BoardDto("no title", "no content", "asdf");
assertTrue(boardDao.insert(boardDto)==1);
boardDto = new BoardDto("no title", "no content", "asdf");
assertTrue(boardDao.insert(boardDto)==1);
assertTrue(boardDao.count()==2);
boardDao.deleteAll();
boardDto = new BoardDto("no title", "no content", "asdf");
assertTrue(boardDao.insert(boardDto)==1);
assertTrue(boardDao.count()==1);
}
@Test
public void selectAllTest() throws Exception {
boardDao.deleteAll();
assertTrue(boardDao.count()==0);
List<BoardDto> list = boardDao.selectAll();
assertTrue(list.size() == 0);
BoardDto boardDto = new BoardDto("no title", "no content", "asdf");
assertTrue(boardDao.insert(boardDto)==1);
list = boardDao.selectAll();
assertTrue(list.size() == 1);
assertTrue(boardDao.insert(boardDto)==1);
list = boardDao.selectAll();
assertTrue(list.size() == 2);
}
@Test
public void selectTest() throws Exception {
boardDao.deleteAll();
assertTrue(boardDao.count()==0);
BoardDto boardDto = new BoardDto("no title", "no content", "asdf");
assertTrue(boardDao.insert(boardDto)==1);
Integer bno = boardDao.selectAll().get(0).getBno();
boardDto.setBno(bno);
BoardDto boardDto2 = boardDao.select(bno);
assertTrue(boardDto.equals(boardDto2));
}
@Test
public void selectPageTest() throws Exception {
boardDao.deleteAll();
for (int i = 1; i <= 10; i++) {
BoardDto boardDto = new BoardDto(""+i, "no content"+i, "asdf");
boardDao.insert(boardDto);
}
Map map = new HashMap();
map.put("offset", 0);
map.put("pageSize", 3);
List<BoardDto> list = boardDao.selectPage(map);
assertTrue(list.get(0).getTitle().equals("10"));
assertTrue(list.get(1).getTitle().equals("9"));
assertTrue(list.get(2).getTitle().equals("8"));
map = new HashMap();
map.put("offset", 0);
map.put("pageSize", 1);
list = boardDao.selectPage(map);
assertTrue(list.get(0).getTitle().equals("10"));
map = new HashMap();
map.put("offset", 7);
map.put("pageSize", 3);
list = boardDao.selectPage(map);
assertTrue(list.get(0).getTitle().equals("3"));
assertTrue(list.get(1).getTitle().equals("2"));
assertTrue(list.get(2).getTitle().equals("1"));
}
@Test
public void updateTest() throws Exception {
boardDao.deleteAll();
BoardDto boardDto = new BoardDto("no title", "no content", "asdf");
assertTrue(boardDao.insert(boardDto)==1);
Integer bno = boardDao.selectAll().get(0).getBno();
System.out.println("bno = " + bno);
boardDto.setBno(bno);
boardDto.setTitle("yes title");
assertTrue(boardDao.update(boardDto)==1);
BoardDto boardDto2 = boardDao.select(bno);
assertTrue(boardDto.equals(boardDto2));
}
@Test
public void increaseViewCntTest() throws Exception {
boardDao.deleteAll();
assertTrue(boardDao.count()==0);
BoardDto boardDto = new BoardDto("no title", "no content", "asdf");
assertTrue(boardDao.insert(boardDto)==1);
assertTrue(boardDao.count()==1);
Integer bno = boardDao.selectAll().get(0).getBno();
assertTrue(boardDao.increaseViewCnt(bno)==1);
boardDto = boardDao.select(bno);
assertTrue(boardDto!=null);
assertTrue(boardDto.getView_cnt() == 1);
assertTrue(boardDao.increaseViewCnt(bno)==1);
boardDto = boardDao.select(bno);
assertTrue(boardDto!=null);
assertTrue(boardDto.getView_cnt() == 2);
}
}
✔️ BoardDaoImpl - refactor - Extract Interface
package com.fastcampus.ch4.service;
@Service
public class BoardServiceImpl implements BoardService {
@Autowired
BoardDao boardDao;
@Override
public int getCount() throws Exception {
return boardDao.count();
}
@Override
public int remove(Integer bno, String writer) throws Exception {
return boardDao.delete(bno, writer);
}
@Override
public int write(BoardDto boardDto) throws Exception {
return boardDao.insert(boardDto);
}
@Override
public List<BoardDto> getList() throws Exception {
return boardDao.selectAll();
}
@Override
public BoardDto read(Integer bno) throws Exception {
BoardDto boardDto = boardDao.select(bno);
boardDao.increaseViewCnt(bno);
return boardDto;
}
@Override
public List<BoardDto> getPage(Map map) throws Exception {
return boardDao.selectPage(map);
}
@Override
public int modify(BoardDto boardDto) throws Exception {
return boardDao.update(boardDto);
}
}
@Controller
@RequestMapping("/board")
public class BoardController {
@Autowired
BoardService boardService;
@GetMapping("/list")
public String list(Integer page, Integer pageSize, Model m, HttpServletRequest request) {
if(!loginCheck(request))
return "redirect:/login/login?toURL="+request.getRequestURL();
if(page==null) page=1;
if(pageSize==null) pageSize=10;
try {
int totalCnt = boardService.getCount();
PageHandler pageHandler = new PageHandler(totalCnt, page, pageSize);
Map map = new HashMap<>();
map.put("offset", (page-1)*pageSize);
map.put("pageSize", pageSize);
List<BoardDto> list = boardService.getPage(map);
m.addAttribute("list", list);
m.addAttribute("ph", pageHandler);
} catch (Exception e) {
e.printStackTrace();
}
return "boardList"; // 로그인을 한 상태이면, 게시판 화면으로 이동
private boolean loginCheck(HttpServletRequest request) {
HttpSession session = request.getSession();
return session.getAttribute("id")!=null;
}
}
<%@ page language="java" contentType="text/html; charset=UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<!DOCTYPE html>
<html lang="en">
<head>
<meta http-equiv="x-ua-compatible" content="IE-edge">
<meta name="viewport" content="width-device-width, initial-scal-1.0">
<meta charset="UTF-8">
<title>fastcampus</title>
<link rel="stylesheet" href="<c:url value='/css/menu.css'/>">
</head>
<body>
<div id="menu">
<ul>
<li id="logo">fastcampus</li>
<li><a href="<c:url value='/'/>">Home</a></li>
<li><a href="<c:url value='/board/list'/>">Board</a></li>
<li><a href="<c:url value='/login/login'/>">login</a></li>
<li><a href="<c:url value='/register/add'/>">Sign in</a></li>
<li><a href=""><i class="fas fa-search small"></i></a></li>
</ul>
</div><div style="text-align:center">
<table border="1">
<tr>
<th class="no">번호</th>
<th class="title">제목</th>
<th class="writer">이름</th>
<th class="reg_date">등록일</th>
<th class="view_cnt">조회수</th>
</tr>
<c:forEach var="board" items="${list}">
<tr>
<td>${board.bno}</td>
<td>${board.title}</td>
<td>${board.writer}</td>
<td>${board.reg_date}</td>
<td>${board.view_cnt}</td>
</tr>
</c:forEach>
</table>
<br>
<div>
<c:if test="${ph.showPrev}">
<a href="<c:url value='/board/list?page=${ph.beginPage-1}&pageSize=${ph.pageSize}'/>"><</a>
</c:if>
<c:forEach var="i" begin="${ph.beginPage}" end="${ph.endPage}">
<a href="<c:url value='/board/list?page=${i}&pageSize=${ph.pageSize}'/>">${i}</a>
</c:forEach>
<c:if test="${ph.showNext}">
<a href="<c:url value='/board/list?page=${ph.endPage+1}&pageSize=${ph.pageSize}'/>">></a>
</c:if>
</div>
</div>
</body>
</html>
참고) 자바의 정석 | 남궁성과 끝까지 간다