댓글은 View.jsp 게시판 상세보기를 클릭 시 게시판 상세보기가 나오고 그 밑에
댓글이 나오는건데 댓글은 JavaScript에 있는 fn_reply_list() 함수를 호출하고 댓글정보, 댓글 개수를 DB에서 가져온다.
그 뒤론 더보기, 삭제, 수정, 저장 함수를 호출하는 구조
ajax는 많이 쓰니 이해하기!
Controller
@RestController //@Controller + @ResponsBody
public class ReplyController {
@Inject
private IReplyService replyService;
@RequestMapping(value="/reply/replyList", produces = "application/json;charset=UTF-8" )
public Map<String, Object> replyList(ReplySearchVO searchVO) throws Exception {
List<ReplyVO> list = replyService.getReplyListByParent(searchVO);
Map<String, Object> map = new HashMap<String, Object>();
map.put("result", true);
map.put("data", list);
map.put("count", list.size());
return map;
}
// @PostMapping ("/reply/replyRegist")
@RequestMapping(value="/reply/replyRegist", method = RequestMethod.POST)
public Map<String, Object> replyRegist(ReplyVO reply, HttpServletRequest req, HttpSession session )
throws Exception {
reply.setReIp(req.getRemoteAddr());
UserVO user = (UserVO)session.getAttribute("USER_INFO");
reply.setReMemId(user.getUserId());
replyService.registReply(reply);
Map<String, Object> map = new HashMap<String, Object>();
map.put("result", true);
map.put("msg", "정상 등록 되었습니다.");
return map;
}
@RestController : @Controller와 @ResponseBody가 합친 어노테이션. 쓰면 좋은 점은 메소드에 매번 @ResponseBody를 붙여 주지 않아도 된다.
@RequestBody : 요청한 Body 내용을 자바 오브젝트로 변환시켜주는 역할이다. 즉, POST방식의 HTTP 바디 안에 JSON으로 넘어오는 값을 VO에 바인딩한다. 요청하는 곳으로 바로 감. ( Get 요청일 경우 RequestBody를 사용 못함)
@ResponseBody : VO 객체를 JSON으로 바꿔서 HTTP body에 담는 스프링 @
메소드의 리턴 값을 Response의 body에 담는 역할
reply.setReIp(req.getRemoteAddr());
UserVO user = (UserVO)session.getAttribute("USER_INFO");
reply.setReMemId(user.getUserId());
:: 로그인 한 후 댓글을 쓸 수 있고, 댓글 쓴 사람은 자기 댓글만 수정,삭제 할 수 있게 하기 위해 User 정보를 가져온다.
@RequestMapping(value="/reply/replyModify")
public Map<String, Object> replyModify(ReplyVO reply, HttpSession session ) throws Exception {
UserVO user = (UserVO)session.getAttribute("USER_INFO");
reply.setReMemId(user.getUserId());
Map<String, Object> map = new HashMap<String, Object>();
try {
replyService.modifyReply(reply);
map.put("result", true);
map.put("msg", "수정 되었습니다.");
return map;
} catch (BizNotFoundException e) {
map.put("result", false);
map.put("msg", "글이 존재하지 않습니다.");
return map;
} catch (BizAccessFailException e) {
map.put("result", false);
map.put("msg", "접근에 실패했습니다.");
return map;
}
}
@RequestMapping(value="/reply/replyDelete")
public Map<String, Object> replyDelete(ReplyVO reply, HttpSession session ) throws Exception {
UserVO user = (UserVO)session.getAttribute("USER_INFO");
reply.setReMemId(user.getUserId());
Map<String, Object> map = new HashMap<String, Object>();
try {
replyService.removeReply(reply);
map.put("result", true);
map.put("msg", "삭제 되었습니다.");
return map;
} catch (BizNotFoundException e) {
map.put("result", false);
map.put("msg", "글이 존재하지 않습니다.");
return map;
} catch (BizAccessFailException e) {
map.put("result", false);
map.put("msg", "접근에 실패했습니다.");
return map;
}
}
}
::Key값을 string으로 value 값을 Object형으로 put 메소드를 통해 입력 할 수 있다.
view.jsp
<!-- START : 댓글 관련 영역 -->
<div class="container">
<!-- START : 댓글 입력 영역 -->
<div class="panel panel-default">
<div class="panel-body form-horizontal">
<form name="frm_reply" action="<c:url value='/reply/replyRegist' />"
method="post" onclick="return false;">
<input type="hidden" name="reParentNo" value="${board.boNo}">
<input type="hidden" name="reCategory" value="FREE">
<div class="form-group">
<label class="col-sm-2 control-label">댓글</label>
<div class="col-sm-8">
<textarea rows="2" name="reContent" class="form-control" ></textarea>
</div>
<div class="col-sm-2">
<button id="btn_reply_regist" type="button" class="btn btn-sm btn-info">등록</button>
</div>
</div>
</form>
</div>
</div>
<!-- END : 댓글 입력 영역 -->
<!-- START : 댓글 목록 영역-->
<div id="id_reply_list_area"></div>
<!-- END : 댓글 목록 영역-->
<!-- START : 더보기 버튼 영역-->
<div class="row text-center" id="id_reply_list_more">
<button id="btn_reply_list_more">
<span class="glyphicon glyphicon-chevron-down" aria-hidden="true"></span>
더보기
</button>
</div>
<!-- END : 더보기 버튼 영역-->
<!-- START : 댓글 수정용 Modal-->
<div class="modal fade" id="id_reply_edit_modal" role="dialog">
<div class="modal-dialog">
<!-- Modal content-->
<div class="modal-content">
<form name="frm_reply_edit"
action="<c:url value='/reply/replyModify' />" method="post"
onclick="return false;">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal">×</button>
<h4 class="modal-title">댓글수정</h4>
</div>
<div class="modal-body">
<input type="text" name="reNo" value="">
<textarea rows="3" name="reContent" class="form-control"></textarea>
</div>
<div class="modal-footer">
<button id="btn_reply_modify" type="button"
class="btn btn-sm btn-info">저장</button>
<button type="button" class="btn btn-default btn-sm"
data-dismiss="modal">닫기</button>
</div>
</form>
</div>
</div>
</div>
<!-- END : 댓글 수정용 Modal-->
</div> <!-- END : 댓글 container-->
:: 더보기, 수정, 삭제, 등록만 해도 이정도다;;; ㄷㄷ
그리고 자바스크립트 부분 (ajax 이해하기)
<!-- START : 댓글 목록 영역-->
<div id="id_reply_list_area"></div>
<!-- END : 댓글 목록 영역-->
<script type="text/javascript">
<!-- START : 댓글 처리 스크립트 -->
<!--페이지마다 댓글 보여줘야한다 -->
var curPage = 1;
var rowSizePerPage = 10 ;
var parentNo = ${board.boNo};
var sendParam = {"curPage" : curPage
, "rowSizePerPage" : rowSizePerPage
, "reCategory" : "FREE"
, "reParentNo": ${board.boNo} };
<!--댓글목록영역 -->
var $reply_list_area = $('#id_reply_list_area');
// 댓글목록을 구하는 함수
function fn_reply_list(){
$.ajax({
url : "<c:url value = '/reply/replyList' />",
// 요청 페이지 URL정보
dataType : 'json', // 서버로부터 전달받을 데이터 유형 (html, xml, json, script)
data : sendParam, // 서버에 전송할 파라미터 정보
success : function(data) {
console.log('data.result', data.result);
console.log('data.count', data.count);
console.log('data.data', data.data);
$.each(data.data,function(i,el){
console.log(i,el);
var str = '<div class="row" >';
str += '<div class="col-sm-2 text-right" >'+el.reMemName+'</div>';
str += '<div class="col-sm-6"><pre>'+el.reContent+'</pre></div>';
str += '<div class="col-sm-2" >'+el.reRegDate+'</div>';
str += '<div class="col-sm-2">';
//로그인 사용자 + 댓글 등록자
if('${sessionScope.USER_INFO.userId}' == el.reMemId){
str += '<button name="btn_reply_edit" type="button"
class=" btn btn-sm btn-info" data-re-no="'+el.reNo+'">수정</button>';
str +='<button name="btn_reply_delete" type="button"
class="btn btn-sm btn-danger" data-re-no="'+el.reNo+'">삭제</button>';
}
str +='</div>';
str +='</div>';
$('#id_reply_list_area').append(str); //append
}); //.each
if(data.count < sendParam.rowSizePerPage){
$('#id_reply_list_more').hide();
}
}, // 요청에 성공한 경우 호출되는 함수 (data, status, xhr )
error : function(xhr,status,error) {
console.log('xhr',xhr);
console.log('status',status);
console.log('error',error);
}
// 요청에 실패한 경우 호출되는 함수 (xhr, status, error)
}); // ajax
} // fn_reply_list
데이터 유형은 json , 서버에 전송할 파라미터 정보는 sendParam
성공 할 시 function(data) 함수를 실행하고
$.each는 JQuery를 사용해 배열을 관리하고자 할 때 each() 메서드를 사용 할 수 있다.
매개 변수로 받은 것을 사용해 for in 반복문과 같이 배열이나 객체의 요소를 검사 할 수 있는 메서드.
$.each(data.data,function(i,el)
컨트롤러단을 보면 data는 list다. list와 익명 i,el
회원이름 + 글 내용 + 작성일
if('${sessionScope.USER_INFO.userId}' == el.reMemId){
str += '<button name="btn_reply_edit"
type="button" class=" btn btn-sm btn-info" data-re-no="'+el.reNo+'">수정</button>';
str +='<button name="btn_reply_delete"
type="button" class="btn btn-sm btn-danger" data-re-no="'+el.reNo+'">삭제</button>';
}
if 문은 접속한 아이디와 일치시 수정,삭제가 나타나게 함. (자기 댓글만 수정,삭제 가능)
수정
$(document).ready(function() {
// 수정버튼 클릭
$('#id_reply_list_area').on('click','button[name=btn_reply_edit]',function(e){
/* $('#id_reply_edit_modal').modal('show') */
$btn = $(this);
$('form[name=frm_reply_edit] ').find('input[name=reNo]').val($btn.data('re-no') );
$('form[name=frm_reply_edit] ').find('textarea[name=reContent]').val($btn.closest('div.row').find('pre').text() );
$('#id_reply_edit_modal').modal('show');
}); // btn_reply_edit.click
// 모달창의 (수정)저장버튼 btn_reply_modify 클릭
$("#btn_reply_modify").click(function(e) {
var params = $('form[name =frm_reply_edit]').serialize();
// #btn_reply_regist.click
$.ajax({
type :"POST", // 전송 방식 설정 (Defaut : GET)
url : "<c:url value = '/reply/replyModify' />",
dataType : 'json', // 서버로부터 전달받을 데이터 유형 (html, xml, json, script)
data : params, // 서버에 전송할 파라미터 정보
success : function(data) {
if(data.result) {
// 성공
reNo = $('form[name=frm_reply_edit]').find('input[name=reNo]').val();
reContent = $('form[name=frm_reply_edit] ').find('textarea[name=reContent]').val();
$('button[data-re-no=' + reNo + ']').closest('div.row').find('pre').text(reContent);
}else{
alert(data.msg);
}
$('#id_reply_edit_modal').modal('hide');
}, // 요청에 성공한 경우 호출되는 함수 (data, status, xhr )
error : function(xhr,status,error) {
console.log('xhr',xhr);
console.log('status',status);
console.log('error',error);
}
// 요청에 실패한 경우 호출되는 함수 (xhr, status, error)
}); // ajax
}); //("#btn_reply_regist").click
url : "<c:url value = '/reply/replyModify' />",
<c:url : URL에 자동으로 Context Path를 붙여줍니다. 편리한게 Context를 변경을 하더라도 URL을 수정 할 필요 X
if(data.result) {
// 성공
reNo = $('form[name=frm_reply_edit]').find('input[name=reNo]').val();
//reply_edit 중 input name이 reNo인 것을 찾아 값 넣기
reContent = $('form[name=frm_reply_edit] ').find('textarea[name=reContent]').val();
//reply_edit 중 input name이 reContent인 것을 찾아 값 넣기
$('button[data-re-no=' + reNo + ']').closest('div.row').find('pre').text(reContent);
}else{
alert(data.msg);
}
.closest('div.row') : 선택한 요소를 포함하면서 가장 가까운 상위 요소를 선택
삭제
// 삭제버튼 클릭
$('#id_reply_list_area').on('click','button[name=btn_reply_delete]',function(e){
$btn = $(this);
var params = {"reNo" : $btn.data('re-no')};
res = confirm("정말로 삭제하시겠습니까?");
if(res) {
$.ajax({
type : "POST",
url : "<c:url value = '/reply/replyDelete' />",
dataType : "json",
data : params,
success : function(data) {
if(data.result){
reContent = $('form[name=frm_reply_edit] ').find('textarea[name=reContent]').val();
$('button[data-re-no=' + del + ']').closest('div.row').find('pre').text(reContent);
}
$("")
}
});
}
}); // btn_reply_delete.click
더보기
// 더보기 버튼 클릭
$('#btn_reply_list_more').click(function(e) {
sendParam.curPage =sendParam.curPage + 1;
fn_reply_list();
}); // #btn_reply_list_more.click
등록
// 등록버튼 클릭(아작스)
$("#btn_reply_regist").click(function(e) {
var params = $('form[name =frm_reply]').serialize();
// #btn_reply_regist.click
$.ajax({
type :"POST", // 전송 방식 설정 (Defaut : GET)
url : "<c:url value = '/reply/replyRegist' />",
// 요청 페이지 URL정보
dataType : 'json', // 서버로부터 전달받을 데이터 유형 (html, xml, json, script)
data : params, // 서버에 전송할 파라미터 정보
success : function(data) {
alert(data);
}, // 요청에 성공한 경우 호출되는 함수 (data, status, xhr )
error : function() {
}
// 요청에 실패한 경우 호출되는 함수 (xhr, status, error)
}); // ajax
}); //("#btn_reply_regist").click
// 4. 초기화 함수 호출
fn_reply_list();
}); // ready
</script>