국비 67 - 댓글 조회

냐아암·2023년 8월 9일
0

국비

목록 보기
84/114

댓글 목록 조회

Ajax

// 댓글 목록 조회(AJAX)
function selectReplyList(){

    // contextPath, boardNo, memberNo 전역변수 사용
    $.ajax({
        url : contextPath + "/reply/selectReplyList",
        data : {"boardNo" : boardNo},
        type : "get",
        dataType : "JSON", // JSON 형태의 문자열 응답 데이터를 JS 객체로 자동 변환

        success : function(rList){
            // rList : 반환받은 댓글 목록
            console.log(rList);

            // 화면에 출력되어 있는 댓글 목록 삭제
            const replyList = document.getElementById("reply-list"); // ul 태그
            replyList.innerHTML="";

            // rList에 저장된 요소를 하나씩 접근
            for(let reply of rList){
                
                // 행
                const replyRow = document.createElement("li");
                replyRow.classList.add("reply-row");

                // 작성자
                const replyWriter = document.createElement("p");
                replyWriter.classList.add("reply-writer");

                // 프로필 이미지
                const profileImage = document.createElement("img");

                if(reply.profileImage != null){ // 프로필 이미지가 있는 경우
                    profileImage.setAttribute("src", contextPath + reply.profileImage);
                } else  { // 없는 경우 == 기본 이미지
                    profileImage.setAttribute("src", contextPath + "/resources/images/user.png");
                }

                // 작성자 닉네임
                const memberNickname = document.createElement("span");
                memberNickname.innerText = reply.memberNickname;

                // 작성일
                const replyDate = document.createElement("span");
                replyDate.classList.add("reply-date");
                replyDate.innerText = "(" +  reply.createDate + ")";

                // 작성자 영역(p)에 프로필, 닉네임, 작성일을 마지막 자식으로 추가
                replyWriter.append(profileImage, memberNickname, replyDate);

                // 댓글 내용
                const replyContent = document.createElement("p");
                replyContent.classList.add("reply-content");

                // 왜 innerHTML? <br> 태그 인식을 위해서
                replyContent.innerHTML = reply.replyContent;

                // 행에 작성자, 내용 추가
                replyRow.append(replyWriter, replyContent);

                // 로그인한 회원 번호와 댓글 작성자의 회원번호가 같을 때만 버튼 추가
                if(loginMemberNo == reply.memberNo){
                    // 버튼 영역
                    const replyBtnArea = document.createElement("div");
                    replyBtnArea.classList.add("reply-btn-area");
    
                    // 수정 버튼
                    const updateBtn = document.createElement("button");
                    updateBtn.innerText="수정";
                    // 수정 버튼에 onclick 이벤트 속성 추가
                    updateBtn.setAttribute("onclick", "showUpdateReply(" + reply.replyNo + ", this)");
    
                    // 삭제 버튼
                    const deleteBtn = document.createElement("button");
                    deleteBtn.innerText="삭제";
                    // 삭제 버튼에 onclick 이벤트 속성 추가
                    deleteBtn.setAttribute("onclick", "deleteReply("+ reply.replyNo +")")

                    // 버튼 영역 마지막 자식으로 수정/삭제 버튼 추가
                    replyBtnArea.append(updateBtn, deleteBtn);

                    // 행에 버튼 영역 추가
                    replyRow.append(replyBtnArea);
                }
                

                // 댓글 목록(ul)에 행(li)추가
                replyList.append(replyRow);
            }
        },
        error : function(){
            console.log("오류발생");
        }
    });
}

Servlet

@WebServlet("/reply/*") // reply로 시작하는 모든 요청 받음
public class ReplyController extends HttpServlet {
	
	// /reply/selectReplyList
	// /reply/insert
	// /reply/update
	// /reply/delete
	
