1. 개요
■ 지난 포스팅 : [JSP개발] 게시판 - 방명록 수정
이제는 게시판에 댓글을 구현할 것이다. 댓글은 게시글 상세보기 시 보이며, 로그인한 사용자만 작성하도록 한다.
■ JSP
- MainForm.jsp : 메인화면에는 스크롤을 나타나게 하기 위해 CSS 코드를 추가해준다.
- BoardDetailForm.jsp : 댓글은 상세보기 화면에서 같이 보이도록 한다. 댓글 작성도 상세보기 화면에서 작성을 한다.
■ Java
- CommentController.java : 댓글 관련 Controller이다.
- CommentWriteAction.java : 댓글 작성 Action이다.
- CommentBean.java : 댓글의 데이터를 담을 자바빈이다.
- CommentDAO.java : 댓글 테이블의 DAO이다.BoardDetailAction.java : 해당 글에 달린 댓글을 같이 보여주기 위해 상세보기 Action에서 댓글을 조회하여 화면으로 전달한다.
■ properties
- CommentCommand.properties : 댓글 관련 명령어를 가지고 있는 프로퍼티 파일
2. 소스 코드
댓글을 저장할 테이블과 시퀀스를 먼저 만들어준다. 그리고 jsp.board.comment.action, jsp.board.comment.model, jsp.board.comment.properties 이렇게 3개의 패키지를 만들어준다.
■ 테이블 및 시퀀스
댓글을 저장할 테이블과 댓글 글 번호를 부여하는 시퀀스를 만든다. 댓글 테이블의 경우 게시글 글 번호가 필요하다. 어느 게시글에 달린 댓글인지를 알기 위해서이다. 게시글 글번호인 COMMENT_BOARD 칼럼의 경우 Member_Board(게시판 테이블)의 board_num을 외래키로 갖는다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | -- 댓글 테이블 CREATE TABLE BOARD_COMMENT ( COMMENT_NUM NUMBER NOT NULL, COMMENT_BOARD NUMBER NOT NULL, COMMENT_ID VARCHAR2(15), COMMENT_DATE DATE, COMMENT_PARENT NUMBER, COMMENT_CONTENT VARCHAR2(1000) NOT NULL, CONSTRAINT PK_comment PRIMARY KEY(COMMENT_NUM), CONSTRAINT FK_comment FOREIGN KEY(COMMENT_BOARD) REFERENCES MEMBER_BOARD(BOARD_NUM) ); -- MEMBER_BOARD는 게시판 테이블을, BOARD_NUM은 글번호를 나타낸다. -- 댓글 시퀀스 create sequence COMMENT_SEQ; | cs |
■ MainForm.jsp
메인화면에는 스크롤을 만들어주는 CSS 코드를 한 줄 추가해준다.
overflow:auto; 의 경우 내용이 div의 크기를 넘어서면 자동적으로 스크롤을 만들어주는 코드이다.
■ BoardDetailForm.jsp
상세보기 화면에서 댓글 목록을 보여주고, 댓글 작성을 하도록 만든다. 그러기 위해서는 html 코드 및 javascript 코드를 추가해야 한다.
먼저 댓글을 보여주는 html 코드이다.
172줄 : 댓글 목록이 있을 경우에만 화면에 보여준다.
173줄 : 댓글 목록을 for 문을 이용하여 화면에 출력한다.
177~181줄 : 댓글 작성자와 작성일을 보여주는 부분이다.
184~188줄 : 댓글 내용을 보여주는 부분이다.
190~199줄 : 댓글에 달린 버튼이다. 수정, 삭제의 경우 댓글 작성자가 로그인했을 경우만 보이도록 한다.
다음으로 댓글 작성 부분이다.
206줄 : 로그인했을 경우만 댓글 작성 화면이 보이게 한다. 이는 로그인한 사용자만 댓글을 작성 가능하게 한 것이다.
209~210줄 : 댓글 저장시 게시글 번호와 작성자 ID가 필요하다. 이것은 화면에는 보일 필요가 없으므로 hidden으로 처리한다.
212~216줄 : 로그인한 경우 자동적으로 아이디가 출력된다.
218~222줄 : 댓글 본문을 작성하는 부분이다.
224~228줄 : 댓글 등록 버튼이다. 클릭 시 함수 writeCmt( )가 실행된다.
스크립트 부분이다. 댓글 저장은 Ajax를 이용하였다. getXMLHttpRequest( ) 함수는 XMLHttpRequest 객체를 생성하는 역할을 한다.
다음으로 댓글을 등록하는 writeCmt( ) 함수이다.
79줄~81줄 : 게시글 번호, 댓글 내용, 댓글 작성자에 대한 정보를 가져와서 변수에 담는다.
83~86줄 : 댓글 내용이 입력되었는지 확인하는 부분이다. 입력되지 않은 상태에서 등록을 하려 하면 경고 창을 띄운다.
90줄 : 서버로 전달할 파라미터이다. 전달할 값은 게시글 번호, 댓글 내용, 댓글 작성자이다.
93줄 : XMLHttpRequest 상태 변화시 호출될 함수를 지정한다.
94줄 : 전송 방식, 전송할 경로, 동기/비동기를 지정한다.
95줄 : 한글 인코딩 처리를 한다.
96줄 : 서버로 파라미터를 전송한다.
서버로 전송 이후 호출되는 함수이다. 정상적으로 데이터를 전송하고, 결과를 받았을 경우 103~150줄이 실행된다.
105줄 : 서버에서 결과값 1을 받을 경우 게시글 상세보기 화면을 새로고침한다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 | <%@ page language="java" contentType="text/html; charset=EUC-KR" pageEncoding="EUC-KR"%> <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%> <html> <head> <title>글 상세보기</title> <style type="text/css"> #wrap { width: 800px; margin: 0 auto 0 auto; } #detailBoard{ text-align :center; } #title{ height : 16; font-family :'돋움'; font-size : 12; text-align :center; background-color: #F7F7F7; } #btn{ font-family :'돋움'; font-size : 14; text-align :center; } </style> <script type="text/javascript"> function changeView(value) { if(value == 0) location.href='BoardListAction.bo?page=${pageNum}'; else if(value == 1) location.href='BoardReplyFormAction.bo?num=${board.board_num}&page=${pageNum}'; } function doAction(value) { if(value == 0) // 수정 location.href="BoardUpdateFormAction.bo?num=${board.board_num}&page=${pageNum}"; else if(value == 1) // 삭제 location.href="BoardDeleteAction.bo?num=${board.board_num}"; } var httpRequest = null; // httpRequest 객체 생성 function getXMLHttpRequest(){ var httpRequest = null; if(window.ActiveXObject){ try{ httpRequest = new ActiveXObject("Msxml2.XMLHTTP"); } catch(e) { try{ httpRequest = new ActiveXObject("Microsoft.XMLHTTP"); } catch (e2) { httpRequest = null; } } } else if(window.XMLHttpRequest){ httpRequest = new window.XMLHttpRequest(); } return httpRequest; } // 댓글 등록 function writeCmt() { var form = document.getElementById("writeCommentForm"); var board = form.comment_board.value var id = form.comment_id.value var content = form.comment_content.value; if(!content) { alert("내용을 입력하세요."); return false; } else { var param="comment_board="+board+"&comment_id="+id+"&comment_content="+content; httpRequest = getXMLHttpRequest(); httpRequest.onreadystatechange = checkFunc; httpRequest.open("POST", "CommentWriteAction.co", true); httpRequest.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded;charset=EUC-KR'); httpRequest.send(param); } } function checkFunc(){ if(httpRequest.readyState == 4){ // 결과값을 가져온다. var resultText = httpRequest.responseText; if(resultText == 1){ document.location.reload(); // 상세보기 창 새로고침 } } } </script> </head> <body> <div id="wrap"> <br><br> <div id="board"> <table id="detailBoard" width="800" border="3" bordercolor="lightgray"> <tr> <td id="title">작성일</td> <td>${board.board_date}</td> </tr> <tr> <td id="title">작성자</td> <td>${board.board_id}</td> </tr> <tr> <td id="title"> 제 목 </td> <td> ${board.board_subject} </td> </tr> <tr> <td id="title"> 내 용 </td> <td> ${board.board_content} </td> </tr> <tr> <td id="title"> 첨부파일 </td> <td> <a href='FileDownloadAction.bo?file_name=${board.board_file}'>${board.board_file}</a> </td> </tr> <tr align="center" valign="middle"> <td colspan="5"> <c:if test="${sessionScope.sessionID !=null}"> <c:if test="${sessionScope.sessionID == board.board_id}"> <input type="button" value="수정" onclick="doAction(0)"> <input type="button" value="삭제" onclick="doAction(1)"> </c:if> <input type="button" value="답글" onclick="changeView(1)" > </c:if> <input type="button" value="목록" onclick="changeView(0)"> </td> <!-- javascript:location.href='BoardListAction.bo?page=${pageNum}' --> </tr> </table> </div> <br><br> <!-- 댓글 부분 --> <div id="comment"> <table border="1" bordercolor="lightgray"> <!-- 댓글 목록 --> <c:if test="${requestScope.commentList != null}"> <c:forEach var="comment" items="${requestScope.commentList}"> <tr> <!-- 아이디, 작성날짜 --> <td width="150"> <div> ${comment.comment_id}<br> <font size="2" color="lightgray">${comment.comment_date}</font> </div> </td> <!-- 본문내용 --> <td width="550"> <div class="text_wrapper"> ${comment.comment_content} </div> </td> <!-- 버튼 --> <td width="100"> <div id="btn" style="text-align:center;"> <a href="#">[답변]</a><br> <!-- 댓글 작성자만 수정, 삭제 가능하도록 --> <c:if test="${comment.comment_id == sessionScope.sessionID}"> <a href="#">[수정]</a><br> <a href="#">[삭제]</a> </c:if> </div> </td> </tr> </c:forEach> </c:if> <!-- 로그인 했을 경우만 댓글 작성가능 --> <c:if test="${sessionScope.sessionID !=null}"> <tr bgcolor="#F5F5F5"> <form id="writeCommentForm"> <input type="hidden" name="comment_board" value="${board.board_num}"> <input type="hidden" name="comment_id" value="${sessionScope.sessionID}"> <!-- 아이디--> <td width="150"> <div> ${sessionScope.sessionID} </div> </td> <!-- 본문 작성--> <td width="550"> <div> <textarea name="comment_content" rows="4" cols="70" ></textarea> </div> </td> <!-- 댓글 등록 버튼 --> <td width="100"> <div id="btn" style="text-align:center;"> <p><a href="#" onclick="writeCmt()">[댓글등록]</a></p> </div> </td> </form> </tr> </c:if> </table> </div> </div> </body> </html> | cs |
■ CommentBean.java
댓글 테이블의 칼럼 항목을 모두 변수로 만들어준다. 그리고 답글의 깊이를 가질 level이라는 변수도 추가로 만들어준다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 | package jsp.board.comment.model; import java.sql.Date; public class CommentBean { private int comment_num; // 댓글 글번호 private int comment_board; // 게시글 번호 private String comment_id; // 댓글 작성자 private Date comment_date; // 댓글 작성일 private int comment_parent; // 부모글 private String comment_content; // 댓글 내용 private int comment_level; // 댓글- 답변글 깊이 public int getComment_num() { return comment_num; } public void setComment_num(int comment_num) { this.comment_num = comment_num; } public int getComment_board() { return comment_board; } public void setComment_board(int comment_board) { this.comment_board = comment_board; } public String getComment_id() { return comment_id; } public void setComment_id(String comment_id) { this.comment_id = comment_id; } public Date getComment_date() { return comment_date; } public void setComment_date(Date comment_date) { this.comment_date = comment_date; } public int getComment_parent() { return comment_parent; } public void setComment_parent(int comment_parent) { this.comment_parent = comment_parent; } public String getComment_content() { return comment_content; } public void setComment_content(String comment_content) { this.comment_content = comment_content; } public int getComment_level() { return comment_level; } public void setComment_level(int comment_level) { this.comment_level = comment_level; } } | cs |
■ CommentController.java
BoardController 및 GuestbookController와 동일하다. 차이점은 위의 init( ) 부분이다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 | package jsp.board.comment.action; import java.io.IOException; import java.util.Enumeration; import java.util.HashMap; import java.util.ResourceBundle; import javax.servlet.RequestDispatcher; import javax.servlet.ServletConfig; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import jsp.common.action.Action; import jsp.common.action.ActionForward; public class CommentController extends HttpServlet { private static final long serialVersionUID = 1L; private HashMap<String,Action> commandMap; /** * 최초 실행 init */ public void init(ServletConfig config) throws ServletException { loadProperties("jsp/board/comment/properties/CommentCommand"); } /** * 프로퍼티 파일에서 키값과 클래스 정보를 추출하여 그것을 Map에 저장한다. * @param filePath 프로퍼티 파일의 경로 */ private void loadProperties(String filePath) { commandMap = new HashMap<String, Action>(); ResourceBundle rb = ResourceBundle.getBundle(filePath); Enumeration<String> actionEnum = rb.getKeys(); // 키값을 가져온다. while (actionEnum.hasMoreElements()) { // 명령어를 가져온다. String command = actionEnum.nextElement(); // 명령어에 해당하는 Action 클래스 이름을 가져온다. String className = rb.getString(command); try { Class actionClass = Class.forName(className); // 클래스 생성 Action actionInstance = (Action)actionClass.newInstance(); // 클래스의 객체를 생성 // 맵에 명령어와 Action을 담는다. commandMap.put(command, actionInstance); } catch (Exception e) { e.printStackTrace(); } } } /** * GET 방식일 경우 doGet() */ public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doProcess(request,response); } /** * POST 방식일 경우 doPost() */ public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doProcess(request,response); } /** * 명령어에 따른 해당 Action을 지정해 준다. * @param request * @param response * @throws ServletException * @throws IOException */ private void doProcess(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // 넘어온 커맨드를 추출하는 과정 String requestURI = request.getRequestURI(); int cmdIdx = requestURI.lastIndexOf("/") + 1; String command = requestURI.substring(cmdIdx); // URI, command 확인 // System.out.println("requestURI : "+requestURI); //System.out.println("Board cmd : "+command); ActionForward forward = null; Action action = null; try { // 맵에서 명령어에 해당하는 Action을 가져온다. action = commandMap.get(command); if (action == null) { System.out.println("명령어 : "+command+"는 잘못된 명령입니다."); return; } forward = action.execute(request, response); /* * 화면이동 - isRedirext() 값에 따라 sendRedirect 또는 forward를 사용 * sendRedirect : 새로운 페이지에서는 request와 response객체가 새롭게 생성된다. * forward : 현재 실행중인 페이지와 forwad에 의해 호출될 페이지는 request와 response 객체를 공유 */ if(forward != null){ if (forward.isRedirect()) { response.sendRedirect(forward.getNextPath()); } else { RequestDispatcher dispatcher = request .getRequestDispatcher(forward.getNextPath()); dispatcher.forward(request, response); } } } catch (Exception e) { e.printStackTrace(); } } // end doProcess } | cs |
■ CommentWriteAction.java
댓글 작성 Action이다.
먼저 상세보기 화면에서 넘어온 파라미터 값을 가져온다.
가져온 파리미터 값을 CommentBean에 세팅한다.
32줄 : 댓글의 글번호는 시퀀스 값을 사용한다.
32줄 : 댓글을 저장한다.
정상적으로 저장되면 화면으로 1을 전달한다. Ajax를 이용하기 때문에 화면을 이동시킬 필요가 없다. 그래서 ActionForward를 사용할 필요가 없기에 retrun 값을 null로 지정한다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 | package jsp.board.comment.action; import java.io.PrintWriter; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import jsp.board.comment.model.CommentBean; import jsp.board.comment.model.CommentDAO; import jsp.common.action.Action; import jsp.common.action.ActionForward; public class CommentWriteAction implements Action { @Override public ActionForward execute(HttpServletRequest request, HttpServletResponse response) throws Exception { CommentDAO dao = CommentDAO.getInstance(); CommentBean comment = new CommentBean(); // 파리미터 값을 가져온다. int comment_board = Integer.parseInt(request.getParameter("comment_board")); String comment_id = request.getParameter("comment_id"); String comment_content = request.getParameter("comment_content"); comment.setComment_num(dao.getSeq()); // 댓글 번호는 시퀀스값으로 comment.setComment_board(comment_board); comment.setComment_id(comment_id); comment.setComment_content(comment_content); boolean result = dao.insertComment(comment); if(result){ response.setContentType("text/html;charset=euc-kr"); PrintWriter out = response.getWriter(); out.println("1"); out.close(); } return null; } } | cs |
■ CommentDAO.java
댓글의 글 번호를 부여하는 시퀀스를 가져오는 메서드이다.
댓글을 저장하는 부분이다. 다른 DAO와 동일하게 처리되어있다.
댓글 목록을 가져오는 getCommentList( )이다. 인자로는 게시글의 글 번호를 넘겨받는다. 그리고 댓글 목록을 담을 ArrayList를 만든다.
124~130줄 : 계층 쿼리를 이용하여 댓글을 검색한다.
133줄 : 게시글의 글 번호를 쿼리에 세팅한다.
136~146줄 : 댓글 정보를 CommentBean에 세팅하고 그것을 ArrayList에 추가한다.
댓글 목록을 가져오면 그것을 리턴한다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 | package jsp.board.comment.model; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.util.ArrayList; import jsp.common.util.DBConnection; public class CommentDAO { private Connection conn; private PreparedStatement pstmt; private ResultSet rs; private static CommentDAO instance; private CommentDAO(){} public static CommentDAO getInstance(){ if(instance==null) instance=new CommentDAO(); return instance; } // 시퀀스를 가져온다. public int getSeq() { int result = 1; try { conn = DBConnection.getConnection(); // 시퀀스 값을 가져온다. (DUAL : 시퀀스 값을 가져오기위한 임시 테이블) StringBuffer sql = new StringBuffer(); sql.append("SELECT COMMENT_SEQ.NEXTVAL FROM DUAL"); pstmt = conn.prepareStatement(sql.toString()); rs = pstmt.executeQuery(); // 쿼리 실행 if (rs.next()) result = rs.getInt(1); } catch (Exception e) { throw new RuntimeException(e.getMessage()); } close(); return result; } // end getSeq // 댓글 등록 public boolean insertComment(CommentBean comment) { boolean result = false; try { conn = DBConnection.getConnection(); // 자동 커밋을 false로 한다. conn.setAutoCommit(false); StringBuffer sql = new StringBuffer(); sql.append("INSERT INTO BOARD_COMMENT"); sql.append(" (COMMENT_NUM, COMMENT_BOARD, COMMENT_ID, COMMENT_DATE"); sql.append(" , COMMENT_PARENT, COMMENT_CONTENT)"); sql.append(" VALUES(?,?,?,sysdate,?,?)"); pstmt = conn.prepareStatement(sql.toString()); pstmt.setInt(1, comment.getComment_num()); pstmt.setInt(2, comment.getComment_board()); pstmt.setString(3, comment.getComment_id()); pstmt.setInt(4, comment.getComment_parent()); pstmt.setString(5, comment.getComment_content()); int flag = pstmt.executeUpdate(); if(flag > 0){ result = true; conn.commit(); // 완료시 커밋 } } catch (Exception e) { try { conn.rollback(); // 오류시 롤백 } catch (SQLException sqle) { sqle.printStackTrace(); } e.printStackTrace(); throw new RuntimeException(e.getMessage()); } close(); return result; } // end boardInsert(); // 댓글 목록 가져오기 public ArrayList<CommentBean> getCommentList(int boardNum) { ArrayList<CommentBean> list = new ArrayList<CommentBean>(); try { conn = DBConnection.getConnection(); /* 댓글의 페이지 처리를 하고싶다면 이 쿼리를 사용하면 된다. * SELECT * FROM * (SELECT ROWNUM AS rnum, * data.* * FROM * (SELECT LEVEL, * COMMENT_NUM, * COMMENT_BOARD, * COMMENT_ID, * COMMENT_DATE, * COMMENT_PARENT, * COMMENT_CONTENT * FROM BOARD_COMMENT * WHERE COMMENT_BOARD = ? * START WITH COMMENT_PARENT = 0 * CONNECT BY PRIOR COMMENT_NUM = COMMENT_PARENT) * data) * WHERE rnum>=? and rnum<=? ; */ StringBuffer sql = new StringBuffer(); sql.append(" SELECT LEVEL, COMMENT_NUM, COMMENT_BOARD,"); sql.append(" COMMENT_ID, COMMENT_DATE,"); sql.append(" COMMENT_PARENT, COMMENT_CONTENT"); sql.append(" FROM BOARD_COMMENT"); sql.append(" WHERE COMMENT_BOARD = ?"); sql.append(" START WITH COMMENT_PARENT = 0"); sql.append(" CONNECT BY PRIOR COMMENT_NUM = COMMENT_PARENT"); pstmt = conn.prepareStatement(sql.toString()); pstmt.setInt(1, boardNum); rs = pstmt.executeQuery(); while(rs.next()) { CommentBean comment = new CommentBean(); comment.setComment_level(rs.getInt("LEVEL")); comment.setComment_num(rs.getInt("COMMENT_NUM")); comment.setComment_board(rs.getInt("COMMENT_BOARD")); comment.setComment_id(rs.getString("COMMENT_ID")); comment.setComment_date(rs.getDate("COMMENT_DATE")); comment.setComment_parent(rs.getInt("COMMENT_PARENT")); comment.setComment_content(rs.getString("COMMENT_CONTENT")); list.add(comment); } } catch (Exception e) { e.printStackTrace(); throw new RuntimeException(e.getMessage()); } close(); return list; } // end getCommentList // DB 자원해제 private void close() { try { if ( pstmt != null ){ pstmt.close(); pstmt=null; } if ( conn != null ){ conn.close(); conn=null; } } catch (Exception e) { throw new RuntimeException(e.getMessage()); } } // end close() } | cs |
■ BoardDetailAction.java
게시글 상세보기 Action에는 댓글을 가져오는 코드를 추가해준다.
34~35줄 : 게시글 번호를 이용하여 해당 글에 달린 댓글 목록을 가져온다.
38줄 : 댓글이 1개라도 있다면 그것을 request에 세팅한다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 | package jsp.board.action; import java.util.ArrayList; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import jsp.board.comment.model.CommentBean; import jsp.board.comment.model.CommentDAO; import jsp.board.model.BoardBean; import jsp.board.model.BoardDAO; import jsp.common.action.Action; import jsp.common.action.ActionForward; public class BoardDetailAction implements Action { @Override public ActionForward execute(HttpServletRequest request, HttpServletResponse response) throws Exception { ActionForward forward = new ActionForward(); // 파라미터로 넘어온 글번호를 가져온다. String num = request.getParameter("num"); int boardNum = Integer.parseInt(num); String pageNum = request.getParameter("pageNum"); BoardDAO dao = BoardDAO.getInstance(); BoardBean board = dao.getDetail(boardNum); boolean result = dao.updateCount(boardNum); // 게시글 번호를 이용하여 해당 글에 있는 댓글 목록을 가져온다. CommentDAO commentDAO = CommentDAO.getInstance(); ArrayList<CommentBean> commentList = commentDAO.getCommentList(boardNum); // 댓글이 1개라도 있다면 request에 commentList를 세팅한다. if(commentList.size() > 0) request.setAttribute("commentList", commentList); request.setAttribute("board", board); request.setAttribute("pageNum", pageNum); if(result){ forward.setRedirect(false); // 단순한 조회이므로 forward.setNextPath("BoardDetailForm.bo"); } return forward; } } | cs |
■ CommentCommand.properties
프로퍼티에는 댓글 저장 명령어를 추가한다.
1 2 3 4 5 | # Form Change # Action CommentWriteAction.co=jsp.board.comment.action.CommentWriteAction | cs |
■ web.xml
web.xml에는 <servlet>과 <servlet-mapping>을 추가해준다.
<servlet>에 댓글 Controller을 추가한다.
<servlet-mapping>에 댓글의 명령어를 추가한다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 | <?xml version="1.0" encoding="UTF-8"?> <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" id="WebApp_ID" version="2.5"> <display-name>JSP_create</display-name> <servlet> <description>Controller</description> <display-name>MemberController</display-name> <servlet-name>MemberController</servlet-name> <servlet-class>jsp.member.action.MemberController</servlet-class> </servlet> <servlet> <description>Controller</description> <display-name>BoardController</display-name> <servlet-name>BoardController</servlet-name> <servlet-class>jsp.board.action.BoardController</servlet-class> </servlet> <servlet> <description>Controller</description> <display-name>CommentController</display-name> <servlet-name>CommentController</servlet-name> <servlet-class>jsp.board.comment.action.CommentController</servlet-class> </servlet> <servlet> <description>Controller</description> <display-name>GuestbookController</display-name> <servlet-name>GuestbookController</servlet-name> <servlet-class>jsp.guestbook.action.GuestbookController</servlet-class> </servlet> <servlet-mapping> <servlet-name>MemberController</servlet-name> <url-pattern>*.do</url-pattern> </servlet-mapping> <servlet-mapping> <servlet-name>BoardController</servlet-name> <url-pattern>*.bo</url-pattern> </servlet-mapping> <servlet-mapping> <servlet-name>CommentController</servlet-name> <url-pattern>*.co</url-pattern> </servlet-mapping> <servlet-mapping> <servlet-name>GuestbookController</servlet-name> <url-pattern>*.ge</url-pattern> </servlet-mapping> <listener> <listener-class>jsp.visit.action.VisitSessionListener</listener-class> </listener> <resource-ref> <description>connection</description> <res-ref-name>jdbc/orcl</res-ref-name> <res-type>javax.sql.DataSource</res-type> <res-auth>Container</res-auth> </resource-ref> </web-app> | cs |
3. 실행 결과
4번이라는 제목의 글에 댓글을 작성할 것이다. 로그인을 하지 않았을 경우 댓글 작성 부분이 보이지 않는다.
로그인을 하면 댓글 작성이 가능하다. 댓글 작성 후 [댓글등록]을 누른다.
댓글이 등록된 것을 확인할 수 있다.
로그아웃할 경우 댓글은 보이지만 댓글 작성 부분은 사라진다.
4. 소스코드 다운로드 (war 파일)
'코딩 > JSP' 카테고리의 다른 글
[JSP개발] 게시판 - 댓글 삭제 (1) | 2017.01.04 |
---|---|
[JSP개발] 게시판 - 댓글 답변 구현 (4) | 2017.01.03 |
[JSP개발] 게시판 - 방명록 수정 (15) | 2017.01.01 |
[JSP개발] 게시판 - 방명록 삭제 (0) | 2016.12.29 |
[JSP개발] 게시판 - 방명록 답글 달기 (0) | 2016.12.28 |