2020년 01월 11일

업데이트:


게시글 삭제

20210111_01

  • DB 상태 변경
    20210111_02



boardView.jsp

<script>
    // 삭제 버튼 이벤트
    $("#deleteBtn").on("click", function(){
        if(confirm("정말 삭제 하시겠습니까?")){
            location.href = "delete.do?no=${board.boardNo}";
        }
    });
</script>



BoardController.java

// 게시글 삭제 Controller ************************************************************************
    else if(command.equals("/delete.do")) {
        // 게시글 번호 얻어오기
        int boardNo = Integer.parseInt(request.getParameter("no"));
        
        // 게시글 삭제(게시글 상태 -> 'N') 비즈니스 로직 수행 후 결과 반환
        int result = service.deleteBoard(boardNo);
    
        // 비즈니스 로직 결과에 따라
        // "댓글 삭제 성공" / "댓글 삭제 실패" 메세지를 전달
        if(result > 0) {
            swalIcon = "success";
            swalTitle = "게시글 삭제 성공";
            path = "list.do?cp=1";
            
            
        }else {
            swalIcon = "error";
            swalTitle = "게시글 삭제 실패";
            path = "view.do?no=" + boardNo;
        }
        // 삭제 성공 시 : 게시글 목록 
        // 삭제 실패 시 : 삭제 시도한 게시글 상세 조회 페이지 redirect
        
        request.getSession().setAttribute("swalIcon", swalIcon);
        request.getSession().setAttribute("swalTitle", swalTitle);
        response.sendRedirect(path);
    }



BoardService.java

/** 게시글 삭제 Service
 * @param boardNo
 * @return result
 * @throws Exception
 */
public int deleteBoard(int boardNo) throws Exception {
	Connection conn = getConnection();
	
	int result = dao.deleteBoard(conn, boardNo);
	
	if(result > 0) commit(conn);
	else rollback(conn);
	
				
	return result;
}



board-query.xml

<!-- 게시글 삭제  -->
<entry key="deleteBoard">
UPDATE BOARD SET
BOARD_STATUS = 'N'
WHERE BOARD_NO = ?
</entry>



BoardDAO.java

/** 게시글 삭제 DAO
    * @param conn
    * @param boardNo
    * @return result
    * @throws Exception
    */
public int deleteBoard(Connection conn, int boardNo) throws Exception {
    int result = 0;
    String query = prop.getProperty("deleteBoard");
    
    try {
        pstmt = conn.prepareStatement(query);
        pstmt.setInt(1, boardNo);
        
        result = pstmt.executeUpdate();
    }finally {
        close(pstmt);
    }

    return result;
}





상세 조회 페이지에 댓글 추가하기

  • 상세 조회 페이지 하단 부분에 댓글 추가
    20210111_04


GSON 사용을 위해 라이브러리 추가하기

20210111_03



reply.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>

<style>
/*댓글*/
.replyWrite>table {
	width: 90%;
	margin-top: 100px;
}

#replyContentArea {
	width: 90%;
}

#replyContentArea > textarea {
	resize: none;
	width: 100%;
}

#replyBtnArea {
	width: 100px;
	text-align: center;
}

.rWriter {
	display: inline-block;
	margin-right: 30px;
	vertical-align: top;
}

.rDate {
	display: inline-block;
	font-size: 0.5em;
	color: gray;
}

#replyListArea {
	list-style-type: none;
}

.rContent, .replyBtnArea {
	height: 100%;
	width: 100%;
}

.replyBtnArea {
	text-align: right;
}

.replyUpdateContent {
	resize: none;
	width: 100%;
}

.reply-row{
	border-top : 1px solid #ccc;
	padding : 15px 0;
}
</style>
<div id="reply-area ">
	<!-- 댓글 작성 부분 -->
	<div class="replyWrite">
		<table align="center">
			<tr>
				<td id="replyContentArea">
					<textArea rows="3" id="replyContent"></textArea>
				</td>
				<td id="replyBtnArea">
					<button class="btn btn-primary" id="addReply">
						댓글<br>등록
					</button>
				</td>
			</tr>
		</table>
	</div>


	<!-- 댓글 출력 부분 -->
	<div class="replyList mt-5 pt-2">
		<ul id="replyListArea">
			
			<!-- 로그인 x 또는 댓글 작성자가 아닌 회원의 화면 -->
			<li class="reply-row">
				<div>
					<p class="rWriter">작성자</p>
					<p class="rDate">작성일 : 2021.01.11 10:30</p>
				</div>
				
				<p class="rContent">댓글 내용1</p>
			</li>

			
			<!-- 로그인한 회원이 댓글 작성자인 경우 -->
			<li class="reply-row">
				<div>
					<p class="rWriter">작성자</p>
					<p class="rDate">작성일 : 2021.01.11 10:30</p>
				</div>

				<p class="rContent">댓글 내용2</p>
				
				<div class="replyBtnArea">
					<button class="btn btn-primary btn-sm ml-1" id="updateReply" onclick="showUpdateReply(2, this)">수정</button>
					<button class="btn btn-primary btn-sm ml-1" id="deleteReply" onclick="deleteReply(2)">삭제</button>
				</div>
			</li>
	
		</ul>
	</div>
