모델 1 게시판
모델 1이란 JSP안의 자바 코드를 떼어 내 자바 빈즈로 만든 코드를 말한다. 이전 절의 게시판 코드는 JSP안에 JDBC 코드가 포함되어 있다. 이런 코드는 악몽이라 불리는 코드로, 최소한 JDBC 관련 코드는 자바 빈즈에 있어야 한다. 모델 1 게시판으로 수정하기 위해 먼저 게시글 정보를 담기 위한 자바 빈즈를 다음과 같이 생성한다.
Article.java
package net.java_school.board;
import java.util.Date;
public class Article {
public static final String LINE_SEPARATOR = System.getProperty("line.separator");
private int no;
private String title;
private String content;
private Date wdate;
private int parent;
private int indent;
public int getNo() {
return no;
}
public void setNo(int no) {
this.no = no;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getContent() {
if (content == null) content = "";
return content;
}
public void setContent(String content) {
this.content = content;
}
public String getHtmlContent() {
if (content == null) {
return "";
} else {
return content.replaceAll(LINE_SEPARATOR, "<br />");
}
}
public Date getWdate() {
return wdate;
}
public void setWdate(Date wdate) {
this.wdate = wdate;
}
public int getParent() {
return parent;
}
public void setParent(int parent) {
this.parent = parent;
}
public int getIndent() {
return indent;
}
public void setIndent(int indent) {
this.indent = indent;
}
}
Article.java의 필드는 board 테이블의 컬럼과 매핑된다. board 테이블에서 indent 컬럼이 없다. indent 필드는 목록(list.jsp)에서 목록 아이템을 들여쓰기할 때 필요하다.
getHtmlContent() 메소드는 content 컬럼에 저장되어 있는 개행문자를 <br />로 바꾸는 메소드이다. 이 메소드는 상세보기(view.jsp)에서 사용된다.
public static final String LINE_SEPARATOR = System.getProperty("line.separator");
LINE_SEPARATOR 상수는 getHtmlContent() 메소드에서 사용한다.
여기서 자바 프로그램에서 상수를 관리하는 팁을 소개한다.
WebContants.java
package net.java_school.commons;
public class WebContants {
//Line Separator
public final static String LINE_SEPARATOR = System.getProperty("line.separator");
}
이렇게 수정하면 Article에서 LINE_SEPARATOR 선언을 제거해야 하고 Article의 getHtmlContent() 메소드는 다음과 같이 수정해야 한다.
//.. 중간 생략 ..
import net.java_school.commons.WebContants;
public class Article {
//public static final String LINE_SEPARATOR = System.getProperty("line.separator"); 제거한다.
//.. 중간 생략 ..
public String getHtmlContent() {
if (content == null) {
return "";
} else {
return content.replaceAll(WebContants.LINE_SEPARATOR, "<br />");
}
}
//.. 중간 생략 ..
}
WebContants 클래스를 enum으로 바꿀 수 있다.
WebContants.java
package net.java_school.commons;
public enum WebContants {
lineSeparator (System.getProperty("line.separator"));
public String value;
WebContants (String value) {
this.value = value;
}
}
enum으로 바꾸면 Article 클래스는 다음과 같이 바뀐다.
//.. 중간 생략 ..
import net.java_school.commons.WebContants;
public class Article {
//.. 중간 생략 ..
public String getHtmlContent() {
if (content == null) {
return "";
} else {
return content.replaceAll(WebContants.lineSeparator.value, "<br />");
}
}
//.. 중간 생략 ..
}
다음으로 JDBC를 담당하는 BoardDao 빈즈를 작성한다. 이름 뒤에 Dao는 Data Access Object의 약자이다. 이와 같은 이름을 가진 빈은 JDBC 관련 코드만을 지녀야 한다. 이를 DAO 패턴이라 한다.
BoardDao.java
package net.java_school.board;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.List;
import java.util.ArrayList;
import net.java_school.db.dbpool.OracleConnectionManager;
import net.java_school.util.Log;
public class BoardDao {
private OracleConnectionManager dbmgr;
public BoardDao() {}
public BoardDao() {
this.dbmgr = dbmgr;
}
private Connection getConnection() throws SQLException {
return dbmgr.getConnection();
}
private void close(ResultSet rs, PreparedStatement stmt, Connection con) {
if (rs != null) {
try {
rs.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (stmt != null) {
try {
stmt.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (con != null) {
dbmgr.freeConnection(con);
}
}
public List<Article> getBoardList(int start, int end, String keyword) {
Log log = new Log();
List<Article> list = new ArrayList<Article>();
String sql = null;
sql = "SELECT no, indent, parent, title, wdate FROM " +
"(SELECT ROWNUM R, A.* " +
"FROM " +
"(SELECT no, level as indent, parent, title, wdate FROM board ";
if (keyword != null && !keyword.equals("")) {
sql += " WHERE title LIKE '%" + keyword + "%' OR content LIKE '%" + keyword + "%' ";
}
sql += "START WITH parent = 0 " +
"CONNECT BY PRIOR no = parent " +
"ORDER SIBLINGS BY no DESC) A) " +
"WHERE R BETWEEN ? AND ?";
Connection con = null;
PreparedStatement stmt = null;
ResultSet rs = null;
try {
con = getConnection();
stmt = con.prepareStatement(sql);
if (keyword == null || keyword.equals("")) {
stmt.setInt(1, start);
stmt.setInt(2, end);
} else {
stmt.setString(1, keyword);
stmt.setString(2, keyword);
stmt.setInt(3, start);
stmt.setInt(4, end);
}
rs = stmt.executeQuery();
while (rs.next()) {
Article article = new Article();
article.setNo(rs.getInt("no"));
article.setTitle(rs.getString("title"));
article.setWdate(rs.getDate("wdate"));
article.setIndent(rs.getInt("indent"));
list.add(article);
}
} catch (SQLException e) {
log.debug("Error Source : BoardDao.getBoardList() : SQLException");
log.debug("SQLState : " + e.getSQLState());
log.debug("Message : " + e.getMessage());
log.debug("Oracle Error Code : " + e.getErrorCode());
log.debug("sql : " + sql);
} finally {
close(rs, stmt, con);
log.close();
}
return list;
}
public int getTotalRecord(String keyword) {
Log log = new Log();
int totalRecord = 0;
String sql = null;
sql = "SELECT count(*) FROM board ";
if (keyword != null && !keyword.equals("")) {
sql += "WHERE title LIKE ? OR content LIKE ?";
}
Connection con = null;
PreparedStatement stmt = null;
ResultSet rs = null;
try {
con = getConnection();
stmt = con.prepareStatement(sql);
if (keyword != null && !keyword.equals("")) {
keyword = "%" + keyword + "%";
stmt.setString(1, keyword);
stmt.setString(2, keyword);
}
rs = stmt.executeQuery();
rs.next();
totalRecord = rs.getInt(1);
} catch (SQLException e) {
log.debug("Error Source : BoardDao.getTotalRecord() : SQLException");
log.debug("SQLState : " + e.getSQLState());
log.debug("Message : " + e.getMessage());
log.debug("Oracle Error Code : " + e.getErrorCode());
log.debug("sql : " + sql);
} finally {
close(rs, stmt, con);
log.close();
}
return totalRecord;
}
}
다음 메소드는 목록의 페이지 매기기에 필요한 숫자를 만들어낸다.
public Map<String, Integer> getNumbersForPaging(int totalRecord, int curPage, int numPerPage, int pagePerBlock) {
Map<String, Integer> map = new HashMap<String, Integer>();
int totalPage = totalRecord / numPerPage;
if (totalRecord % numPerPage != 0) totalPage++;
int totalBlock = totalPage / pagePerBlock;
if (totalPage % pagePerBlock != 0) totalBlock++;
int block = curPage / pagePerBlock;
if (curPage % pagePerBlock != 0) block++;
int firstPage = (block - 1) * pagePerBlock + 1;
int lastPage = block * pagePerBlock;
int prevPage = 0;
if (block > 1) {
prevPage = firstPage - 1;
}
int nextPage = 0;
if (block < totalBlock) {
nextPage = lastPage + 1;
}
if (block >= totalBlock) {
lastPage = totalPage;
}
int listItemNo = totalRecord - (curPage - 1) * numPerPage;
map.put("totalPage", totalPage);
map.put("firstPage", firstPage);
map.put("lastPage", lastPage);
map.put("prevPage", prevPage);
map.put("nextPage", nextPage);
map.put("listItemNo", listItemNo);
return map;
}
/board/list.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ page import="net.java_school.board.*" %>
<%@ page import="java.util.*" %>
<%!
public Map<String, Integer> getNumbersForPaging(int totalRecord, int curPage, int numPerPage, int pagePerBlock) {
Map<String, Integer> map = new HashMap<String, Integer>();
int totalPage = totalRecord / numPerPage;
if (totalRecord % numPerPage != 0) totalPage++;
int totalBlock = totalPage / pagePerBlock;
if (totalPage % pagePerBlock != 0) totalBlock++;
int block = curPage / pagePerBlock;
if (curPage % pagePerBlock != 0) block++;
int firstPage = (block - 1) * pagePerBlock + 1;
int lastPage = block * pagePerBlock;
int prevPage = 0;
if (block > 1) {
prevPage = firstPage - 1;
}
int nextPage = 0;
if (block < totalBlock) {
nextPage = lastPage + 1;
}
if (block >= totalBlock) {
lastPage = totalPage;
}
int listItemNo = totalRecord - (curPage - 1) * numPerPage;
map.put("totalPage", totalPage);
map.put("firstPage", firstPage);
map.put("lastPage", lastPage);
map.put("prevPage", prevPage);
map.put("nextPage", nextPage);
map.put("listItemNo", listItemNo);
return map;
}
%>
<%
request.setCharacterEncoding("UTF-8");
int curPage = request.getParameter("curPage") == null ? 1 : Integer.parseInt(request.getParameter("curPage"));
String keyword = request.getParameter("keyword");
if (keyword == null) keyword = "";
BoardDao dao = new BoardDao();
int totalRecord = dao.getTotalRecord(keyword);
int numPerPage = 10;
int pagePerBlock = 5;
Map<String, Integer> numbers = this.getNumbersForPaging(totalRecord, curPage, numPerPage, pagePerBlcok);
int startRecord = (curPage - 1) * numPerPage + 1;
int endRecord = curPage * numPerPage;
List<Article> list = dao.getBoardList(startRecord, endRecord, keyword);
%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>목록</title>
</head>
<body style="font-size: 11px;">
<h1>목록</h1>
<%
int listItemNo = numbers.get("listItemNo");//이 값은 목록 페이지에서 계산되는 번호다. no 컬럼 값이 아니다.
for (int i = 0; i < list.size(); i++) {
Article article = list.get(i);
int indent = article.getIndent();
for (int j = 0; j < indent; j++) {
out.println(" ");
}
if(indent != 1) {
out.println("⌙");
}
%>
<%=listItemNo %>
<a href="view.jsp?no=<%=article.getNo() %>&curPage=<%=curPage %>&keyword=<%=keyword %>"><%=article.getTitle() %></a>
<%=article.getWdate() %><br />
<hr />
<%
listItemNo--;
}
int prevPage = numbers.get("prevPage");
if (prevPage != 0) {
%>
<a href="list.jsp?curPage=<%=prevPage %>&keyword=<%=keyword %>">[이전]</a>
<%
}
int firstPage = numbers.get("firstPage");
int lastPage = numbers.get("lastPage");
for (int i = firstPage; i <= lastPage; i++) {
%>
<a href="list.jsp?curPage=<%=i %>&keyword=<%=keyword %>">[<%=i %>]</a>
<%
}
int nextPage = numbers.get("nextPage");
if (nextPage != 0) {
%>
<a href="list.jsp?curPage=<%=nextPage %>&keyword=<%=keyword %>">[다음]</a>
<%
}
%>
<p>
<a href="write_form.jsp?curPage=<%=curPage %>&keyword=<%=keyword %>">글쓰기</a>
</p>
<form method="get">
<input type="text" size="10" maxlength="30" name="keyword" />
<input type="submit" value="Search" />
</form>
</body>
</html>
목록을 방문하여 테스트한다. 간단한 게시판은 Article과 BoardDao 정도로 충분하지만, 대부분 모듈은 JSP의 프런트 역할을 하는 빈즈을 따로 두는 경우가 많다. 이 빈즈의 이름에는 Service란 이름이 붙는다. 게시판 JSP의 프런트 역할을 하는 BoardService 빈즈를 생성한다. BoardService를 만들면 게시판 JSP는 BoardService만을 바라보게 된다. 위 list.jsp에 선언된 getNumbersForPaging() 메소드는 BoardService로 옮길 수 있다.
BoardService.java
package net.java_school.board;
import java.util.Map;
import java.util.HashMap;
import java.util.List;
public class BoardService {
private BoardDao dao = new BoardDao();
public BoardService() {}
public Map<String, Integer> getNumbersForPaging(int totalRecord, int curPage, int numPerPage, int pagePerBlock) {
Map<String, Integer> map = new HashMap<String, Integer>();
int totalPage = totalRecord / numPerPage;
if (totalRecord % numPerPage != 0) totalPage++;
int totalBlock = totalPage / pagePerBlock;
if (totalPage % pagePerBlock != 0) totalBlock++;
int block = curPage / pagePerBlock;
if (curPage % pagePerBlock != 0) block++;
int firstPage = (block - 1) * pagePerBlock + 1;
int lastPage = block * pagePerBlock;
int prevPage = 0;
if (block > 1) {
prevPage = firstPage - 1;
}
int nextPage = 0;
if (block < totalBlock) {
nextPage = lastPage + 1;
}
if (block >= totalBlock) {
lastPage = totalPage;
}
int listItemNo = totalRecord - (curPage - 1) * numPerPage;
map.put("totalPage", totalPage);
map.put("firstPage", firstPage);
map.put("lastPage", lastPage);
map.put("prevPage", prevPage);
map.put("nextPage", nextPage);
map.put("listItemNo", listItemNo);
return map;
}
public List<Article> getBoardList(int startRecord, int endRecord, String keyword) {
return dao.getBoardList(startRecord, endRecord, keyword);
}
public int getTotalRecord(String keyword) {
return dao.getTotalRecord(keyword);
}
}
BoardService.java만을 사용하도록 list.jsp를 수정한다.
/board/list.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ page import="net.java_school.board.*" %>
<%@ page import="net.java_school.commons.*" %>
<%@ page import="java.util.*" %>
<%
int curPage = (request.getParameter("curPage") == null ? 1 : Integer.parseInt(request.getParameter("curPage")));
String keyword = request.getParameter("keyword");
if (keyword == null) keyword = "";
BoardService service = new BoardService();
int totalRecord = service.getTotalRecord(keyword);
int numPerPage = 10;
int pagePerBlock = 5;
Map<String, Integer> numbers = service.getNumbersForPaging(totalRecord, curPage, numPerPage, pagePerBlock);
int startRecord = (curPage - 1) * numPerPage + 1;
int endRecord = curPage * numPerPage;
List<Article> list = service.getBoardList(startRecord, endRecord, keyword);
%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>목록</title>
</head>
<body style="font-size: 11px;">
<h1>목록</h1>
<%
int listItemNo = numbers.get("listItemNo");
for (int i = 0; i < list.size(); i++) {
Article article = list.get(i);
int indent = article.getIndent();
for (int j = 0; j < indent; j++) {
out.println(" ");
}
if(indent != 1) {
out.println("⌙");
}
%>
<%=listItemNo %>
<a href="view.jsp?no=<%=article.getNo() %>&curPage=<%=curPage %>&keyword=<%=keyword %>"><%=article.getTitle() %></a>
<%=article.getWdate() %><br />
<hr />
<%
listItemNo--;
}
int prevPage = numbers.get("prevPage");
if (prevPage != 0) {
%>
<a href="list.jsp?curPage=<%=prevPage %>&keyword=<%=keyword %>">[이전]</a>
<%
}
int firstPage = numbers.get("firstPage");
int lastPage = numbers.get("lastPage");
for (int i = firstPage; i <= lastPage; i++) {
%>
<a href="list.jsp?curPage=<%=i %>&keyword=<%=keyword %>">[<%=i %>]</a>
<%
}
int nextPage = numbers.get("nextPage");
if (nextPage != 0) {
%>
<a href="list.jsp?curPage=<%=nextPage %>&keyword=<%=keyword %>">[다음]</a>
<%
}
%>
<p>
<a href="write_form.jsp?curPage=<%=curPage %>&keyword=<%=keyword %>">글쓰기</a>
</p>
<form method="get">
<input type="text" size="10" maxlength="30" name="keyword" />
<input type="submit" value="Search" />
</form>
</body>
</html>
/board/write_form.jsp 파일의 폼 태그의 action 속성값을 write.jsp로 수정한다.
/board/write_form.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%
String curPage = request.getParameter("curPage");
String keyword = request.getParameter("keyword");
%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>글쓰기</title>
</head>
<body>
<h3>새 글쓰기</h3>
<form action="write.jsp" method="post">
<table>
<tr>
<td>제목</td>
<td><input type="text" name="title" size="50"></td>
</tr>
<tr>
<td colspan="2">
<textarea name="content" rows="20" cols="100"></textarea>
</td>
</tr>
<tr>
<td colspan="2">
<input type="submit" value="전송">
<input type="reset" value="취소">
<a href="list.jsp?curPage=<%=curPage %>&keyword=<%=keyword %>">목록</a>
</td>
</tr>
</table>
</form>
</body>
</html>
BoardDao 클래스에 다음 메소드를 추가한다.
BoardDao.java
public void insert(Article article) {
Log log = new Log();
String sql = "INSERT INTO board (no, title, content, wdate, parent) "
+ "VALUES (board_no_seq.nextval, ?, ?, sysdate, 0)";
Connection con = null;
PreparedStatement stmt = null;
try {
con = getConnection();
stmt = con.prepareStatement(sql);
stmt.setString(1, article.getTitle());
stmt.setString(2, article.getContent());
stmt.executeUpdate();
} catch (SQLException e) {
log.debug("Error Source : BoardDao.insert() : SQLException");
log.debug("SQLState : " + e.getSQLState());
log.debug("Message : " + e.getMessage());
log.debug("Oracle Error Code : " + e.getErrorCode());
log.debug("sql : " + sql);
} finally {
close(null, stmt, con);
log.close();
}
}
BoardService에 다음 메소드를 추가한다.
BoardService.java 수정
public void write(Article article) {
dao.insert(article);
}
새 글쓰기를 처리하는 write.jsp 파일을 만든다.
/board/write.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ page import="net.java_school.board.*" %>
<%
request.setCharacterEncoding("UTF-8");
String title = request.getParameter("title");
String content = request.getParameter("content");
Article article = new Article();
article.setTitle(title);
article.setContent(content);
BoardService service= new BoardService();
service.write(article);
response.sendRedirect("list.jsp");
%>
다음으로 상세보기 구현한다. BoardDao에 selectOne() 메소드를 추가한다.
BoardDao.java
public Article selectOne(int no) {
Log log = new Log();
Article article = null;
String sql = "SELECT no, title, content, wdate FROM board WHERE no = ?";
Connection con = null;
PreparedStatement stmt = null;
ResultSet rs = null;
try {
con = getConnection();
stmt = con.prepareStatement(sql);
stmt.setInt(1, no);
rs = stmt.executeQuery();
while (rs.next()) {
article = new Article();
article.setNo(rs.getInt("no"));
article.setTitle(rs.getString("title"));
article.setContent(rs.getString("content"));
article.setWdate(rs.getDate("wdate"));
}
} catch (SQLException e) {
log.debug("Error Source : BoardDao.selectOne() : SQLException");
log.debug("SQLState : " + e.getSQLState());
log.debug("Message : " + e.getMessage());
log.debug("Oracle Error Code : " + e.getErrorCode());
log.debug("sql : " + sql);
} finally {
close(rs, stmt, con);
log.close();
}
return article;
}
BoardService에 다음 메소드를 추가한다.
BoardService.java
public Article getArticle(int no) {
return dao.selectOne(no);
}
view.jsp를 아래와 같이 수정한다.
/board/view.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ page import="net.java_school.board.*" %>
<%
int no = Integer.parseInt(request.getParameter("no"));
String curPage = request.getParameter("curPage");
String keyword = request.getParameter("keyword");
if (keyword == null) keyword = "";
BoardService service = new BoardService();
Article article = service.getArticle(no);
%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>상세보기</title>
<script type="text/javascript">
function goModify(no,curPage,keyword) {
location.href="modify_form.jsp?no=" + no + "&curPage=" + curPage + "&keyword=" + keyword;
}
function goDelete(no,curPage,keyword) {
var check = confirm("정말로 삭제하겠습니까?");
if (check) {
location.href="del.jsp?no=" + no + "&curPage=" + curPage + "&keyword=" + keyword;
}
}
</script>
</head>
<body>
<h1>상세보기</h1>
<h2>제목: <%=article.getTitle() %>, 작성일: <%=article.getWdate() %></h2>
<p>
<%=article.getHtmlContent() %>
</p>
<a href="list.jsp?curPage=<%=curPage %>&keyword=<%=keyword %>">목록</a>
<input type="button" value="수정" onclick="javascript:goModify('<%=no %>','<%=curPage %>','<%=keyword %>')">
<input type="button" value="삭제" onclick="javascript:goDelete('<%=no %>','<%=curPage %>','<%=keyword %>')">
<a href="reply_form.jsp?no=<%=no %>&curPage=<%=curPage %>&keyword=<%=keyword %>">답변쓰기</a>
</body>
</html>
다음으로 글 수정을 구현한다. BoardDao 클래스에 update() 메소드를 추가한다.
BoardDao.java
public void update(Article article) {
Log log = new Log();
String sql = "UPDATE board SET title = ?, content = ? WHERE no = ?";
Connection con = null;
PreparedStatement stmt = null;
try {
con = getConnection();
stmt = con.prepareStatement(sql);
stmt.setString(1, article.getTitle());
stmt.setString(2, article.getContent());
stmt.setInt(3, article.getNo());
stmt.executeUpdate();
} catch (SQLException e) {
log.debug("Error Source : BoardDao.update() : SQLException");
log.debug("SQLState : " + e.getSQLState());
log.debug("Message : " + e.getMessage());
log.debug("Oracle Error Code : " + e.getErrorCode());
log.debug("sql : " + sql);
} finally {
close(null, stmt, con);
log.close();
}
}
BoardService.java 수정
public void modify(Article article) {
dao.update(article);
}
modify_form.jsp가 BoardService를 사용하도록 수정한다.
/board/modify_form.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ page import="java.sql.*" %>
<%@ page import="net.java_school.board.*" %>
<%
int no = Integer.parseInt(request.getParameter("no"));
String curPage = request.getParameter("curPage");
String keyword = request.getParameter("keyword");
BoardService service = new BoardService();
Article article = service.getArticle(no);
%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>수정</title>
</head>
<body>
<h1>수정</h1>
<form action="modify.jsp" method="post">
<input type="hidden" name="no" value="<%=no %>">
<input type="hidden" name="curPage" value="<%=curPage %>">
<input type="hidden" name="keyword" value="<%=keyword %>">
<table>
<tr>
<td>제목</td>
<td><input type="text" name="title" size="50" value="<%=article.getTitle() %>" /></td>
</tr>
<tr>
<td colspan="2">
<textarea name="content" rows="30" cols="100"><%=article.getContent() %></textarea>
</td>
</tr>
<tr>
<td colspan="2">
<input type="submit" value="전송">
<input type="reset" value="취소">
<a href="view.jsp?no=<%=no %>&curPage=<%=curPage %>&keyword=<%=keyword %>">상세보기</a>
</td>
</tr>
</table>
</form>
</body>
</html>
modify.jsp를 아래와 같이 생성한다.
/board/modify.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ page import="net.java_school.board.*" %>
<%
request.setCharacterEncoding("UTF-8");
int no = Integer.parseInt(request.getParameter("no"));
String curPage = request.getParameter("curPage");
String keyword = request.getParameter("keyword");
String title = request.getParameter("title");
String content = request.getParameter("content");
Article article = new Article();
article.setNo(no);
article.setTitle(title);
article.setContent(content);
BoardService service= new BoardService();
service.modify(article);
keyword = java.net.URLEncoder.encode(keyword,"UTF-8");
response.sendRedirect("view.jsp?no=" + no + "&curPage=" + curPage + "&keyword=" + keyword);
%>
다음으로 글 삭제를 구현한다. BoardDao 클래스에 delete() 메소드를 추가한다.
BoardDao.java
public void delete(int no) {
Log log = new Log();
String sql1 = "SELECT count(*) FROM board WHERE parent = ?";
String sql2 = "DELETE FROM board WHERE no = ?";
Connection con = null;
PreparedStatement stmt1 = null;
PreparedStatement stmt2 = null;
ResultSet rs = null;
boolean check = false; //true면 삭제
try {
con = getConnection();
stmt1 = con.prepareStatement(sql1);
stmt1.setInt(1, no);
rs = stmt1.executeQuery();
rs.next();
int num = rs.getInt(1);
if (num == 0) {
check = true;
}
if (check == true) {
stmt2 = con.prepareStatement(sql2);
stmt2.setInt(1, no);
stmt2.executeUpdate();
}
} catch (SQLException e) {
log.debug("Error Source : BoardDao.delete() : SQLException");
log.debug("SQLState : " + e.getSQLState());
log.debug("Message : " + e.getMessage());
log.debug("Oracle Error Code : " + e.getErrorCode());
log.debug("sql : " + sql1);
} finally {
if (stmt1 != null) {
try {
stmt1.close();
} catch (SQLException e) {}
}
close(rs, stmt2, con);
log.close();
}
}
BoardService에 다음 메소드를 추가한다.
BoardService.java
public void delete(int no) {
dao.delete(no);
}
del.jsp를 다음과 같이 생성한다.
/board/del.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ page import="net.java_school.board.*" %>
<%
int no = Integer.parseInt(request.getParameter("no"));
String curPage = request.getParameter("curPage");
String keyword = request.getParameter("keyword");
BoardService service= new BoardService();
service.delete(no);
keyword = java.net.URLEncoder.encode(keyword,"UTF-8");
response.sendRedirect("list.jsp?curPage=" + curPage + "&keyword=" + keyword);
%>
답변글이 있으면 삭제되지 않는다. 다음으로 답변쓰기를 구현한다. BoardDao에 다음 메소드를 추가한다.
BoardDao.java
public void reply(Article article) {
Log log = new Log();
//답변쓰기용 쿼리
String sql = "INSERT INTO board " +
"(no, parent, title, content, wdate) " +
"VALUES (board_no_seq.nextval, ?, ?, ?, sysdate)";
Connection con = null;
PreparedStatement stmt = null;
try {
con = getConnection();
stmt = con.prepareStatement(sql);
stmt.setInt(1, article.getParent());
stmt.setString(2, article.getTitle());
stmt.setString(3, article.getContent());
stmt.executeUpdate();
} catch (SQLException e) {
log.debug("Error Source:BoardDao.reply() : SQLException");
log.debug("SQLState : " + e.getSQLState());
log.debug("Message : " + e.getMessage());
log.debug("Oracle Error Code : " + e.getErrorCode());
log.debug("sql : " + sql);
} finally {
close(null, stmt, con);
log.close();
}
}
BoardService에 reply() 메소드를 추가한다.
BoardService.java
public void reply(Article article) {
dao.reply(article);
}
/board/reply_form.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ page import="net.java_school.board.*" %>
<%@ page import="net.java_school.commons.*" %>
<%
int no = Integer.parseInt(request.getParameter("no"));
String curPage = request.getParameter("curPage");
String keyword = request.getParameter("keyword");
BoardService service = new BoardService();
Article article = service.getArticle(no);
String content = article.getContent();
//부모글을 구별하기 위해 부모글의 각 행마다 >가 추가되도록 한다.
content = content.replaceAll(WebContants.lineSeparator.value, WebContants.lineSeparator.value + ">");
content = WebContants.lineSeparator.value + WebContants.lineSeparator.value + ">" + content;
%>
<html>
<head>
<meta charset="UTF-8" />
<title>답변쓰기</title>
</head>
<body>
<h1>답변쓰기</h1>
<form action="reply.jsp" method="post">
<input type="hidden" name="no" value="<%=no %>" />
<input type="hidden" name="curPage" value="<%=curPage %>" />
<input type="hidden" name="keyword" value="<%=keyword %>" />
제목 : <input type="text" name="title" size="45" value="<%=article.getTitle() %>" /><br />
<textarea name="content" rows="10" cols="60"><%=content %></textarea><br />
<input type="submit" value="전송" />
<input type="reset" value="취소" /><br />
</form>
<a href="view.jsp?no=<%=no %>&curPage=<%=curPage %>&keyword=<%=keyword %>">상세보기</a>
</body>
</html>
reply.jsp를 아래와 같이 생성한다.
/board/reply.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ page import="net.java_school.board.*" %>
<%
request.setCharacterEncoding("UTF-8");
int parent = Integer.parseInt(request.getParameter("no"));
String title = request.getParameter("title");
String content = request.getParameter("content");
String curPage = request.getParameter("curPage");
String keyword = request.getParameter("keyword");
Article article = new Article();
article.setParent(parent);
article.setTitle(title);
article.setContent(content);
BoardService service= new BoardService();
service.reply(article);
keyword = java.net.URLEncoder.encode(keyword,"UTF-8");
response.sendRedirect("list.jsp?curPage=" + curPage + "&keyword=" + keyword);
%>
