이번에는 답글달기인 reply.jsp 와 reply_ok.jsp 를 만들겠습니다.
답글달기는 기존 글쓰기와는 다른점이 있습니다.
답글은 원게시물보다 아래에 출력이 되야하며 원게시물보다 들여쓰기가 되야합니다.
원게시물과 답글과의 출력순서를 위해 데이터베이스에 3가지의 필드를 추가시키겠습니다.
데이터베이스에 ref, indent, step 을 추가시킵니다. 형식은 int 즉 숫자 입니다.
ref는 부모의 글번호를 저장하는 필드이고
indent는 원글의 답글인지 답글의 답글인지를 구분하기위한 들여쓰기 입니다.
그리고 step은 같은 답글끼리의 출력순서를 위한 필드입니다.
우선 데이터베이스에 필드를 추가시키겠습니다.
기본값은 0으로 해놨습니다.
새로운 필드가 생겼기 때문에 write.jsp와 list.jsp도 수정해야하지만 답글을 완성후에 수정하도록 하겠습니다.
그리고 답글쓰기인 reply.jsp의 특징은 원글의 제목을 불러와서 입력이 되있어야 합니다.
본격적으로 reply.jsp파일과 relpy_ok.jsp을 생성후에 reply.jsp를 열어서 코드를 추가시킵니다.
<%@ page language="java" contentType="text/html; charset=EUC-KR"
pageEncoding="EUC-KR"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>게시판</title>
</head>
<body>
<table>
<tr>
<td>
<table width="100%" cellpadding="0" cellspacing="0" border="0">
<tr style="background:url('img/table_mid.gif') repeat-x; text-align:center;">
<td width="5"><img src="img/table_left.gif" width="5" height="30" /></td>
<td>답글</td>
<td width="5"><img src="img/table_right.gif" width="5" height="30" /></td>
</tr>
</table>
<table>
<tr>
<td> </td>
<td align="center">제목</td>
<td><input name="subject" size="50" maxlength="100"></td>
<td> </td>
</tr>
<tr height="1" bgcolor="#dddddd"><td colspan="4"></td></tr>
<tr>
<td> </td>
<td align="center">이름</td>
<td><input name="name" size="50" maxlength="50"></td>
<td> </td>
</tr>
<tr height="1" bgcolor="#dddddd"><td colspan="4"></td></tr>
<tr>
<td> </td>
<td align="center">비밀번호</td>
<td><input name="name" size="50" maxlength="50"></td>
<td> </td>
</tr>
<tr height="1" bgcolor="#dddddd"><td colspan="4"></td></tr>
<tr>
<td> </td>
<td align="center">내용</td>
<td><textarea name="contents" cols="50" rows="13"></textarea></td>
<td> </td>
</tr>
<tr height="1" bgcolor="#dddddd"><td colspan="4"></td></tr>
<tr height="1" bgcolor="#82B5DF"><td colspan="4"></td></tr>
<tr align="center">
<td> </td>
<td colspan="2"><input type=button value="등록">
<input type=button value="취소">
<td> </td>
</tr>
</table>
</td>
</tr>
</table>
</body>
</html>
코드를 입력하시고 실행시키면
아직 제목에는 아무것도 없습니다. 연동을 안시켰기때문에..
이제 코드를 추가시키겠습니다.
<%@ page import="java.sql.*"%>
SQL문을 이용하기 위한 import
<script language = "javascript"> // 자바 스크립트 시작
function replyCheck()
{
var form = document.replyform;
if( !form.name.value ) // form 에 있는 name 값이 없을 때
{
alert( "이름을 적어주세요" ); // 경고창 띄움
form.name.focus(); // form 에 있는 name 위치로 이동
return;
}
if( !form.password.value )
{
alert( "비밀번호를 적어주세요" );
form.password.focus();
return;
}
if( !form.title.value )
{
alert( "제목을 적어주세요" );
form.title.focus();
return;
}
if( !form.memo.value )
{
alert( "내용을 적어주세요" );
form.memo.focus();
return;
}
form.submit();
}
</script>
자바스크립트 내용
<%
int idx = Integer.parseInt(request.getParameter("idx"));
Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");
String url = "jdbc:odbc:board2";
String id = "";
String pass = "";
String title = "";
try {
Connection conn = DriverManager.getConnection(url,id,pass);
Statement stmt = conn.createStatement();
String sql = "SELECT TITLE FROM board WHERE NUM=" + idx;
ResultSet rs = stmt.executeQuery(sql);
if(rs.next()){
title = rs.getString(1);
}
rs.close();
stmt.close();
conn.close();
} catch(SQLException e) {
}
%>
view.jsp 에서 보낸 idx을 받아오고 SQL문을 이용해 idx값에 있는 title을 받아옵니다.
<form name=replyform method=post action="reply_ok.jsp?idx=<%=idx%>">
replys_ok.jsp 에 Get방식으로 idx를 추가해서 전송합니다.
<tr>
<td> </td>
<td align="center">제목</td>
<td><input name="title" size="50" maxlength="100" value = "<%=title%>"></td>
<td> </td>
</tr>
제목에는 받아온 title을 입력해놓습니다.
<input type=button value="등록" OnClick="javascript:replyCheck();">
<input type=button value="취소" OnClick="javascript:history.back(-1)">
버튼에 링크를 겁니다.
이제 list.jsp를 실행시켜서 확인을 해보겠습니다.
아 그러기전에 view.jsp 에 링크를 안시켰군요
<input type=button value="답글" OnClick="window.location='reply.jsp?idx=<%=idx%>'">
제목이 잘 입력이 되있네요.
reply.jsp의 최종 코드
<%@ page language="java" contentType="text/html; charset=EUC-KR"
pageEncoding="EUC-KR"%>
<%@ page import="java.sql.*"%>
<script language = "javascript"> // 자바 스크립트 시작
function replyCheck()
{
var form = document.replyform;
if( !form.name.value ) // form 에 있는 name 값이 없을 때
{
alert( "이름을 적어주세요" ); // 경고창 띄움
form.name.focus(); // form 에 있는 name 위치로 이동
return;
}
if( !form.password.value )
{
alert( "비밀번호를 적어주세요" );
form.password.focus();
return;
}
if( !form.title.value )
{
alert( "제목을 적어주세요" );
form.title.focus();
return;
}
if( !form.memo.value )
{
alert( "내용을 적어주세요" );
form.memo.focus();
return;
}
form.submit();
}
</script>
<%
int idx = Integer.parseInt(request.getParameter("idx"));
Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");
String url = "jdbc:odbc:board2";
String id = "";
String pass = "";
String title = "";
try {
Connection conn = DriverManager.getConnection(url,id,pass);
Statement stmt = conn.createStatement();
String sql = "SELECT TITLE FROM board WHERE NUM=" + idx;
ResultSet rs = stmt.executeQuery(sql);
if(rs.next()){
title = rs.getString(1);
}
rs.close();
stmt.close();
conn.close();
} catch(SQLException e) {
}
%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>게시판</title>
</head>
<body>
<table>
<form name=replyform method=post action="reply_ok.jsp?idx=<%=idx%>">
<tr>
<td>
<table width="100%" cellpadding="0" cellspacing="0" border="0">
<tr style="background:url('img/table_mid.gif') repeat-x; text-align:center;">
<td width="5"><img src="img/table_left.gif" width="5" height="30" /></td>
<td>답글</td>
<td width="5"><img src="img/table_right.gif" width="5" height="30" /></td>
</tr>
</table>
<table>
<tr>
<td> </td>
<td align="center">제목</td>
<td><input name="title" size="50" maxlength="100" value = "<%=title%>"></td>
<td> </td>
</tr>
<tr height="1" bgcolor="#dddddd"><td colspan="4"></td></tr>
<tr>
<td> </td>
<td align="center">이름</td>
<td><input name="name" size="50" maxlength="50"></td>
<td> </td>
</tr>
<tr height="1" bgcolor="#dddddd"><td colspan="4"></td></tr>
<tr>
<td> </td>
<td align="center">비밀번호</td>
<td><input name="password" size="50" maxlength="50"></td>
<td> </td>
</tr>
<tr height="1" bgcolor="#dddddd"><td colspan="4"></td></tr>
<tr>
<td> </td>
<td align="center">내용</td>
<td><textarea name="memo" cols="50" rows="13"></textarea></td>
<td> </td>
</tr>
<tr height="1" bgcolor="#dddddd"><td colspan="4"></td></tr>
<tr height="1" bgcolor="#82B5DF"><td colspan="4"></td></tr>
<tr align="center">
<td> </td>
<td colspan="2"><input type=button value="등록" OnClick="javascript:replyCheck();">
<input type=button value="취소" OnClick="javascript:history.back(-1)">
<td> </td>
</tr>
</table>
</td>
</tr>
</table>
</body>
</html>
이제 reply_ok.jsp를 열어서 코드를 삽입합니다.
<%@ page import="java.sql.*"%>
SQL문을 이용하기 위한 import
<%
request.setCharacterEncoding("euc-kr");
Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");
String url = "jdbc:odbc:board2";
String id = "";
String pass = "";
String name = request.getParameter("name");
String password = request.getParameter("password");
String title = request.getParameter("title");
String memo = request.getParameter("memo");
int idx = Integer.parseInt(request.getParameter("idx"));
try {
int ref = 0;
int indent = 0;
int step = 0;
Connection conn = DriverManager.getConnection(url,id,pass);
Statement stmt = conn.createStatement();
String sql = "SELECT REF, INDENT, STEP FROM board WHERE NUM=" + idx;
ResultSet rs = stmt.executeQuery(sql);
if(rs.next()) {
ref = rs.getInt(1);
indent = rs.getInt(2);
step = rs.getInt(3);
}
select문을 이용해서 idx 즉 원글의 ref, indent, step값을 가져옵니다.
sql = "UPDATE board SET STEP=STEP+1 where REF="+ref+" and STEP>" +step;
stmt.executeUpdate(sql);
Update문을 이용해서 ref값이 불러온 ref와 같고 step이 불러온 step값보다 큰 자료들의 step을 +1 시키게 됩니다.
sql = "INSERT INTO board(USERNAME, PASSWORD, TITLE, MEMO, REF, INDENT, STEP) "+
"values(?,?,?,?,?,?,?)";
PreparedStatement pstmt = conn.prepareStatement(sql);
pstmt.setString(1, name);
pstmt.setString(2, password);
pstmt.setString(3, title);
pstmt.setString(4, memo);
pstmt.setInt(5, ref);
pstmt.setInt(6, indent+1);
pstmt.setInt(7, step+1);
pstmt.execute();
rs.close();
stmt.close();
pstmt.close();
conn.close();
}catch(Exception e) {
}
%>
insert문을 이용해서 데이터베이스에 자료를 입력합니다. reply.jsp에서 가져온 값들과 select문을 이용한 값들을 넣어 주되 ref는 같은 값을 넣고 indent와 step은 원글의 값보다 +1 시켜서 넣게 됩니다.
<script language=javascript>
self.window.alert("입력한 글을 저장하였습니다.");
location.href="list.jsp";
</script>
입력이 완료되면 목록으로 가게 됩니다.
reply_ok.jsp 최종코드
<%@ page language="java" contentType="text/html; charset=EUC-KR"
pageEncoding="EUC-KR"%>
<%@ page import="java.sql.*"%>
<%
request.setCharacterEncoding("euc-kr");
Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");
String url = "jdbc:odbc:board2";
String id = "";
String pass = "";
String name = request.getParameter("name");
String password = request.getParameter("password");
String title = request.getParameter("title");
String memo = request.getParameter("memo");
int idx = Integer.parseInt(request.getParameter("idx"));
try {
int ref = 0;
int indent = 0;
int step = 0;
Connection conn = DriverManager.getConnection(url,id,pass);
Statement stmt = conn.createStatement();
String sql = "SELECT REF, INDENT, STEP FROM board1 WHERE NUM=" + idx;
ResultSet rs = stmt.executeQuery(sql);
if(rs.next()) {
ref = rs.getInt(1);
indent = rs.getInt(2);
step = rs.getInt(3);
}
sql = "UPDATE board1 SET STEP=STEP+1 where REF="+ref+" and STEP>" +step;
stmt.executeUpdate(sql);
sql = "INSERT INTO board1(USERNAME, PASSWORD, TITLE, MEMO, REF, INDENT, STEP) "+
"values(?,?,?,?,?,?,?)";
PreparedStatement pstmt = conn.prepareStatement(sql);
pstmt.setString(1, name);
pstmt.setString(2, password);
pstmt.setString(3, title);
pstmt.setString(4, memo);
pstmt.setInt(5, ref);
pstmt.setInt(6, indent+1);
pstmt.setInt(7, step+1);
pstmt.execute();
rs.close();
stmt.close();
pstmt.close();
conn.close();
}catch(Exception e) {
}
%>
<script language=javascript>
self.window.alert("입력한 글을 저장하였습니다.");
location.href="list.jsp";
</script>
모든 코드를 입력하고 list.jsp를 실행시켜서 답글을 달아보도록 하겠습니다.
테스트1번 글에 답글누르고 글을 작성했습니다.
현재는 글번호로 내림차순 정렬이 되어있기 때문에 원글보다 위로 가있는걸 확인할 수 있습니다.
그래도 확인겸 데이터베이스를 보겠습니다.
보시면 indent와 step이 원글보다 +1 된걸 확인하실수 있지만
ref는 그대로 0인걸 보실수 있습니다. 이유는 원글의 ref가 0이기 때문입니다.
우선 수작업으로 원글과 답글의 값을 1로 저장하겠습니다.
왜냐하면 아직 글쓰기 파일인 write.jsp파일을 수정을 안했기 때문에 ref는 0으로 들어가기때문입니다.
부모글을 1로 바꿨기 때문에 답글의 답글을 한번 달아보겠습니다.
5번 게시물은 1번의 답글의 답글을 단 게시물입니다. ref는 원글의 값을 가져갔고 indent와 step은 2가 된걸 확인할 수 있습니다.
이제 write_ok.jsp로 가서 ref값을 추가시키겠습니다.
int max = 0;
try {
Connection conn = DriverManager.getConnection(url,id,pass);
Statement stmt = conn.createStatement();
String sql = "SELECT MAX(NUM) FROM board";
ResultSet rs = stmt.executeQuery(sql);
if(rs.next()){
max=rs.getInt(1);
}
sql = "INSERT INTO board(USERNAME,PASSWORD,TITLE,MEMO,REF) VALUES(?,?,?,?,?)";
PreparedStatement pstmt = conn.prepareStatement(sql);
pstmt.setString(1, name);
pstmt.setString(2, password);
pstmt.setString(3, title);
pstmt.setString(4, memo);
pstmt.setInt(5, max+1);
pstmt.execute();
pstmt.close();
stmt.close();
conn.close();
} catch(SQLException e) {
out.println( e.toString() );
}
write_ok.jsp의 중간에 추가시킨 내용들입니다.
int max라는 변수를 선언했고
select문으로 Num의 max값을 받아왔습니다. 왜냐하면 글번호는 현재의 제일 높은 번호보다 +1이 되어 만들어지기 때문에 자신의 글번호를 ref넣기 위한 방법입니다.
그리고 insert문에 ref값을 추가시키고 값은 max+1을 해서 삽입합니다.
이제 출력순서를 바꿔주기 위해 list.jsp를 손보도록 하겠습니다.
String sqlList = "SELECT NUM, USERNAME, TITLE, TIME, HIT, INDENT from board order by REF DESC, STEP ASC";
list.jsp의 select문에 indent를 추가검색 합니다. 또한 기존에는 Num즉 글번호를 이용한 정렬이였지만 답글이 있기 때문에 글번호정렬이 아닌 REF와 STEP을 이용한 정렬을 하겠습니다.
Ref즉 원글의 글번호를 기준으로 내림차순, Step을 기준으로 오름차순을 합니다.
그리고 답글인지를 표시하기 위해 이미지를 한개 더 추가시키고 들여쓰기를 하도록 코드를 추가시킵니다.
<td align="left">
<%
for(int j=0;j<indent;j++){
%> <%
}
if(indent!=0){
%> <img src='img/reply_icon.gif' />
<%
}
%>
<a href="view.jsp?idx=<%=idx%>"><%=title %></td>
중간에 보시면 title을 출력하는곳에 이렇게 코드를 추가시킵니다. 그리고 이미지를 img폴더에 추가시킵니다.
반복문을 이용해서 들여쓰기를 넣었고, 답글일경우 이미지를 표시하도록 조건문을 걸었습니다.
이제 list.jsp를 실행하도록 하겠습니다.
답글이 순서대로 잘 달리고 있는걸 확인했습니다.
이제 남은건 페이징처리가 남아있네요
이미지출처 : 판다의 이상한 블로그(http://ssppmm.tistory.com/)