</div>



boardView.jsp

상세 조회 페이지에서 댓글이 보이고 싶은 부분에 reply.jsp를 연결한다.

<jsp:include page="reply.jsp"></jsp:include>



SQL 테이블

  • REPLY 테이블
    20210111_05

  • V_REPLY View
    20210111_06

댓글 목록 조회

  • 댓글 목록 조회
    20210111_07

  • DB 확인
    20210111_08



  • reply.jsp
<script>
var loginMemberId = "${loginMember.memberId}";
var parentBoardNo = ${board.boardNo};

// 페이지 로딩 완료 시 댓글 목록 호출
$(function(){
	selectReplyList();
});


// 해당 게시글 댓글 목록 조회 함수(ajax)
function selectReplyList(){
	$.ajax({
		url : "${contextPath}/reply/selectList.do",
		data : {"parentBoardNo" : parentBoardNo },
		type : "post",
		dataType : "JSON",
		success : function(rList){
			//console.log(rList);
			
			$("#replyListArea").html("");
			
			$.each(rList, function(index, item){
				var li = $("<li>").addClass("reply-row");
				var rWriter = $("<p>").addClass("rWriter").text(item.memberId);
				var rDate = $("<p>").addClass("rDate").text("작성일 : " + item.replyCreateDate);
				var div = $("<div>");
				div.append(rWriter).append(rDate);
				
				var rContent = $("<p>").addClass("rContent").html(item.replyContent);
				
				li.append(div).append(rContent);
				
				
				
				// 현재 댓글의 작성자와 로그인한 멤버의 아이디가 같을 때 버튼 추가
				if(item.memberId == loginMemberId){
					// 수정, 삭제 버튼 영역
					var replyBtnArea = $("<div>").addClass("replyBtnArea");
					
					// ** 추가되는 댓글에 onclick 이벤트를 부여하여 버튼 클릭 시 수정, 삭제를 수행할 수 있는 함수를 이벤트 핸들러로 추가함. 
					var showUpdate = $("<button>").addClass("btn btn-primary btn-sm ml-1").text("수정").attr("onclick", "showUpdateReply("+item.replyNo+", this)");
					var deleteReply = $("<button>").addClass("btn btn-primary btn-sm ml-1").text("삭제").attr("onclick", "deleteReply("+item.replyNo+")");
					
					replyBtnArea.append(showUpdate).append(deleteReply);
					
					li.append(replyBtnArea);
					
				}
				
				
				$("#replyListArea").append(li);
			});
		},
		error : function(){
			console.log("댓글 목록 조회 실패");
		}
	});
}
</script>




  • ReplyController.java
// 댓글 목록 조회 Controller *************************************
if(command.equals("/selectList.do")) {
    int parentBoardNo = Integer.parseInt(request.getParameter("parentBoardNo"));
    
    List<Reply> rList = service.selectList(parentBoardNo);
    
    Gson gson = new GsonBuilder().setDateFormat("yyyy년 MM월 dd일 HH:mm").create();
    gson.toJson(rList, response.getWriter()); // rList가 자동으로 gson 형태로 변환된다.
}




  • ReplyService.java
/** 댓글 목록 조회 Service
    * @param parentBoardNo
    * @return rList
    * @throws Exception
    */
public List<Reply> selectList(int parentBoardNo) throws Exception{
    Connection conn = getConnection();
    
    List<Reply> rList = dao.selectList(conn, parentBoardNo);
    close(conn);
    return rList;
}




  • reply-query.xml
<!-- 댓글 목록 조회 -->
<entry key="selectList">
SELECT REPLY_NO, REPLY_CONTENT, REPLY_CREATE_DT, MEMBER_ID
FROM V_REPLY
WHERE REPLY_STATUS = 'Y'
AND PARENT_BOARD_NO = ?
</entry>




  • ReplyDAO.java
