Spring10_댓글 기능 구현
댓글달기
- 우선 spring을 구현하기 위해서는 t_board 테이블과, t_reply테이블이 필요하다
- t_board : 게시물
- t_reply : 게시물에 연결된 댓글
-- 답글기능을 넣을 것을 고려하여 아래와 같이 테이블을 구성했다.
create table t_reply(
no number(5) primary key
, board_no number(5) not null
, comments varchar2(1000) not null
, writer varchar2(100) not null
, reg_date date default sysdate
, groupid number(5) not null
, parentid number(5) not null
, cstep number(5) not null
, constraint t_reply_board_no_fk foreign key(board_no) references t_board(no)
);
create sequence seq_t_reply_no;
create sequence seq_t_reply_groupid;
-- 댓글 등록
insert into t_reply(no, board_no, comments, writer, groupid, parentid, cstep )
values( seq_t_reply_no.nextval, 11, '정말 열심히 하시는군요!', 'kopo1234', seq_t_reply_groupid.nextval, 0, 0);
insert into t_reply(no, board_no, comments, writer, groupid, parentid, cstep )
values( seq_t_reply_no.nextval, 11, 'ㅇㅈ', 'bbbb', 1, 1, 1);
insert into t_reply(no, board_no, comments, writer, groupid, parentid, cstep )
values( seq_t_reply_no.nextval, 11, '222', 'eeee', 1, 1, 1);
insert into t_reply(no, board_no, comments, writer, groupid, parentid, cstep )
values( seq_t_reply_no.nextval, 11, 'ㅇㅈㅇㅈ', 'aaaa', 1, 2, 2);
insert into t_reply(no, board_no, comments, writer, groupid, parentid, cstep )
values( seq_t_reply_no.nextval, 11, '최고다!', 'user', seq_t_reply_groupid.nextval, 0, 0);
-- 댓글 불러오기
select no, board_no, comments, writer, groupid, parentid, cstep, reg_date
from t_reply
where board_no = 11
start with parentid = 0
connect by prior no = parentid
order siblings by groupid asc;
1. 구조설명
- detail.jsp(게시물상세)에 댓글을 작성하는 기능이 구현되어있다.
- 등록 버튼을 클릭했을 때 데이터를 넘긴다. ( 데이터의 형식은 json/딕셔너리형식으로 설정했다.)
ajax
를 이용하여 가상의 uri/board/reply.json
에 댓글 데이터를 전송- 성공시
Controller
에서는 자동으로 ReplyVO가 넘어가고, 이것을 session 로그인 ID 정보(writer)와 함께 insert 해준다. - 만약 insert성공시 1을 반환하게 되는데 1이 반환될 경우 ObjectMapper를 이용하여 ReplyVO를 json형식의 String으로 리턴한다.
- 실패시 “err”리턴
2. 구현코드
1. 댓글기능 프론트 구현
- detail.jsp
- 입력칸
<div style="margin-bottom:20px;">
<table border="1" style="width:100%;">
<tr>
<td width="80%">
<textarea rows="2" cols="60" placeholder="댓글을 입력하세요!" id="comments"></textarea>
</td>
<td>
<button id="submitBtn"> 등록</button>
</td>
</tr>
</table>
</div>
- 출력칸
<c:if test="${ not empty requestScope.replyList }">
<table id="replyShow" border="1" width="100%" >
<c:forEach items="${ requestScope.replyList }" var="replyVO" varStatus="loop">
<tr>
<th>${ replyVO.writer }</th>
<td>${ replyVO.comments }</td>
<td>${ replyVO.regDate }</td>
<td>답글작성</td>
</tr>
</c:forEach>
</table>
</c:if>
2. 등록버튼 눌렀을 경우 데이터 넘기기 (ajax)
- spring-mvc.xml
- ajax에서 Controller로 데이터를 넘겼을 때 알아서 VO가 인식하도록 하기 위해서는
message-converters
가 필요하다 - 아래의 xml 코드를
spring-mvc.xml
설정 파일의<mvc:annotation-driven>
태그 아래에 넣는다. (없으면 만들기) - messageConverter란?
- HTTP통신에서 일반 문자열이 아닌 XML이나 JSON으로 통신하기 위해 사용
- 왜 JSON을 쓸까? XMLHttpRequest라는 내장 브라우저가 존재하여 Ajax 통신이 가능한데 XML로 데이터를 전송하는 것은 비효율적이므로 JSON으로 주고받음
- ajax에서 Controller로 데이터를 넘겼을 때 알아서 VO가 인식하도록 하기 위해서는
<mvc:message-converters>
<bean class="org.springframework.http.converter.StringHttpMessageConverter">
<property name="supportedMediaTypes">
<list>
<value>text/html; charset=utf-8</value>
<value>application/json; charset=utf-8</value>
</list>
</property>
</bean>
</mvc:message-converters>
- pom.xml
<!-- jackson -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.1.1</version>
</dependency>
- detail.jsp의 script파일/코드
- ajax에서 데이터를 넘긴다.
- 성공시 크롬브라우저 console창에 출력
$(document).ready(function(){
$('#submitBtn').click(function(){
var date = new Date();
// 데이터 넘기기
var info={
boardNo: '${board.no}', // 현재 게시물 번호
comments:$('#comments').val() // 댓글내용
}
$.ajax({
url: "${ pageContext.request.contextPath }/board/reply.json", // ${ pageContext.request.contextPath } + controller에서 작성한 uri
type: "GET",
data: info,
success: function(data){
console.log(data) // 데이터 콘솔창 출력
},
error: function(){
alert("simpleWithObject err");
}
});
})
})
3. Controller 에서 값 받고 넘기기
ResponseBody
: 데이터를 RequestMapping에 설정한 uri에 바로 전달.- jsp파일이 없어도 알아서 뿌려주게 됨.
@ResponseBody
@RequestMapping("/board/reply.json")
public String insertComments(ReplyVO reply, HttpSession session) throws JsonProcessingException {
MemberVO userVO = (MemberVO)session.getAttribute("userVO"); // 작성자 설정을 위해 session에서 값 불러옴
reply.setWriter(userVO.getId()); // ReplyVO에 Writer로 지정
int result = service.insertComments(reply); // insert하면 몇개가 insert 되었는지 리턴됨.
if (result == 1) { // 댓글 하나만 넣으니까 1일 경우에만 VO를 json형태의 string으로 리턴
ObjectMapper mapper = new ObjectMapper();
String json = mapper.writeValueAsString(reply);// json 모양의 String으로 변환
return json;
}
return "err";
}
service
public int insertComments(ReplyVO reply) {
int result = boardDAO.insertComments(reply);
return result;
}
DAO
public int insertComments(ReplyVO reply) {
int result = sqlSessionTemplate.insert("board.BoardDAO.insertComment", reply);
return result; // insert 성공한 개수 반환
}
sqlmap-board.xml(MyBatis)
<insert id="insertComment" parameterType="replyVO" >
insert into t_reply(no, board_no, comments, writer, groupid, parentid, cstep )
values( seq_t_reply_no.nextval, #{boardNo}, #{comments}, #{writer}, seq_t_reply_groupid.nextval, 0, 0)
</insert>
4. ajax 통신 성공시 날아온 데이터를 파싱하여 append하기
- 2번의 코드를 아래와 같이 변경한다.
$(document).ready(function(){
$('#submitBtn').click(function(){
var date = new Date();
// 데이터 넘기기
var info={
boardNo: '${board.no}', // 현재 게시물 번호
comments:$('#comments').val() // 댓글내용
}
$.ajax({
url: "${ pageContext.request.contextPath }/board/reply.json", // ${ pageContext.request.contextPath } + controller에서 작성한 uri
type: "GET",
data: info,
success: function(data){
console.log(data)
var comm = JSON.parse(data) // 날아온 데이터(string)를 json형식으로 변환
//console.log(comm)
// 댓글 목록 table안에 제일 마지막에 입력한 정보 붙이기
$('#replyShow').append("<tr>")
$('#replyShow').append("<th>"+comm.writer+"</th>")
$('#replyShow').append("<td>"+comm.comments+"</td>")
$('#replyShow').append("<td>"+date.getFullYear()+"-"+ ('0' + (date.getMonth() + 1)).slice(-2) +"-"+('0' + date.getDate()).slice(-2)+"</td>")
$('#replyShow').append("<td>답글작성</td>")
$('#replyShow').append("</tr>")
},
error: function(){
alert("simpleWithObject err");
}
});
})
})