Spring

회원가입, 로그인, 게시판 백엔드 실습( 댓글 리스트 , pagenation )

hojomu 2023. 4. 6. 15:03

댓글 리스트 , 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) 결과