댓글기능
댓글 조회와 댓글입력 기능을 구현해보자(수정 삭제 생략)
이때, 1초마다 댓글목록이 리로드되어 갱신된다.
![]() |
댓글조회
일반 게시글 목록에서 게시글을 클릭하면 조회되는 상세페이지가 있다.
해당 상세페이지가 로딩되면 해당 게시글의 댓글을 가져오도록 로직을 짜보자.
STEP1) Reply.java
- 생성위치 : com.br.board.model.vo
- 댓글정보를 보관할 vo 클래스를 만든다.
- 작성자 번호는 숫자와 문자 둘다 넣을수 있으므로 String 타입으로 지정.
- 날짜는 왠만하면 그냥 Date타입 말고 String 타입으로 한다.
STEP2) board-mapper.xml (수정)
- 게시글의 댓글을 조회하는데 필요한 sql문을 작성하면서 필요한 데이터를 확인해본다.
SELECT
REPLY_NO
, REPLY_CONTENT
, USER_ID
, TO_CHAR(CREATE_DATE, 'YY/MM/DD HH:MI') "CREATE_DATE"
FROM REPLY R
JOIN MEMBER ON (REPLY_WRITER=USER_NO)
WHERE R.STATUS='Y'
AND REF_BNO = 현재 내가 보고있던 게시글 번호
ORDER
BY REPLY_NO DESC
STEP3) boardDetailView.jsp (수정)
- 화면딴에서 댓글영역을 구현한다.
>> 댓글작성은 로그인한 상태에서만 가능하게 설정한다. - 댓글목록을 조회하는 함수는 selectReplyList로 명명하고
페이지가 다 로드되면 호출되도록 $(function(){...})안에서 호출한다.
<div id="reply-area">
<table border="1">
<thead>
<tr>
<th>댓글작성</th>
<% if(loginUser != null) { %>
<!-- 로그인이 되어있을 경우 -->
<td><textarea cols="50" rows="3" style="resize:none;"></textarea></td>
<td><button>댓글등록</button></td>
<% }else{ %>
<!-- 로그인이 되어있지 않은 경우 -->
<td><textarea cols="50" rows="3" style="resize:none;">로그인후 이용이 가능한 서비스입니다.</textarea></td>
<td><button disabled>댓글등록</button></td>
<% } %>
</tr>
</thead>
<tbody>
<!-- 댓글이 뿌려질 자리 -->
</tbody>
</table>
</div>
<script>
// 페이지가 로드되면 selectReplyList 메소드 실행
$(function(){
selectReplyList();
})
// ajax로 해당 게시글에 달린 댓글 목록 조회해오는 메소드
function selectReplyList(){
$.ajax({
url:"<%=contextPath%>/rlist.bo",
//숫자는 따옴표로 묶지 않아도 된다.
data:{no:<%=b.getBoardNo()%>},
success:function(list){
//console.log(list); 댓글 형태 확인
let value = "";
if(list.length == 0) {
//댓글이 없을 경우
value += "<tr>"
+ "<td colspan='3'>조회된 댓글이 없습니다.</td>"
+ "</tr>"
}else{
//댓글이 있을 경우
for(let i=0; i<list.length; i++){
value += "<tr>" //필드명이 키값이다.
+ "<td>" + list[i].replyWriter + "</td>"
+ "<td>" + list[i].replyContent + "</td>"
+ "<td>" + list[i].createDate + "</td>"
+ "</tr>";
}
}
$('#reply-area tbody').html(value);
},error:function(){
console.log('댓글목록 조회용 ajax통신 실패');
}
})
}
</script>
STEP4) AjaxReplyListController.java
- 생성위치 : com.br.board.controller
서블릿/매핑값 rlist.bo - 상세페이지가 로딩되자마자 실행되는, 댓글목록을 조회해서 데이터를 넘겨주는 Ajax용 서블릿
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
int boardNo = Integer.parseInt(request.getParameter("no"));
ArrayList<Reply> list = new BoardService().selectReplyList(boardNo);
response.setContentType("application/json; charset=utf-8");
// [{...}, {...}, ... ] 의 형태로 돌려줘야함.
// toJson()메소드를 호출할때 객체와 요청했던곳과의 스트림을 제시
new Gson().toJson(list, response.getWriter());
}
STEP5) BoardService.java (수정)
- selectReplyList(boardNo) 메소드 작성
public ArrayList<Reply> selectReplyList(int boardNo) {
Connection conn = getConnection();
ArrayList<Reply> list = new BoardDao().selectReplyList(conn, boardNo);
close(conn);
return list;
}
STEP6) BoardDao.java (수정)
- selectReplyList(conn, boardNo) 메소드 작성
public ArrayList<Reply> selectReplyList(Connection conn, int boardNo) {
ArrayList<Reply> list = new ArrayList<>();
PreparedStatement pstmt = null;
ResultSet rset = null;
String sql = prop.getProperty("selectReplyList");
try {
pstmt = conn.prepareStatement(sql);
pstmt.setInt(1, boardNo);
rset = pstmt.executeQuery();
while(rset.next()) {
Reply r = new Reply();
r.setReplyNo(rset.getInt("reply_no"));
.....
list.add(r);
}
} catch (SQLException e) {
e.printStackTrace();
} finally {
close(rset);
close(pstmt);
}
return list;
}
댓글입력
댓글을 입력했을때 db에 insert후
새롭게 댓글목록을 리로딩해서 내가 쓴 댓글이 보이도록 한다.
STEP1) board-mapper.xml (수정)
- Reply테이블이 댓글을 insert하는 구문을 작성해보면서 필요한 데이터들을 확인해본다.
INSERT
INTO REPLY
(
REPLY_NO
, REPLY_CONTENT
, REF_BNO
, REPLY_WRITER
)
VALUES
(
SEQ_RNO.NEXTVAL
, 사용자가 입력한 댓글 내용
, 현재보굈던 게시글 번호
, 작성자의 회원번호
)
STEP2) boardDetailView.jsp (수정)
- 댓글등록에 클릭시 insertReply 함수 발동되도록 한다
- Ajax에서 data를 담는 객체에 userNo:<%=loginUser.getUserNo()%> 구문을 쓰면 비회원 상태 로딩시 null오류난다.
회원이든 비회원이든 스크립트는 한번 쫙 읽히기 때문이다.
>>서블릿에서 데이터를 담도록 한다.
댓글작성 : <textarea cols="50" rows="3" style="resize:none;"></textarea>
<button onclick="insertReply();">댓글등록</button>
.....
<script>
function insertReply(){
$.ajax({
url:"<%=contextPath%>/rinsert.bo",
data:{
content:$('#reply-area textarea').val(),
no:<%=b.getBoardNo()%>
//여기서 UserId를 담는 구문을 쓰면, 오류가 난다
},
type"post",
success:function(result){
if(result>0) { //댓글 등록 성공
//댓글란에 적힌것은 초기화 시킨다.
$("#reply-area textarea").val("");
//db로부터 댓글들을 재조회 한다.
selectReplyList();
}else {
alert("댓글등록 실패");
}
}, error:function(){
console.log("댓글작성용 ajax 통신 실패")
}
})
}
</script>
STEP3) AjaxReplyInsertController.java
- 생성위치 : com.br.board.controller
서블릿/매핑값 rinsert.bo - 일반 서블릿과 달리 result에 담긴 성공여부를 판별하지 않고 바로 응답데이터를 넘기면 된다.
>> 이때, result는 한글이 없으므로 setContentType 안해도 됨.
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String replyContent = request.getParameter("content");
int boardNo = Integer.parseInt(request.getParameter("no"));
int userNo = ((Member)request.getSession().getAttribute("loginUser")).getUserNo();
Reply r = new Reply();
r.setReplyContent(replyContent);
r.setRefBoardNo(boardNo);
r.setReplyWriter(String.valueOf(userNo));
int result = new BoardService().insertReply(r);
response.getWriter().print(result);
}
STEP4) BoardService.java (수정)
- insertReply(r) 메소드 작성
public int insertReply(Reply r) {
Connection conn = getConnection();
int result = new BoardDao().insertReply(conn, r);
if(result>0) {
commit(conn);
}else {
rollback(conn);
}
close(conn);
return result;
}
STEP5) BoardDao.java (수정)
- insertReply(conn, r) 메소드 작성
public int insertReply(Connection conn, Reply r) {
int result = 0;
PreparedStatement pstmt = null;
String sql = prop.getProperty("insertReply");
try {
pstmt = conn.prepareStatement(sql);
pstmt.setString(1, r.getReplyContent());
pstmt.setInt(2, r.getRefBoardNo());
pstmt.setString(3, r.getReplyWriter());
result = pstmt.executeUpdate();
} catch (SQLException e) {
e.printStackTrace();
} finally {
close(pstmt);
}
return result;
}
주기적으로 댓글 리로드
1초마다 댓글목록을 새로 조회하도록 한다.
해당 원리는 채팅에서도 활용할 수 있다.
STEP1) AjaxReplyListController.java (수정)
- 윈도우 객체의 함수 setInterval(함수, ms) 사용
>>이때 함수에 ()를 붙이지 않는다! - 위치는 $(function(){...}) 안
- 테스트를 하기 위해서는 세션을 분리시켜야하는데,
탭을 여러개 연다고 해도 세션은 공유됨.
>> 크롬 시크릿창 활용
<script>
// 페이지가 로드되면 selectReplyList 메소드 실행
$(function(){
selectReplyList();
setInterval(selectReplyList, 1000)
})
</script>

'다양한 기술들 > 레거시 Web 실습' 카테고리의 다른 글
| [13] 아이디 중복체크 : Ajax 활용 (0) | 2023.01.18 |
|---|---|
| [12] 게시판심화2 : 상세보기(+첨부된 이미지 띄우기) (0) | 2023.01.18 |
| [11] 게시판심화2 : 썸네일목록, 글작성(+첨부파일 미리보기) (0) | 2023.01.16 |
| [10] 게시판심화1 : 상세보기(+첨부파일 조회 및 다운로드) (0) | 2023.01.12 |
| [09] 게시판심화1 : 글쓰기(+파일첨부) (0) | 2023.01.11 |

댓글