/** 댓글 목록 조회 DAO
    * @param conn
    * @param parentBoardNo
    * @return rList
    * @throws Exception
    */
public List<Reply> selectList(Connection conn, int parentBoardNo) throws Exception{
    List<Reply> rList = null;
    
    String query = prop.getProperty("selectList");
    
    try {
        pstmt = conn.prepareStatement(query);
        pstmt.setInt(1,  parentBoardNo);
        
        rset = pstmt.executeQuery();
        
        rList = new ArrayList<Reply>();
        
        while(rset.next()) {
            Reply reply = new Reply();
            reply.setReplyNo(rset.getInt("REPLY_NO"));
            reply.setReplyContent(rset.getString("REPLY_CONTENT"));
            reply.setReplyCreateDate(rset.getTimestamp("REPLY_CREATE_DT"));
            reply.setMemberId(rset.getString("MEMBER_ID"));
            
            rList.add(reply);
        }
    } finally {
        close(rset);
        close(pstmt);
    }
    return rList;
}





댓글 등록

  • 미 로그인 시


    20210111_09
  • 로그인 O, 댓글 내용 미 작성 시
    20210111_08

  • 댓글 작성 성공 시
    20210111_07


  • reply.jsp
<script>
// 댓글 등록 (ajax)

$("#addReply").on("click", function(){
   
   // 댓글 내용을 얻어와서 변수에 저장
   var replyContent = $("#replyContent").val().trim();
   
   // 로그인이 되어있지 않은 경우 == loginMemberId 전역 변수에 저장된 값이 "" 일 경우
   if(loginMemberId == ""){
      alert("로그인 후 이용해 주세요.");
   } else { // 로그인이 되어있는 경우
      
      // 댓글 내용이 작성되어있는지 확인
      if(replyContent.length == 0){
         alert("댓글 작성 후 클릭해주세요.");
      } else { // 로그인도 되어있고, 댓글도  작성되어있는 경우
         
         // 회원 번호를 얻어와서 변수에 저장
         var replyWriter = "${loginMember.memberNo}";
         $.ajax({
            url : "${contextPath}/reply/insertReply.do",
            data : {"replyWriter" : replyWriter,
                  "replyContent" : replyContent,
                  "parentBoardNo" : parentBoardNo},
            type : "post",
            success : function(result){
               if(result >0){ // 댓글 삽입 성공 시
                  // 댓글 작성 내용 삭제
                  $("#replyContent").val("");
               
                  // 성공 메세지 출력
                  swal({"icon" : "success", "title" : "댓글 등록 성공"});
                  
                  // 댓글 목록을 다시 조회 -> 새로 삽입한 댓글도 조회하여 화면에 출력
                  selectReplyList();
               }
            },
            error : function(){
               console.log("댓글 등록 실패");
            }
         });
      }
   }
});
</script>




  • ReplyController.java
// 댓글 삽입 Controller ******************************************************
else if(command.equals("/insertReply.do")) {
    // 오라클에서 숫자로 이루어진 문자열은 자동으로 숫자로 변환되는 특징을 사용할 예정
    String replyWriter = request.getParameter("replyWriter");
    int parentBoardNo = Integer.parseInt(request.getParameter("parentBoardNo"));
    String replyContent = request.getParameter("replyContent");

    
    Reply reply = new Reply();
    reply.setMemberId(replyWriter);
    reply.setReplyContent(replyContent);
    reply.setParentBoardNo(parentBoardNo);
    
    int result = service.insertReply(reply);
    
    response.getWriter().print(result); // result 결과를 바로 응답페이지로 보내버림
                                        // -> ajax!!! 
}




  • ReplyService.java
/** 댓글 삽입 Service
    * @param reply
    * @return result
    * @throws Exception
    */
public int insertReply(Reply reply) throws Exception{
    Connection conn = getConnection();
    String replyContent = reply.getReplyContent();
    
    // 크로스 사이트 스크립팅 방지 처리
    replyContent = replaceParameter(replyContent);
    
    // 개행문자 변환 처리
    // ajax 통신 시 textarea의 개행문자가 \n 하나만 넘어옴 -> <br>
    
    replyContent = replyContent.replace("\n", "<br>");
    
    // 변경된 replyContent를 다시 reply에 세팅
    reply.setReplyContent(replyContent);
    
    int result = dao.insertReply(conn, reply);
    
    // 트랜잭션 처리
    if(result > 0) commit(conn);
    else rollback(conn);
    
    close(conn);
    
    return result;
}