	@Override
	protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		// GET 방식 요청 처리
		String uri = req.getRequestURI();
		// /community/reply/insert
		String contextPath = req.getContextPath();
		// /community
		String command = uri.substring(  (contextPath + "/reply/").length()  );
		// insert
		
		
		ReplyService service = new ReplyService();
		
		try {
			
			// 댓글 목록 조회 요청인 경우
			if(command.equals("selectReplyList")) {
				// 파라미터를 얻어와 정수 형태로 파싱
				
				int boardNo = Integer.parseInt(req.getParameter("boardNo"));
				
				// 댓글 목록 조회 service 호출 후 결과 반환 받기
				List<Reply> replyList =service.selectReplyList(boardNo);
				
				// JSON 변환 + 응답
				new Gson().toJson(replyList, resp.getWriter());
			}

Service

/** 댓글 목록 조회 service
	 * @param boardNo
	 * @return replyList
	 * @throws Exception
	 */
	public List<Reply> selectReplyList(int boardNo) throws Exception{
		
		Connection conn = getConnection();
		
		List<Reply> replyList = dao.selectReplyList(conn, boardNo);
		
		close(conn);
		
		return replyList;
	}

DAO

/** 댓글 목록 조회 DAO
	 * @param conn
	 * @param boardNo
	 * @return replyList
	 * @throws Exception
	 */
	public List<Reply> selectReplyList(Connection conn, int boardNo) throws Exception {
		
		List<Reply> replyList = new ArrayList<Reply>();
		
		try {
			
			String sql = prop.getProperty("selectReplyList");
			
			pstmt = conn.prepareStatement(sql);
			
			pstmt.setInt(1, boardNo);
			
			rs = pstmt.executeQuery();
			
			while(rs.next()) {
				
				Reply r = new Reply();
				
				r.setReplyNo(rs.getInt("REPLY_NO"));
				r.setReplyContent(rs.getString(2));
				r.setCreateDate(rs.getString(3));
				r.setBoardNo(rs.getInt(4));
				r.setMemberNo(rs.getInt(5));
				r.setMemberNickname(rs.getString(6));
				r.setProfileImage(rs.getString(7));
				
				replyList.add(r);
				
			}
			
		} finally {
			close(rs);
			close(pstmt);
		}
		
		
		
		return replyList;
	}

SQL

<!-- 댓글 목록 조회 -->
	<entry key="selectReplyList">
		SELECT REPLY_NO, REPLY_CONTENT,
		        TO_CHAR(CREATE_DT, 'YYYY.MM.DD HH24:MI:SS') CREATE_DT,
		        BOARD_NO, MEMBER_NO, MEMBER_NICK, PROFILE_IMG
		FROM REPLY
		JOIN MEMBER USING(MEMBER_NO)
		WHERE REPLY_ST ='N'
		AND BOARD_NO=?
		ORDER BY REPLY_NO
	</entry>
    

Jsp

<div class="reply-list-area">
        <ul id="reply-list">
            

            <c:forEach var="reply" items="${rList}">

                <li class="reply-row">
                    <p class="reply-writer">

                        <c:if test="${empty reply.profileImage}">
                            <!-- 프로필 이미지가 없을 경우 -->
                            <img src="${contextPath}/resources/images/user.png">
                        </c:if>
                        <c:if test="${!empty reply.profileImage}">
                            <!-- 프로필 이미지가 있을 경우 -->
                            <img src="${contextPath}${reply.profileImage}">
                        </c:if>
                        <span>${reply.memberNickname}</span>
                        <span class="reply-date"> (${reply.createDate})</span>
                    </p>
                    <p class="reply-content">${reply.replyContent}</p>

                    <c:if test="${loginMember.memberNo == reply.memberNo}">
                        <div class="reply-btn-area">
                            <button onclick="showUpdateReply(${reply.replyNo}, this)">수정</button>
                            <button onclick="deleteReply(${reply.replyNo})">삭제</button>
                        </div>
                    </c:if>
                </li>

            </c:forEach>

            
        </ul>
    </div>
profile
개발 일지

0개의 댓글