회원가입, 로그인, 게시판 백엔드 실습( 댓글 리스트 , pagenation )
댓글 리스트 , pagenation 작성하기
: get 방식으로 데이터베이스에 있는 데이터를 조회하고 JavaScript로 데이터를 브라우저에 나타낼 것이다.
1) JavaScript 작성
$(document).ready(function(){
var board_noValue=$("input[name='board_no']").val();
var pageValue=1;
// detail.jsp가 시작되자마자 댓글목록리스트(list) 함수를 호출
list({board_no:board_noValue,page:pageValue});
// 페이지네이션의 페이지를 클릭하면 해당 페이지의 댓글을 호출
$("#replyPage").on("click","li a",function(e){
alert("aaa")
e.preventDefault();
var board_noValue=$("input[name='board_no']").val();
var pageValue = $(this).attr("href");
list({board_no:board_noValue,page:pageValue});
})
})
// list 함수 호출
function list(param){
var board_no = param.board_no;
var page = param.page;
$.getJSON("/replies/"+board_no+"/"+page+".json",function(data){
var str="";
for(var i=0;i<data.list.length;i++){
str+="<li>"+data.list[i].id+"</li>"
str+="<li><textarea id='replycontent"+data.list[i].rno+"'>"+data.list[i].content+"</textarea></li>"
str+="<li>"
str+="<input class='update' type='button' value='수정' data-rno="+data.list[i].rno+">"
str+="<input class='remove' type='button' value='삭제' data-rno="+data.list[i].rno+">"
str+="</li>"
}
$("#replyUL").html(str);
// 페이지네이션 함수 호출
showReplyPage(data.replycnt,page);
});
}
// 페이지네이션 호출
function showReplyPage(replycnt,pageNum){
var endNum = Math.ceil(pageNum/10.0)*10;
var startNum = endNum-9
var prev=startNum !=1;
var next=false;
if(endNum * 10 >= replycnt){
endNum = Math.ceil(replycnt/10.0)
}
if(endNum * 10 < replycnt){
next=true;
}
var str="<ul>";
if(prev){
str+="<li><a href='"+(startNum-1)+"'>Previous</a></li>";
}
for(var i=startNum ; i<=endNum ; i++){
str+="<li><a href='"+i+"'>"+i+"</a></li>"
}
if(next){
str+="<li><a href='"+(endNum+1)+"'>Next</a></li>";
}
str+="</ul><div>"
$("#replyPage").html(str);
}
- 처음 렌더링이 시작 될 때 현재 게시글 번호인 board_no를 읽어오고 pageValue를 1로 저장하고 list 함수를 호출한다.
- list 함수는 JSON 형태로 해당 게시물에 대한 정보를 호출하고, 호출한 데이터를 for 문을 활용해서 HTML 문법으로 작성한다.
- 작성된 HTML 문법을 다음과 같은 형태로 jsp파일 내부의 원하는 위치에 배치한다.
$("#replyUL").html(str);
- 페이지네이션은 a 태그로 작성되었기 때문에, 클릭 이벤트로 선언할 때 e.preventDefault를 선언해 a 태그의 이동 기능을 제한한다.
또한 a 태그의 href 의 속성을 pageValue에 저장하고 list를 호출함으로서 a 태그 클릭 시 해당 page에 속하는 댓글들을 불러온다.
- 페이지네이션의 호출은 현재 페이지 넘버를 올림함으로서 endNum을 정의하고 startNum = endNum-9를 하는 것으로
나타날 페이지의 숫자의 일의 자릿 수가 1 ~ 0 까지 배치될 수 있도록 한다.
- endNum * 10 과 replycnt ( 댓글의 총 갯수 ) 를 비교해서
댓글의 총 갯수가 적을 경우 next 버튼이 생성되지 않도록 next = false인 상태로 두고
댓글의 총 갯수가 많을 경우 next 버튼이 생성되도록 next = true 선언한다.
- 만일 페이지의 총 갯수가 10개 이하라면, startNum 은 항상 1이기 때문에, 이전 버튼을 생성하지 않고
총 갯수가 11개 이상이라면, startNum != 1 이 참이기 때문엥 이전 버튼을 생성한다.
CriteriaVO.java는 다음과 같다
public class CriteriaVO {
private int pageNum;
private int amount;
private String keyword;
private String type;
//생성자
public CriteriaVO() {
this(1,10);
}
public CriteriaVO(int pageNum, int amount) {
this.pageNum = pageNum;
this.amount = amount;
}
필드의 getter 와 setter
}
2) Controller 작성
@Controller
public class ReplyController {
@Autowired
ReplyService rs;
// 댓글 목록 리스트
@RequestMapping(value = "/replies/{board_no}/{page}", method = RequestMethod.GET)
public ResponseEntity <ReplyPageVO> getList(@PathVariable("page") int page,@PathVariable("board_no") int board_no){
CriteriaVO cri = new CriteriaVO(page,10);
return new ResponseEntity<>(rs.list(cri, board_no),HttpStatus.OK);
}
}
- /replies/{board_no}/{page} 으로 부터 Json 데이터를 호출하고 page , board_no 파라미터를 매개변수로 보낸다.
이 파라미터는 (현재 페이지-1) * 10 ~ (현재 페이지) * 10 사이의 pno 데이터들을 내림차순으로 호출하는데 사용된다.
- CriteriaVO 는 기본적으로 (1,10)으로 생성자가 선언되어 있지만, (page,10)으로 다시 생성해서 호출한다.
3) Service , ServiceImpl 작성
public interface ReplyService {
// 댓글 목록 리스트를 위한 설계
//public ArrayList<ReplyVO> list(int bno);
public ReplyPageVO list(CriteriaVO cri, int board_no);
}
@Service
public class ReplyServiceImpl implements ReplyService{
@Autowired
ReplyMapper rm;
// 댓글 목록 리스트를 위한 구현
public ReplyPageVO list(CriteriaVO cri,int board_no){
return new ReplyPageVO(rm.rpycnt(board_no),rm.list(cri,board_no));
}
}
- ServiceImpl에서 전체 댓글 갯수를 읽어오는 rm.rpycnt()와, 댓글의 정보를 가져오는 rm.list() 함수를 실행한다.
4) Mapper , Mapper.xml
public interface ReplyMapper {
// 댓글 목록리스트를 위한 구현
//public ArrayList<ReplyVO> list(int bno);
public ArrayList<ReplyVO> list(@Param("cri") CriteriaVO cri,@Param("board_no") int board_no);
}
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="hjm.portfolio.mapper.ReplyMapper">
<select id="list" resultType="hjm.portfolio.model.ReplyVO">
select *
from(
select @rownum:=@rownum+1 rownum, b.*
from port_reply b, (select @rownum:=0) as tmp
where board_no=#{board_no}
order by board_no desc
) as boardlist
<![CDATA[
where rownum > (#{cri.pageNum}-1)*#{cri.amount} and rownum <= #{cri.pageNum}*#{cri.amount}
]]>
</select>
<select id="rpycnt" resultType="int">
select count(*) from port_reply where board_no=#{board_no}
</select>
</mapper>
** Mapper 를 통해 mySql 에서 사용할 변수가 여러개일 경우 @param("변수명") 을 꼭 선언해줘야한다.
- Mapper.xml의 list는 현재 페이지를 기준으로 ( 현재페이지 -1 ) * 10 ~ ( 현재페이지 ) * 10 사이의 rno를 가진 데이터를 호출한다.
- rpycnt는 현재 게시글의 board_no와 같은 값을 가진 모든 댓글 데이터의 갯수를 호출한다.
5) 결과