// 크로스 사이트 스크립트 방지 메소드
private String replaceParameter(String param) {
    String result = param;
    if(param != null) {
        result = result.replaceAll("&", "&amp;");
        result = result.replaceAll("<", "&lt;");
        result = result.replaceAll(">", "&gt;");
        result = result.replaceAll("\"", "&quot;");
    }
    
    return result;
}




  • reply-query.xml
<!-- 댓글 삽입 -->
<entry key="insertReply">
INSERT INTO REPLY VALUES(SEQ_RNO.NEXTVAL, ?, DEFAULT, DEFAULT, ?, ?)
</entry>




  • ReplyDAO.java
/** 댓글 삽입 DAO
    * @param conn
    * @param reply
    * @return result
    * @throws Exception
    */
public int insertReply(Connection conn, Reply reply) throws Exception {
    int result = 0;
    
    String query = prop.getProperty("insertReply");
    
    try {
        pstmt = conn.prepareStatement(query);
        
        pstmt.setString(1, reply.getReplyContent());
        pstmt.setString(2, reply.getMemberId());
        pstmt.setInt(3, reply.getParentBoardNo());
        
        result = pstmt.executeUpdate();
        
    } finally {
        close(pstmt);
    }
    return result;
}





댓글 수정

댓글 수정 폼과 기능을 만드는데 복붙으로 수업해서 나중에 더 자세히 봐야겠다.

  • 수정 성공 시
    20210111_10

  • 취소 버튼 클릭 시
    20210111_11

  • reply.jsp
<script>
var beforeReplyRow;

// 댓글 수정 폼 출력 함수
function showUpdateReply(replyNo, el){
	
	//console.log($(".replyUpdateContent").length);
	
	// 이미 열려있는 댓글 수정 창이 있을 경우 닫아주기
	if($(".replyUpdateContent").length > 0){
		$(".replyUpdateContent").eq(0).parent().html(beforeReplyRow);
	}
		
	
	// 댓글 수정화면 출력 전 요소를 저장해둠.
	beforeReplyRow = $(el).parent().parent().html();
	//console.log(beforeReplyRow);
	
	
	// 작성되어있던 내용(수정 전 댓글 내용) 
	var beforeContent = $(el).parent().prev().html();
	
	
	// 이전 댓글 내용의 크로스사이트 스크립트 처리 해제, 개행문자 변경
	// -> 자바스크립트에는 replaceAll() 메소드가 없으므로 정규 표현식을 이용하여 변경
	beforeContent = beforeContent.replace(/&amp;/g, "&");	
	beforeContent = beforeContent.replace(/&lt;/g, "<");	
	beforeContent = beforeContent.replace(/&gt;/g, ">");	
	beforeContent = beforeContent.replace(/&quot;/g, "\"");	
	
	beforeContent = beforeContent.replace(/<br>/g, "\n");	
	//console.log(beforeContent)
	
	
	// 기존 댓글 영역을 삭제하고 textarea를 추가 
	$(el).parent().prev().remove();
	var textarea = $("<textarea>").addClass("replyUpdateContent").attr("rows", "3").val(beforeContent);
	$(el).parent().before(textarea);
	
	//console.log(replyBtnArea);
	
	
	// 수정 버튼
	var updateReply = $("<button>").addClass("btn btn-primary btn-sm ml-1 mb-4").text("댓글 수정").attr("onclick", "updateReply(" + replyNo + ", this)");
	
	// 취소 버튼
	var cancelBtn = $("<button>").addClass("btn btn-primary btn-sm ml-1 mb-4").text("취소").attr("onclick", "updateCancel(this)");
	
	var replyBtnArea = $(el).parent();
	
	$(replyBtnArea).empty(); 
	$(replyBtnArea).append(updateReply); 
	$(replyBtnArea).append(cancelBtn); 
}

//-----------------------------------------------------------------------------------------


// 댓글 수정 함수
function updateReply(replyNo, el){
	
	// 수정된 댓글 내용
	var replyContent = $(el).parent().prev().val();
	
	$.ajax({
 		url : "${contextPath}/reply/updateReply.do",
		type : "post",
		data : {"replyNo" : replyNo, "replyContent" : replyContent},
		success : function(result){
			if(result > 0){
				
				selectReplyList(parentBoardNo);
				
				swal({"icon" : "success" , "title" : "댓글 수정 성공"});
			}
			
		}, error : function(){
			console.log("댓글 수정 실패");
		}		
	});
}


