이 포스팅은 공부할 겸 오픈소스를 참고하지 않고 혼자서 만들어 본 것으로 굉장히 비효율적일 것입니다.
-------------------------------------------------------------------------------------------------------------------------------------------
1. DB 테이블
CREATE TABLE TB_COMMENT( IDX INT PRIMARY KEY AUTO_INCREMENT, BOARD_IDX INT NOT NULL, CREA_DTM TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, CREA_ID VARCHAR(30) NOT NULL, CONTENTS VARCHAR(100), DEL_GB VARCHAR(1) NOT NULL DEFAULT 'N')
- TB_COMMENT
IDX - 댓글 번호(주키, INT, AUTO_INCREMENT)
BOARD_IDX - 게시글 번호(NN, INT )
CREA_DTM - 작성 시간(NN, TIMESTAMP, DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP)
CREA_ID - 작성자(NN, VARCHAR(30))
CONTENTS - 내용(N, VARCHAR(100))
DEL_GB - 삭제여부(NN, VARCHAR(1), DEFAULT 'N')
2. Controller
- SampleController
@RequestMapping(value="/sample/writeComment.do") public ModelAndView writeComment(CommandMap commandMap) throws Exception{ ModelAndView mv = new ModelAndView("redirect:/sample/openBoardDetail.do"); sampleService.writeComment(commandMap.getMap()); mv.addObject("IDX",commandMap.get("IDX")); return mv; } @RequestMapping(value="/sample/deleteComment.do") public ModelAndView deleteComment(CommandMap commandMap) throws Exception{ ModelAndView mv = new ModelAndView("redirect:/sample/openBoardDetail.do"); sampleService.deleteComment(commandMap.getMap()); mv.addObject("IDX",commandMap.get("IDX")); return mv; } @RequestMapping(value="/sample/updateComment.do") public ModelAndView updateComment(CommandMap commandMap) throws Exception{ ModelAndView mv = new ModelAndView("redirect:/sample/openBoardDetail.do"); sampleService.updateComment(commandMap.getMap()); mv.addObject("IDX",commandMap.get("IDX")); return mv; }
차례대로 댓글 작성, 삭제, 수정에 관한 Controller이다. 각자 IDX을 추가해 가져가는데 redirect로 게시글 보기 페이지의 게시글 번호가 필요하기 때문이다.
3. Service
- SampleService(Impl)
@Override public void writeComment(Map<String, Object> map) throws Exception { sampleDAO.insertComment(map); } @Override public void deleteComment(Map<String, Object> map) throws Exception { sampleDAO.deleteComment(map); } @Override public void updateComment(Map<String, Object> map) throws Exception { sampleDAO.updateComment(map); }
서비스단에서는 특이한 것 없이 게시판 관련 서비스단과 동일하다.
4. DAO
- SampleDAO
public void insertComment(Map<String,Object> map) throws Exception{ insert("sample.insertComment",map); } @SuppressWarnings("unchecked") public List<Map<String,Object>> selectCommentList(Map<String,Object> map) throws Exception{ return (List<Map<String,Object>>)selectList("sample.selectCommentList",map); } public void deleteComment(Map<String,Object> map) throws Exception{ update("sample.deleteComment",map); } public void updateComment(Map<String,Object> map) throws Exception{ update("sample.updateComment",map); }
댓글 리스트들을 가져오는 DAO단이 하나가 따로 추가되어 있고 나머지 등록, 삭제, 수정에 관한 DAO단은 동일하다.
5. SQL
- sample_SQL.xml
<insert id="insertComment" parameterType="HashMap"> <![CDATA[ INSERT INTO TB_COMMENT( BOARD_IDX, CREA_ID, GRADE, CONTENTS )VALUES( #{IDX}, 'Admin', '0', #{COM_CONTENTS} ) ]]> </insert> <select id="selectCommentList" parameterType="HashMap" resultType="HashMap"> <![CDATA[ SELECT IDX, CREA_ID, CONTENTS, CREA_DTM FROM TB_COMMENT WHERE BOARD_IDX=#{IDX} AND DEL_GB='N' ]]> </select> <update id="deleteComment" parameterType="HashMap"> <![CDATA[ UPDATE TB_COMMENT SET DEL_GB='Y' WHERE IDX=#{COM_IDX} ]]> </update> <update id="updateComment" parameterType="HashMap"> <![CDATA[ UPDATE TB_COMMENT SET CONTENTS=#{COM_CONTENTS_UPD} WHERE IDX=#{COM_IDX} ]]> </update>
추가로 설명할 부분은 없을 것 같다.
6. JSP
- boardDetail.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <title>글 보기</title> <%@ include file="/WEB-INF/include/include-header.jspf" %> </head> <body> <table class="board_view"> <colgroup> <col width="15%"> <col width="35%"> <col width="15%"> <col width="35%"> </colgroup> <caption>${map.TITLE }</caption> <tbody> <tr> <th>No.</th> <td>${map.IDX }</td> <th>Hit.</th> <td>${map.HIT_CNT }</td> </tr> <tr> <th>Writer.</th> <td>${map.CREA_ID }</td> <th>Date.</th> <td>${map.CREA_DTM }</td> </tr> <tr> <th>Content.</th> <td colspan="3">${map.CONTENTS }</td> </tr> <c:if test="${fn:length(list)>0 }"> <tr> <th>첨부파일</th> <td colspan="3"> <c:forEach items="${list }" var="f" > <p> <input type="hidden" id="IDX" value="${f.IDX }"><a href="#this" name="FILE">${f.ORIGINAL_FILE_NAME }</a>(${f.FILE_SIZE}byte) </p> </c:forEach> </td> </tr> </c:if> </tbody> </table><br> <form id="frm"> <table class="board_view"> <colgroup> <col width="15%"> <col width="85%"> </colgroup> <tbody> <tr> <th>댓글</th> <td> ${fn:length(comment) } </td> </tr> <c:if test="${fn:length(comment)>0 }"> <c:forEach items="${comment }" var="com"> <tr> <td style="background:#f7f7f7;color:#3b3a3a;" > ${com.CREA_ID } <p style="font-size: 8px;" >${com.CREA_DTM }</p> </td> <td> <input type="hidden" value="${com.IDX }" id="com_IDX"> <div id="com_Div"><input type="hidden" value ="${com.CONTENTS}" id="com_CON">${com.CONTENTS }</div> <div align="right"> <a href="#this" name="com_Del" class="btn">삭제</a> <a href="#this" name="com_Mod" class="btn">수정</a> </div> </td> </tr> </c:forEach> </c:if> <tr> <td colspan="2"> <div> Admin<br/><br/> <textarea rows="5" cols="130" name="COM_CONTENTS" ></textarea> <p align="right" ><a href="#this" id="com_write" class="btn">등록</a></p> </div> </td> </tr> </tbody> </table> </form> <%@ include file="/WEB-INF/include/include-body.jspf" %> <a href="#this" id="update" class="btn">수정하기</a> <a href="#this" id="list" class="btn">목록</a> <script type="text/javascript"> $(document).ready(function(){ $("#update").on("click",function(e){ e.preventDefault(); fn_openBoardUpdate(); }) $("#list").on("click",function(e){ e.preventDefault(); fn_openBoardList(); }) $("a[name=FILE]").on("click",function(e){ e.preventDefault(); fn_downloadFile($(this)); }) $("#com_write").on("click",function(e){ e.preventDefault(); fn_writeComment(); }) $("a[name=com_Del]").on("click",function(e){ e.preventDefault(); fn_deleteComment($(this)); }) $("a[name=com_Mod]").on("click",function(e){ e.preventDefault(); fn_commentModify($(this)); }) }) function fn_openBoardUpdate(){ var comSubmit = new ComSubmit(); comSubmit.addParam("IDX",${map.IDX}); comSubmit.setUrl("<c:url value='/sample/openBoardUpdate.do'/>"); comSubmit.submit(); } function fn_openBoardList(){ var comSubmit = new ComSubmit(); comSubmit.setUrl("<c:url value='/sample/openBoardList.do'/>"); comSubmit.submit(); } function fn_downloadFile(obj){ var comSubmit = new ComSubmit(); comSubmit.addParam("IDX",obj.parent().find("#IDX").val()); comSubmit.setUrl("<c:url value='/common/downloadFile.do'/>"); comSubmit.submit(); $("#commonForm").children().remove(); } function fn_writeComment(){ var comSubmit = new ComSubmit("frm"); comSubmit.addParam("IDX",${map.IDX}) comSubmit.setUrl("<c:url value='/sample/writeComment.do'/>"); comSubmit.submit(); } function fn_deleteComment(obj){ var comSubmit = new ComSubmit(); comSubmit.addParam("IDX",${map.IDX}) comSubmit.addParam("COM_IDX",obj.parent().parent().find("#com_IDX").val()); comSubmit.setUrl("<c:url value='/sample/deleteComment.do'/>"); comSubmit.submit(); } function fn_commentModify(obj){ var con = obj.parent().parent().find("#com_Div").find("#com_CON").val(); var str = "<textarea rows='5' cols='100' name='COM_CONTENTS_UPD'>"+con+"</textarea><p align='right' ><a href=''#this' name='com_Upd' class='btn'>등록</a></p><hr/>"; var div = obj.parent().parent().find("#com_Div"); div.empty(); div.append(str) $("a[name=com_Upd]").on("click",function(e){ e.preventDefault(); fn_updateComment($(this)); }) } function fn_updateComment(obj){ var comSubmit = new ComSubmit("frm"); comSubmit.addParam("IDX",${map.IDX}) comSubmit.addParam("COM_IDX",obj.parent().parent().parent().find("#com_IDX").val()); comSubmit.setUrl("<c:url value='/sample/updateComment.do'/>"); comSubmit.submit(); } </script> </body> </html>
- 49~91줄
댓글에 대한 내용 정보를 관리하기 위해 form 태그를 이용하였고, 테이블로 구성하였으며 여태 게시판 만들기 과정을 거치면서 사용했던 방식을 사용하여 구성하였다.
- 111~122, 147~182줄
게시판 만들기 과정을 거치며 사용했던 방식을 사용하여 구성하였다. 예를 들자면 Input 태그의 Hidden 타입을 사용하여 IDX값 넘겨주는 방식, Div 태그에 append를 사용하여 내용 추가하는 방식을 이용하여 댓글 수정 시에 유용하게 사용 되었다.
7. 테스트
- 댓글 작성
현재는 댓글이 없는 상태이기에 댓글의 갯수와 댓글을 등록할 수 있는 창을 띄운다.
댓글을 작성하였다. 현재는 Admin이라고 고정값으로 CREA_ID를 주었으므로 Admin으로 고정되었고 등록 시간과 함께 내용이 표시됨을 확인할 수있다.
위 로그를 살펴보면 게시판 상세보기창을 불러오면서 DAO단에서 댓글리스트를 불러오는 것이 보이며 게시판 상세보기창에서 댓글을 작성하고 그 기능들이 사용됨이 보이고 리다이렉트로 게시판 상세보기를 다시 불러오는 것을 볼 수 있다.
댓글을 하나 더 작성하여 테스트 해보았다.
- 댓글 수정
댓글 수정을 위해 수정 버튼을 클릭 후 뜬 텍스트창에 새로 입력하였다.
수정이 잘되었음을 볼 수 있다.(줄바꿈이 안된 것은 일단은 넘어가도록 한다)
위는 해당 댓글 수정 기능의 과정을 나타내는 로그다.
- 댓글 삭제
맨 위에 있는 댓글을 삭제 한 후의 화면이다.
삭제의 기능이 이루어지는 로그로 삭제를 위한 메서드들이 잘 실행되었는 것을 확인 할 수 있다.
'코딩 > Spring' 카테고리의 다른 글
Spring 개발 - 게시판 만들기 번외(3) - 회원 기능(로그인) (2) | 2018.03.13 |
---|---|
Spring 개발 - 게시판 만들기 번외(2) - 회원 기능(회원가입) (0) | 2018.03.13 |
Spring 개발 - 게시판 만들기(17) - 페이징(전자정부프레임워크 라이브러리) (0) | 2018.03.03 |
Spring 개발 - 게시판 만들기(16) - AOP 적용하기 (0) | 2018.03.02 |
Spring 개발 - 게시판 만들기(15) - 파일 다중 업로드 및 게시판 수정하기(파일 업로드) (0) | 2018.01.02 |