프로젝트를 진행하며 맡은 게시판만드는법을 정리해보겠습니다.
먼저 게시판테이블에 들어갈 속성을 담을 NoticeVO 클래스를 만듭니다.
@Data
public class NoticeVO {
private Long noticeNum;
private String id;
private String title;
private String contents;
private Date regDate;
private Long hit;
}
그리고 게시판 목록을 가져올 sql을 작성해야 되는데 pagination을 이용해 게시판의 페이지 이동을 하기 위해 Pager Class를 만듭니다.
@Data
@Slf4j
public class Pager {
private Long page; // 현재 게시판 페이지
private Long perPage; // 페이지당 글의 갯수
private Long totalPage; // 전체 페이지의 갯수
private Long startRow; // 현재 페이지의 시작 글번호
private Long lastRow; // 현재 페이지의 마지막 글번호
private Long block; // 현재 pagionation
private Long perBlock; // pagination당 page갯수
private Long startNum; // pagination의 시작 페이지번호
private Long lastNum; // pagination의 마지막 페이지번호
private boolean pre; // 이전페이지
private boolean next; // 다음페이지
public Pager() {
this.page=1L;
this.perPage=10L;
this.perBlock=10L;
}
public void setRow() {
//한페이지에 10개씩 출력 기준
//page startrow lastrow
//1 1 10
//2 11 20
//3 21 30
this.startRow = (this.getPage()-1)*this.getPerPage();
this.lastRow = this.getPage()*this.getPerPage();
}
public void setNum(Long totalCount) {
// 게시판 글의 총 갯수로 전체페이지의 수를 구함
this.totalPage = totalCount%this.getPerPage()==0 ? totalCount/this.getPerPage() : totalCount/this.getPerPage()+1;
// 전체 페이지수로 전체블록의 수를 구함
Long totalBlock = totalPage%this.getPerBlock()==0 ? totalPage/this.getPerBlock() : totalPage/this.getPerBlock()+1;
/* 현재페이지에 해당하는 현재블록을 구함
page curBlcok
1 1
2 1
3 1
4 1
5 1
6 2*/
Long curBlock = this.getPage()%this.getPerBlock()==0 ? this.getPage()/this.getPerBlock() : this.getPage()/this.getPerBlock()+1;
/* 현재블록의 startNum, lastNum을 구함
curBlock startNum lastNum
1 1 5
2 6 10
3 11 16
*/
this.startNum= (curBlock-1)*this.getPerBlock() + 1;
this.lastNum= curBlock*this.getPerBlock();
//현재블록이 마지막블록이면 lastNum은 마지막페이지번호임
if(curBlock==totalBlock) {
this.lastNum=totalPage;
}
// 2번 페이지이상 부터 이전버튼 활성화
if(this.page>1) {
pre=true;
}else{
pre=false;
}
//현재블록이 마지막블록보다 작으면 다음버튼 활성화
if(curBlock<totalBlock) {
next=true;
}else{
next=false;
}
}
public Long getPerPage() {
if(this.perPage==null) {
this.perPage=10L;
}
return perPage;
}
// 페이지가 null이거나 음수이면 1로 초기화 (사용자가 임의로 페이지에 이상한 값을 입력해서 이동을 방지)
public Long getPage() {
if(this.page==null || this.page<=0) {
this.page=1L;
}
return page;
}
}
NoticeMapper에 게시판목록을 가져오는 sql을 mapper에 등록합니다. mysql의 limit을 사용하여 startRow번호 부터 perPage개씩 목록을 가져옵니다. mysql은 0번부터 시작하고 oracle은 rownum을 사용할때 1번 부터 시작하는 것 같습니다.
<select id="getList" parameterType="Pager" resultType="NoticeVO" >
SELECT * FROM NOTICE ORDER BY NOTICENUM DESC LIMIT #{startRow},#{perPage}
</select>
// 전체 글의 갯수
<select id="getTotalCount" resultType="Long">
SELECT COUNT(NOTICENUM) FROM NOTICE
</select>
// 오라클에서 사용할때
SELECT NUM,TITLE,WRITER,REGDATE,HIT
FROM (SELECT ROWNUM R, N.* FROM
(SELECT * FROM NOTICE ORDER BY NUM DESC) N)
WHERE R BETWEEN #{startRow} AND #{lastRow}
NoticeMapper.java에 등록하고 NoticeService에서 페이지번호를 세팅합니다.
@Autowired
private NoticeMapper noticeMapper;
public List<NoticeVO> getList(Pager pager)throws Exception{
Long totalCount = noticeMapper.getTotalCount();
pager.setRow();
pager.setNum(totalCount);
return noticeMapper.getList(pager);
};
컨트롤러에서 리스트와 페이지정보를 넘겨줍니다.
@GetMapping("notice")
public ModelAndView getBoard(Pager pager)throws Exception {
ModelAndView mv = new ModelAndView();
List<NoticeVO> list = noticeService.getList(pager);
mv.addObject("list",list);
mv.addObject("pager",pager);
mv.setViewName("/board/notice");
return mv;
}
patgination은 bootstrap으로 만들었습니다. 게시글의 상세정보를 보기위해 noticeNum을 넘겨 주는 링크를 제목에 걸어줍니다.
<table class="table table-hover" id="list">
<tr>
<th>번호</th>
<th>제목</th>
<th>작성자</th>
<th>날짜</th>
<th>조회수</th>
</tr>
<c:forEach items="${list}" var="noticeVO">
<tr>
<td>${noticeVO.noticeNum}</td>
<td><a href="./detail?noticeNum=${noticeVO.noticeNum}">${noticeVO.title}</a></td>
<td>${noticeVO.id}</td>
<td>${noticeVO.regDate}</td>
<td>${noticeVO.hit}</td>
</tr>
</c:forEach>
</table>
<div>
<nav aria-label="Page navigation example">
<ul class="pagination">
<li class="page-item" value="${pager.pre}" id="pre">
<a class="page-link" href="./notice?page=${pager.page-1}" aria-label="Previous">
<span aria-hidden="true">«</span>
</a>
</li>
<c:forEach var="i" begin="${pager.startNum}" end="${pager.lastNum}">
<li class="page-item ${pager.page==i? 'active':''}">
<a class="page-link" href="./notice?page=${i}">${i}</a>
</li>
</c:forEach>
<li class="page-item ${pager.next?'':'disabled'}" id="next">
<a class="page-link" href="./notice?page=${pager.page+1}" aria-label="Next">
<span aria-hidden="true">»</span>
</a>
</li>
</ul>
</nav>
</div>