// 댓글 수정 취소 시 원래대로 돌아가는 함수
function updateCancel(el){
	//console.log(beforeReplyRow);
	$(el).parent().parent().html(beforeReplyRow);
}
</script>




  • ReplyController.java
// 댓글 수정 Controller ******************************************************
else if(command.equals("/updateReply.do")) {
    
    //파라미터(댓글 번호, 댓글 내용) 얻어오기
    int replyNo = Integer.parseInt(request.getParameter("replyNo"));
    String replyContent = request.getParameter("replyContent");
    
    Reply reply = new Reply();
    reply.setReplyNo(replyNo);
    reply.setReplyContent(replyContent);
    
    int result = service.updateReply(reply);
    
    response.getWriter().print(result);
}




  • ReplayService.java
/** 댓글 수정 Service
    * @param reply
    * @return result
    * @throws Exception
    */
public int updateReply(Reply reply) throws Exception{
    Connection conn = getConnection();
    
    String replyContent = reply.getReplyContent();
    
    // 크로스 사이트 스크립팅 방지 처리
    replyContent = replaceParameter(replyContent);
    
    // 개행문자 변환 처리
    // ajax 통신 시 textarea의 개행문자가 \n 하나만 넘어옴 -> <br>
    
    replyContent = replyContent.replace("\n", "<br>");
    
    // 변경된 replyContent를 다시 reply에 세팅
    reply.setReplyContent(replyContent);
    
    int result = dao.updateReply(conn, reply);
    
    if(result > 0) commit(conn);
    else rollback(conn);
    
    close(conn);
            
    return result;
}




  • reply-query.xml
<!-- 댓글 수정 -->
<entry key="updateReply">
UPDATE REPLY SET
REPLY_CONTENT = ?
WHERE REPLY_NO = ?
</entry>




  • ReplyDAO.java
/** 댓글 수정 DAO
    * @param conn
    * @param reply
    * @return result
    * @throws Exception
    */
public int updateReply(Connection conn, Reply reply) throws Exception{
    int result = 0;
    
    String query = prop.getProperty("updateReply");
    
    try {
        pstmt = conn.prepareStatement(query);
        
        pstmt.setString(1, reply.getReplyContent());
        pstmt.setInt(2, reply.getReplyNo());
        
        result = pstmt.executeUpdate();
        
    } finally {
        close(pstmt);
    }
    return result;
}




댓글 삭제

  • 댓글 삭제 성공 시
    20210111_12

  • DB 상태 변경
    20210111_13


  • reply.jsp
<script>
//댓글 삭제 함수
function deleteReply(replyNo){
	if(confirm("정말로 삭제하시겠습니까?")){
		var url = "${contextPath}/reply/deleteReply.do";
		
		$.ajax({
			url : url,
			data : {"replyNo" : replyNo},
			success : function(result){
				if(result > 0){
					selectReplyList(parentBoardNo);
					
					swal({"icon" : "success" , "title" : "댓글 삭제 성공"});
				}
			}, error : function(){
				console.log("ajax 통신 실패");
			}
		});
	}
}
</script>




  • ReplyController.java
// 댓글 삭제 Controller *******************************
else if(command.equals("/deleteReply.do")) {
    int replyNo = Integer.parseInt(request.getParameter("replyNo"));
    int result = service.updateReplyStatus(replyNo);
    
    response.getWriter().print(result);
}




  • ReplayService.java
/** 댓글 상태 변경 Service
    * @param replyNo
    * @return result
    * @throws Exception
    */
public int updateReplyStatus(int replyNo) throws Exception {
    Connection conn = getConnection();
    
    int result = dao.updateReplyStatus(conn, replyNo);
    
    if(result > 0) commit(conn);
    else rollback(conn);
    
    close(conn);
    return result;
}




  • reply-query.xml
<!-- 댓글 삭제  -->
<entry key="deleteBoard">
UPDATE BOARD SET
BOARD_STATUS = 'N'
WHERE BOARD_NO = ?
</entry>




  • ReplyDAO.java
/** 댓글 상태 변경 DAO
    * @param conn
    * @param replyNo
    * @return result
    * @throws Exception
    */
public int updateReplyStatus(Connection conn, int replyNo) throws Exception {
    int result = 0;
    
    String query = prop.getProperty("updateReplyStatus");
    
    try {
        pstmt = conn.prepareStatement(query);
        
        pstmt.setInt(1, replyNo);
        
        result = pstmt.executeUpdate();
        
    } finally {
        close(pstmt);
    }
    return result;
    
}




태그: , , ,

카테고리:

업데이트:

댓글남기기