
DB테이블
- r_depth = 댓글의 깊이( 댓글 0 , 답글 1 로 구별하기 위해서)
- r_group = 댓글이 속한 번호
<댓글부분>
Controller
- @RestController을 이용한 방식입니다.
이방식은 @Controller 사용하는 대신 @RequestController을 사용해야 하기 때문에 새로운 클래스를 생성하였습니다.
- 게시판 상세보기 메서드에 @ModelAttribute("replyVO")ReplyVO replyVO 어노테이션을 추가해서 jsp에서 사용하기 위해서 선언을 하였다
// 댓글목록
@Override
@RequestMapping(value = "/getReplyList.do", method = RequestMethod.POST)
public List<ReplyVO> getReplyList(@RequestParam("bno") int bno) throws Exception {
boardService.UpdateReplyCount(bno);
return replyService.getReplyList(bno);
}
//작성
@Override
@RequestMapping(value = "/addReply.do", method = RequestMethod.POST)
public Map<String, Object> addReply(@RequestBody ReplyVO replyVO) throws Exception {
Map<String, Object> result = new HashMap<>();
try {
replyService.addReply(replyVO);
result.put("status", "OK");
} catch (Exception e) {
e.printStackTrace();
result.put("status", "false");
}
return result;
}
//수정
@Override
@RequestMapping(value = "/updateReply.do", method = RequestMethod.POST)
public Map<String, Object> updateReply(@RequestBody ReplyVO replyVO) throws Exception {
Map<String, Object> result = new HashMap<>();
try {
replyService.updateReply(replyVO);
result.put("status", "ok");
} catch (Exception e) {
e.printStackTrace();
result.put("status", "false");
}
return result;
}
//삭제
@Override
@RequestMapping(value="deleteReply.do" , method=RequestMethod.POST)
public Map<String,Object>deleteReply(@RequestParam("rno")int rno)throws Exception{
Map<String,Object>result = new HashMap<>();
try {
replyService.deleteReply(rno);
result.put("status", "ok");
}catch(Exception e) {
e.printStackTrace();
result.put("status", "false");
}
return result;
}
Service
//댓글리스트
@Override
public List<ReplyVO> getReplyList(int bno)throws Exception{
return replyDAO.getReplyList(bno);
}
//댓글작성
@Override
public int addReply(ReplyVO replyVO)throws Exception{
return replyDAO.addReply(replyVO);
}
//댓글수정
@Override
public int updateReply(ReplyVO replyVO)throws Exception{
return replyDAO.updateReply(replyVO);
}
//댓글삭제
@Override
public int deleteReply(int rno)throws Exception{
return replyDAO.deleteReply(rno);
}
DAO
// 댓글 리스트
@Override
public List<ReplyVO> getReplyList(int bno) throws DataAccessException {
return session.selectList("mapper.reply.getReplyList", bno);
}
// 댓글 작성
@Override
public int addReply(ReplyVO replyVO) throws DataAccessException {
int result = session.insert("mapper.reply.addReply", replyVO);
//댓글이 작성되면 댓글의 그룹번호 r_group를 rno와 같게 값을 넣기위해 선언
//답글이 달리면 답글을 작성한 댓글과 묶기 위해
if(result == 1) {
int check_update = session.update("mapper.reply.Re_group",replyVO);
replyVO.setR_group(check_update);
}
return result;
}
// 댓글 수정
@Override
public int updateReply(ReplyVO replyVO) throws DataAccessException {
return session.update("mapper.reply.updateReply", replyVO);
}
// 댓글 삭제
@Override
public int deleteReply(int rno) throws DataAccessException {
return session.delete("mapper.reply.deleteReply", rno);
}
mapper(Oracle)
//목록
<select id="getReplyList" resultMap="ReplyResult">
<![CDATA[
select *
from b_reply
where bno = #{bno}
order by r_group asc , r_depth asc, rno desc
]]>
</select>
//작성
<insert id="addReply" parameterType="ReplyVO">
<selectKey resultType="int" keyProperty="rno" order="BEFORE">
select seq_reply.nextval from dual
</selectKey>
<![CDATA[
insert into b_reply(rno, bno, content, writer,r_group)
values(#{rno},#{bno},#{content},#{writer},#{r_group})
]]>
</insert>
//수정
<update id="updateReply" parameterType="ReplyVO">
<![CDATA[
update b_reply
set content = #{content}
where rno = #{rno}
]]>
</update>
//삭제
<delete id="deleteReply" parameterType="int">
<![CDATA[
delete from b_reply
where rno = #{rno}
]]>
</delete>
<!-- 부모글 r_group 를 rno와 같게 셋팅 -->
<update id="Re_group" parameterType="ReplyVO">
<![CDATA[
update b_reply
set r_group = rno
where r_group != rno
and r_depth = 0
]]>
</update>
<답글부분>
Controller
// 답글 작성
@RequestMapping(value = "write_rereply.do", method = RequestMethod.POST)
public Map<String,Object> write_rereply(@RequestBody ReplyVO replyVO)throws Exception {
Map<String,Object>result = new HashMap<>();
//댓글에 답글을 작성할 때 r_group를 댓글 r_group를 가져오기위해 변수를 선언하여 get,set을 하였음.
//그리고 r_depth 즉 답글이라는 것을 알기 위해 r_depth를 1로 설정하여 답글이 작성되면 자동적으로 1이 데이터값에 들어가기위해 선언
int rno = replyVO.getRno();
replyVO.setR_group(rno);
replyVO.setR_depth(1);
try {
replyService.WriteReReply(replyVO);
result.put("status", "ok");
}catch(Exception e) {
e.printStackTrace();
result.put("status", "false");
}
return result;
}
//답글 수정
@RequestMapping(value = "update_rereply.do", method = RequestMethod.POST)
public Map<String,Object> update_rereply(@RequestBody ReplyVO replyVO)throws Exception {
Map<String,Object>result = new HashMap<>();
//답글 수정을 하기위해 r_group, r_depth를 get, set 하여 일반 댓글과 구분지어 수정이 되게 하였음
int r_group = replyVO.getR_group();
int r_depth = replyVO.getR_depth();
replyVO.setR_depth(r_depth);
replyVO.setR_group(r_group);
try {
replyService.UpdateReReply(replyVO);
result.put("status", "ok");
}catch(Exception e) {
e.printStackTrace();
result.put("status", "false");
}
return result;
}
Service
//답글 등록
@Override
public int WriteReReply(ReplyVO replyVO)throws Exception{
return replyDAO.WriteReReply(replyVO);
}
//답글 수정
@Override
public int UpdateReReply(ReplyVO replyVO)throws Exception{
return replyDAO.updateReply(replyVO);
}
DAO
// 답글 작성
@Override
public int WriteReReply(ReplyVO replyVO) throws DataAccessException{
return session.insert("mapper.reply.ReRePly_write", replyVO);
}
//답글 수정
@Override
public int UpdateReReply(ReplyVO replyVO) throws DataAccessException {
return session.update("mapper.reply.ReReply_update", replyVO);
}
Mapper(Oracle)
<!-- 답글 작성 -->
<insert id="ReRePly_write" parameterType="ReplyVO">
<selectKey resultType="int" keyProperty="rno" order="BEFORE">
select seq_reply.nextval from dual
</selectKey>
<![CDATA[
insert into b_reply(rno, bno, content, writer, r_depth,r_group)
values(#{rno},#{bno},#{content},#{writer},#{r_depth},#{r_group})
]]>
</insert>
//수정
<update id="ReReply_update" parameterType="ReplyVO">
<![CDATA[
update b_reply
set content = #{content}
where rno = #{rno} and r_depth = #{r_depth}
]]>
</update>
JSP
//목록 부분..
<div class="Reply" style="padding-top: 10px">
<h3 class= "ReplyList">댓글</h3>
<div id="replyList"></div>
</div>
//작성부분..
<br>
<div class="my-3 p-3 bg-white rounded shadow-sm" style="padding-top: 10px">
<form:form name="form" id="form" role="form" modelAttribute="replyVO" method="post">
<form:hidden path="bno" id="bno"/>
<div class="col-sm-2">
<form:input path="writer" class="form-control" id="writer" value="${memberVO.id }" type="hidden" />
</div>
<div class="row">
<div class="col-sm-10">
<form:textarea path="content" id="content" class="form-control" rows="3" placeholder="댓글을 입력해 주세요" />
<c:if test="${not empty memberVO}">
<button type="button"id="btnReplyAdd">등록</button>
</c:if>
</div>
</div>
</form:form>
</div>
Script
$(document).ready(function(){ getReplyList(); }):
이 부분은 페이자가 완전히 로딩되면 호출되는 이벤트 부분이다. 따라서 조회 페이지가 로딩이 되고 나면 getReplyList()
함수를 싱행하게 된다
//댓글 리스트
$(document).ready(function(){
getReplyList();
});
function getReplyList(){
var url = "${Path}/reply/getReplyList.do";
var paramData = {"bno": "${board.bno}"};
var writer = $('#writer').val();
var id = '${memberVO.id}';
$.ajax({
type:'POST',
url:url,
data:paramData,
dataType:'json',
success: function(data){
//console.log("댓글 리스트 받아졌나?");
var htmls = "";
for(const i in data){//list를 받기위해 for문 사용
let rno = data[i].rno;
let bno = data[i].bno;
let content = data[i].content;
let writer = data[i].writer;
let reg_date = data[i].reg_date;
let r_depth = data[i].r_depth;
let r_group = data[i].r_group;
if(r_depth == 0){ //댓글
htmls += '<div class="media text-muted pt-3" id="rno' + rno + '">';
htmls += '<p class="media-body pb-3 mb-0 small lh-125 border-bottom horder-gray">';
htmls += '<span class="d-block">';
htmls += '<strong class="text-gray-dark">' + writer + '</strong>';
htmls += ' '+ reg_date;
htmls += '<br>'
htmls += content;
htmls += '</span>';
if(id != ""){ //로그인시 답글 버튼 나오게하기
htmls += '<span style="padding-left: 7px; font-size: 9pt">';
htmls += " <a href='#' class='write_reply_start' data-bs-toggle='collapse' data-bs-target='#re_reply"+ rno +"' aria-expanded='false' aria-controls='collapseExample'>답글</a>";
htmls += '</span>';
}
}else{ //답글
htmls += "<div class='rereply-content" + rno + " col-7'>";
htmls += "<div>";
htmls += '<span>';
htmls += '<b> ⤷ ' + writer + '</b>';
htmls += ' '+ reg_date;
htmls += '</span>';
htmls += '<br>';
htmls += '<span>';
htmls += ' '+content;
htmls += '</span>';
}
//---------------
if(id != ''){//로그인 및 작성자와 id가 동일시 수정 및 삭제버튼 나오게
if(id == writer){
htmls += '<span style="padding-left: 7px; font-size: 9pt">';
htmls += " <a href='#' class='update_reply_start' data-bs-toggle='collapse' data-bs-target='#rno"+ rno +"' aria-expanded='false' aria-controls='collapseExample'>수정</a>";
htmls += ' ';
htmls += '<a href="javascript:void(0)" onclick="fn_deleteReply(' + rno + ',\'' + writer + '\')" >삭제</a>';
htmls += '</span>';
}
}
//---------------
//답글 입력란
htmls += "<div class='collapse rereply_write' id='re_reply"+ rno +"'>";
htmls += "<div class='col-1'>"
htmls += "</div>";
htmls += "<div class='col-1'>"
htmls +="<input class ='w-100 input_writer_div form-control' id='input_writer"+ rno +"' value='${memberVO.id}' type='hidden'>";
htmls += "</div>";
htmls += "<div class='col-7'>"
htmls +="<input class ='w-100 input_rereply_div form-control' id='input_rereply"+ rno +"' type='text' placeholder = '댓글을 입력하세요.'>";
htmls += "</div>";
htmls += "<div class='col-3'>"
//동적으로 넣은 html 태그에서 발생하는 이벤트는 동적으로 처리해줘야 함
//동적으로 넣은 html 태그에서 발생하는 click 이벤트는 html 태그 안에서 onclick 처리하면 안되고 , jquery에서 클래스명 이나 id값을 받아서 처리하도록 해야함
htmls += "<button type='button' class='btn btn-success mb-1 write_rereply' rno='" + rno +"' bno= '" + bno +"'>답글 달기</button>";
htmls += "</div>";
htmls += "</div>";
//-------------------------------------------------
//수정 html
htmls += "<div class='collapse reply_update' id='rno"+ rno +"'>";
htmls += "<div class='col-1'>"
htmls += "</div>";
htmls += "<div class='col-1'>"
htmls +="<input class ='w-100 input_writer_div form-control' id='input_writer"+ rno +"' value='${memberVO.id}' type='hidden'>";
htmls += "</div>";
htmls += "<div class='col-7'>"
htmls +="<input class ='w-100 input_content_div form-control' id='input_content"+ rno +"' type='text'>";
htmls += "</div>";
htmls += "<div class='col-3'>"
htmls += "<button type='button' class='btn btn-success mb-1 update_reply' rno='" + rno +"' bno= '" + bno +"'>수정 하기</button>";
htmls += "<button type='button' class='btn' name='list' >취소</button>"
htmls += "</div>";
htmls += "</div>";
}//end for
$("#replyList").html(htmls);
//답글 작성 후 답글 달기버튼 를 click event를 아래처럼 jquery로 처리
$('button.btn.btn-success.mb-1.write_rereply').on('click',function(){
WriteReReply($(this).attr('bno'), $(this).attr('rno'));
});
//--------------답글 저장 end
$('button.btn.btn-success.mb-1.update_reply').on('click',function(){
if($(this).attr('r_depth') == 0){
UpdateReply($(this).attr('rno'), $(this).attr('bno'));
}else{
UpdateReReply($(this).attr('rno'), $(this).attr('bno'), $(this).attr('r_depth'));
}
});
}//ajax success end
});//end ajax
}
<댓글부분>
//댓글 저장
$(document).on('click','#btnReplyAdd', function(){
var Content = $('#content').val();
var Writer = $('#writer').val();
if(Content == ""){
alert("내용을 입력해주세요.");
return ;
}
var paramData = JSON.stringify(
{"content": Content
,"writer" : Writer
,"bno" : '${board.bno}'
});
var headers = {"Content-Type":"application/json"
,"X-HTTP-Method-Override":"POST"};
$.ajax({
url:"${Path}/reply/addReply.do"
,headers : headers
,data : paramData
,type : 'POST'
,dataType : 'text'
,success:function(result){
window.location.reload();
getReplyList();
}
,error:function(error){
console.log("에러:" + error);
}
});//end ajax
});//end on
//댓글 수정
UpdateReply = function(rno, bno) {
var writer = $('#input_writer' + rno).val();
var content = $('#input_content' + rno).val();
var paramData = JSON.stringify({
"bno" : bno,
"rno" : rno,
"content" : content,
"writer" : writer
});
var headers = {
"Content-Type" : "application/json",
"X-HTTP-Method-Override" : "POST"
};
$.ajax({
url : "${Path}/reply/updateReply.do",
headers : headers,
data : paramData,
type : 'POST',
dataType : 'text',
success : function(result) {
console.log(result);
getReplyList();
},
error : function(error) {
console.log("에러:" + error);
}
});//end ajax
}
//댓글 삭제
function fn_deleteReply(rno){
var DelConfirm = confirm('댓글을 삭제 하시겠습니까?');
var paramData = {"rno" : rno};
if(DelConfirm){
alert("댓글이 삭제 되었습니다.");
}else{
alert("댓글 삭제가 취소 되었습니다.");
return;
}
$.ajax({
url:"${Path}/reply/deleteReply.do"
,data : paramData
,type : 'POST'
,dataType : 'text'
,success:function(result){
getReplyList();
}
,error: function(error){
console.log("에러:" + error);
}
});
}
<답글부분>
//-----------------------------------------------
//답글 달기 버튼 클릭시 실행
WriteReReply = function(bno, rno){
var writer = $('#input_writer' + rno).val();
var content = $('#input_rereply' + rno).val();
content = content.trim();
var paramData = JSON.stringify({
"bno" : bno,
"rno" : rno,
"content" : content,
"writer" : writer
});
var headers = {
"Content-Type" : "application/json",
"X-HTTP-Method-Override" : "POST"
};
if(content == ""){
alert("답글을 입력해주세요.");
}else{
$('#input_rereply' + rno).val("");//입력란 비우기
$.ajax({
url : "${Path}/reply/write_rereply.do"
,headers : headers
,data : paramData
,type : 'POST'
,dataType : 'text'
,success:function(result){
getReplyList();
},
error:function(error){
console.log("에러:"+ error);
}
});//end ajax
};
};
//답글 수정
UpdateReReply = function fn_updateReply(rno, bno, r_depth) {
var writer = $('#input_writer' + rno).val();
var content = $('#input_content' + rno).val();
var paramData = JSON.stringify({
"bno" : bno,
"rno" : rno,
"r_depth" : r_depth,
"content" : content,
"writer" : writer
});
var headers = {
"Content-Type" : "application/json",
"X-HTTP-Method-Override" : "POST"
};
$.ajax({
url : "${Path}/reply/update_rereply.do",
headers : headers,
data : paramData,
type : 'POST',
dataType : 'text',
success : function(result) {
console.log(result);
getReplyList();
},
error : function(error) {
console.log("에러:" + error);
}
});//end ajax
}
//동적 html에서는 onclick을 사용을 못하기에 jquery로 click버튼을 만듬
$(document).ready(function(){
$(document).on("click", "button[name='list']", function(){
getReplyList();
});
});
'Spring > Study' 카테고리의 다른 글
[Spring]게시판 상단 고정 공지사항 구현 (0) | 2022.10.04 |
---|---|
[Spring]Ajax를 이용한 좋아요 기능 구현 (0) | 2022.09.25 |
[Spring]비밀번호 인코딩(BCryptPasswordEncoder 적용)-로그인 부분 (0) | 2022.05.21 |
[Spring]비밀번호 인코딩(BCryptPasswordEncoder 적용)-회원가입 부분 (0) | 2022.05.21 |
[Spring]로그인 & 로그아웃 구현(2) (0) | 2022.05.21 |