JSP BBS (Bulletin Board System)
Internet Computing Laboratory @ KUT Youn-Hee Han
Design
게시물에 할당해야 할 값
일렬 번호 (테이블 필드명: THEME_MESSAGE_ID)
게시물마다 고유의 값을 가지면 글이 추가될 때 마다 1씩 증가
그룹 번호 (GROUP_ID)
연관된 게시물들이 공유하는 번호
주 게시물 및 그 게시물의 모든 답글은 같은 그룹 번호를 가짐
부모 번호 (PARENT_ID)
주 게시물은 항상 0을 지님
답변 게시물은 해당 주 게시물의 일렬 번호를 부모 번호로 가짐
출력 순서 (ORDER_NO)
주 게시물은 항상 0을 지님
같은 그룹 내의 답변 게시물 들에 대한 출력 순서를 저장
단계값 (LEVEL)
주 게시물은 항상 1을 지님
얼마나 중첩이 된 답변 게시물인지를 나타냄
2
Web Programming
Design
게시물에 할당해야 할 값
Primary Key
일련 번호 1 그룹 번호 1 부모 번호 0 출력 순서 0 단계값 (들여쓰기) 1
입력 순서
1
Hi!
Hello~~~
2
2
2
0
0
1
입력 순서 1
일련 번호 1 3
그룹 번호 1 1
부모 번호 0 1
출력 순서 0 1
단계값 (들여쓰기) 1 2 Hi! Me too! Hello~~~
3
2
2
2
0
0
1
3
Web Programming
Design
게시물에 할당해야 할 값
입력 순서
1 일련 번호 1 그룹 번호 1 부모 번호 0 출력 순서 0 단계값 (들여쓰기) 1 Hi!
4
3 2 입력 순서 1 3 5 4 2
3
4 2 일련 번호 1 3
1
1 2 그룹 번호 1 1
1
1 0 부모 번호 0 1
1
2 0 출력 순서 0 1
2
2 1 단계값 (들여쓰기) 1 2
Me too!
I‟m not! Hello~~~
Hi!
Me too!
Me three! I‟m not!
5 4
2
1 1
2
3 1
0
2 3
0
3 2
1
Hello~~~
4
Web Programming
Design
게시물에 할당해야 할 값
입력 순서
일련 번호 1
3 5
그룹 번호 1
1 1
부모 번호 0
1 3
출력 순서 0
1 2
단계값 (들여쓰기) 1
2 3 Hi! Me too!
1
3
5 6
4 2
Me three!
Good!!! I‟m not!
6
4 2 일련 번호 1 3
1
1 2 그룹 번호 1 1
5
1 0 부모 번호 0 1
3
4 0 출력 순서 0 1
4
2 1 단계값 (들여쓰기) 1 2
Hello~~~
입력 순서
1
Hi!
3
5 6
Me too!
Me three! Good!!!
5
6 7
1
1 1
3
5 3
2
3 4
3
4 3
7 4
2 5
Me four!
I‟m not! Hello~~~ Web Programming
4
2
1
2
1
0
5
0
2
1
DB Schema for BBS
데이터베이스 Table 목록
THEME_MESSAGE(, NOTICE_MESSAGE, STUDY_MESSAGE…)
THEME_CONTENT(, NOTICE_CONTENT, STUDY_CONTENT…)
6
Web Programming
DB Schema for BBS
데이터베이스 Table 목록
ID_SEQUENCE
인덱스
THEME_MESSAGE_INDEX
7
Web Programming
컴파일러 준비
sjc.bat
다음과 같이 재정비 할 필요
set CLASSPATH= set CLASSPATH=%CLASSPATH%;D:\jakarta-tomcat-5.0.19\webapps\2006777888 \WEB-INF\classes;D:\jakarta-tomcat-5.0.19\common\lib\servlet-api.jar javac -d D:\jakarta-tomcat-5.0.19\webapps\2006777888\WEB-INF\classes %1
기본 위치는 java 설치 디렉토리의 bin 디렉토리 밑 하지만, \2006777888\WEB-INF\src 밑에 두고 써도 상관없음
그러나, 시스템 전체에 sjc.bat는 하나만 존재해야 함!
8
Web Programming
DB 준비
데이터베이스 준비
MySQL 4.0.18 설치
패스워드는 디폴트로 없이 수행
압축 해제 디렉토리: d:\install_mysql
설치 디렉토리: d:\mysql d:\mysql\bin\winmysqladmin.exe 을 실행한다. User ID는 root로 PASSWD는 적절하게 넣어준다.
도스창에서 mysqladmin -p create theme
d:\mysql\bin\ 에서 수행 패스워드는 아무것도 넣지 말고 엔터 누름
theme.sql 다운받기
d:\mysql\bin\ 에 다운받는다.
도스창에서 mysql -p theme < theme.sql
d:\mysql\bin\ 에서 수행 패스워드는 아무것도 넣지 말고 엔터 누름
Web Programming
9
WEB Application 준비
kut.ime.jdbcdriver.DBCPInit 서블릿 클래스
DBCPInit.java 다운로드
다운로드 디렉토리: \2006777888\WEB-INF\src
패키지명 유의 컴파일
10
Web Programming
Connection Pool 및 JDBC 드라이버 로드
Connection Pool 설정 pool.jocl 다운로드: /2006777888/WEB-INF/classes 밑에 저장 교재 474 페이지 참고 JDBC Driver 사용을 위한 web.xml 수정 교재 475 페이지 참고 web.xml 내에 다음을 추가
…
DBCPInit kut.ime.jdbcdriver.DBCPInit 1 jdbcdriver com.mysql.jdbc.Driver …
11
Web Programming
Connection Pool 및 JDBC 드라이버 로드
DB 이용을 위한 라이브러리 다운로드 다운로드 위치: /2006777888/WEB-INF/lib 다운로드할 파일
classes12.jar
commons-collections-3.1.jar commons-dbcp-1.2.1.jar
commons-pool-1.2.jar
mysql-connector-java-3.0.14-production-bin.jar
Tomcat 재시작
DB 테스트
<%@ page import="java.sql.*"%>
2006777888/bbs/test.jsp
<% Connection conn = DriverManager.getConnection("jdbc:apache:commons:dbcp:/"+"pool"); ResultSet rs = conn.createStatement().executeQuery("show tables;");
while(rs.next()) { out.println(rs.getString(1) + "
"); } %>
12
pool.jocl
Web Programming
보조 클래스
kut.ime.util.DBUtil 클래스
package kut.ime.util; import java.sql.DriverManager; import java.sql.Connection; import java.sql.SQLException;
2006777888/WEB-INF/src/DBUtil.java
public class DBUtil { public static Connection getConnection(String poolName) throws SQLException { return DriverManager.getConnection( "jdbc:apache:commons:dbcp:/"+poolName); } }
이후 모든 .java 소스는 다운 받아서 sjc 로 컴파일 필요
보조 클래스
kut.ime.bbs.Sequencer 클래스 (교재 p.476) 다음의 1개 메소드 제공
public synchronized static int nextID(Connection conn, String tableName) ID_SEQUENCE 테이블에 저장된 게시물들의 가장 큰 일련 번호인 MESSAGE_ID 필드
값을 얻어와 하나 증가된 값을 리턴해줌
사용법 int id = Sequencer.nextId(conn, “THEME_MESSAGE”);
kut.ime.bbs.Theme 클래스 (교재 p.477~479) 자바빈 클래스 THEME_MESSAGE 테이블과 THEME_CONTENT 테이블의 내용을 모두 포함 용도
새로운 게시물을 입력할 때 게시물을 얻어올 때 게시물을 업데이트 할 때
kut.ime.bbs.ThemeManagerException 클래스 (교재 p.480) 본 JSP BBS 관련 작업 처리 중 발생하는 예외를 다른 예외들과 구별하기 위하여
필요함
주 클래스: ThemeManager
ThemeManager 클래스
JSP BBS의 대부분의 기능을 수행하는 클래스 메소드 목록
• •
public static ThemeManager getInstance();
ThemeManager의 인스턴스를 얻어옴
public void insert(Theme theme) throws ThemeManagerException;
게시판에 새로운 글을 삽입할 때 사용
•
•
public int count(List whereCond, Map valueMap) throws ThemeManagerException;
특정 조건에 만족하는 게시물의 총 개수를 구함
public List selectList(List whereCond, Map valueMap, int startRow, int endRow) throws ThemeManagerException;
특정 조건에 만족하는 게시물을 목록을 가져 올때 사용
•
• •
public int select(int id) throws ThemeManagerException;
하나의 게시물을 읽어 올 때 사용
public int update(Theme theme) throws ThemeManagerException;
게시물 하나를 업데이트 할 때 사용
public int delete(int id) throws ThemeManagerException;
게시물 하나를 삭제 할 때 사용
클래스 배치
현재까지 클래스 컴파일 결과 모습
이미지 업로드&핸들링을 대비한 사전 준비 작업
폴더 생성 업로드 이미지 임시 저장소
D:\jakarta-tomcat-5.0.19\webapps\2006777888\bbs\temp 업로드 이미지 저장소 D:\jakarta-tomcat-5.0.19\webapps\2006777888\bbs\image
ImageUtil 클래스 배치
FileUploadRequestWrapper 클래스 배치
이미지 업로드&핸들링을 대비한 사전 준비 작업
라이브러리 재확인
TOMCAT 재시작!!!
화면 출력용 JSP 구성
BBS.zip 다운로드
•
•
다운로드 위치: 2006777888/bbs/ write.jsp 에서 2006777888을 자신의 폴더 이름으로 변경
화면 레이아웃과 모듈화 • 교재 494 페이지 참조
2006777888/bbs/template/template.jsp 2006777888/bbs/module/top.jsp
2006777888/bbs/list_view.jsp 2006777888/bbs/writeForm_view.jsp 2006777888/bbs/read_view.jsp 2006777888/bbs/updateForm_view.jsp 2006777888/bbs/deleteForm_view.jsp
2006777888/bbs/module/bottom.jsp
화면 출력용 JSP 구성
JSP 구성 및 연결도 (아래 파일들은 2006777888/bbs 아래에 위치함) • 게시물 목록 출력
/module/top.jsp list.jsp /template/template.jsp list_view.jsp /module/bottom.jsp
•
새 게시물 입력
/module/top.jsp writeForm.jsp /template/template.jsp writeForm_view.jsp /module/bottom.jsp
form action javascript location.href = “list.jsp”
write.jsp
화면 출력용 JSP 구성
JSP 구성 및 연결도 • 게시물 읽기
/module/top.jsp read.jsp /template/template.jsp read_view.jsp /module/bottom.jsp
•
게시물 수정
/module/top.jsp updateForm.jsp /template/template.jsp updateForm_view.jsp /module/bottom.jsp
list.jsp
javascript document.move.action = "list.jsp"; document.move.submit();
form action
update.jsp
화면 출력용 JSP 구성
JSP 구성 및 연결도 • 게시물 삭제
/module/top.jsp deleteForm.jsp /template/template.jsp deleteForm_view.jsp /module/bottom.jsp
form action
list.jsp
javascript location.href = “list.jsp”
delete.jsp
BBS 수행 모습
수행 모습
데이터 베이스 모습
게시물 목록 출력 코드
게시물 목록 출력 코드 설명 (검색 조건 없을 경우)
관련 코드 리스트
코드 리스트 18.18, 18.8, 18.9
출력할 페이지 번호 설정
currentPage 변수 설정
따라서, whereCond, whereValue, searchCondName, searchCondTitle 모두 null
searchCond, searchKey 는 null 이라고 가정
글의 전체 개수를 얻어옴
int count = manager.count(whereCond, whereValue);
수행되는 Query 문
select count(*) from THEME_MESSAGE
전체 페이지 개수와 읽어 올 시작행, 끝행을 구한다.
totalPageCount, startRow, endRow 설정
게시물 목록 출력 코드
게시물 목록 출력 코드 설명 (검색 조건 없을 경우) – 계속
글 목록을 읽어 옴
List list = manager.selectList(whereCond, whereValue, startRow-1, endRow-1); 수행되는 Query 문
select * from THEME_MESSAGE order by GROUP_ID desc, ORDER_NO asc limit ?, ?
Java 코딩에서 Query 구성 법
query.append(“select * from THEME_MESSAGE “); query.append(“order by GROUP_ID desc, ORDER_NO asc limit ?, ?”); Connection conn = DBUtil.getConnection(POOLNAME); PreparedStatement pstmtMessage = conn.prepareStatement(query.toString()); pstmtMessage.setInt(valueMap.size() + 1, startRow); pstmtMessage.setInt(valueMap.size() + 2, endRow- startRow + 1); ResultSet rsMessage = pstmtMessage.executeQuery();
리스트 18.10 StringBuffer query = new StringBuffer(200);
EL과 JSTL을 이용해서 글 목록 출력
글 목록 및 하나의 게시글 보기에 대한 링크 생성
자바 스크립트와 form을 활용
페이지 이동 링크 출력 ([이전], [1], [2], …., [다음]) 검색 폼 출력
게시물 목록 출력 코드
게시물 목록 출력 코드 설명 (검색 조건 있을 경우)
value: title value: name
관련 변수 선언
name: search_cond
name: search_key
리스트 18.8
String[] searchCond = request.getParameterValues("search_cond"); String searchKey = request.getParameter("search_key"); boolean searchCondName = false; boolean searchCondTitle = false; List whereCond = new java.util.ArrayList(); Map whereValue = new java.util.HashMap();
검색 조건 구성
for (int i = 0 ; i < searchCond.length ; i++) { if (searchCond[i].equals("name")) { whereCond.add("NAME = ?"); whereValue.put(new Integer(1), searchKey); searchCondName = true; } else if (searchCond[i].equals("title")) { whereCond.add("TITLE LIKE '%"+searchKey+"%'"); searchCondTitle = true; } }
리스트 18.8
whereCond 구성 예 ( List) : < “NAME=?”, “TITLE LIKE „%공지%‟ ”>
whereValue 구성 예 ( Map) :< (new Integer(1), ”한연희”), >
게시물 목록 출력 코드
게시물 목록 출력 코드 설명 (검색 조건 있을 경우) – 계속
글의 전체 개수를 얻어옴
int count = manager.count(whereCond, whereValue);
수행되는 Query 문
select count(*) from THEME_MESSAGE where NAME=한연희 select count(*) from THEME_MESSAGE where NAME=한연희 or title like „%공지%‟
Java 코딩에서 Query 구성 법
StringBuffer query = new StringBuffer(200); query.append("select count(*) from THEME_MESSAGE "); if (whereCond != null && whereCond.size() > 0) { query.append("where "); for (int i = 0 ; i < whereCond.size() ; i++) { query.append(whereCond.get(i)); if (i < whereCond.size() -1 ) { query.append(" or "); } } } pstmt = conn.prepareStatement(query.toString()); Iterator keyIter = valueMap.keySet().iterator(); Integer key = (Integer)keyIter.next(); Object obj = valueMap.get(key); pstmt.setString(key.intValue(), (String)obj);
리스트 18.9
게시물 목록 출력 코드
게시물 목록 출력 코드 설명 (검색 조건 있을 경우) – 계속
글 목록을 읽어 옴
List list = manager.selectList(whereCond, whereValue, startRow-1, endRow-1);
수행되는 Query 문
select * from THEME_MESSAGE where NAME=한연희 or title like „%공지%‟ order by GROUP_ID desc, ORDER_NO asc limit ?, ? 글 전체 개수를 구하는 코드에서 Query 구성법과 비슷
Java 코딩에서 Query 구성 법
검색 조건 없을 때의 Query 구성법과 병합하여 최종 Query를 구성!!!
새 게시물 입력 링크 관련 코드
[이미지등록] |
게시물 목록 출력 코드
파라미터 값 갖는 링크 구성
링크 구성 시 활용하는 폼
리스트 18.8
게시물 링크
${theme.title} . .
리스트 18.8
게시물 목록 출력 코드
파라미터 값 갖는 링크 구성
페이지 번호 링크
리스트 18.8
[이전] [${pageNo}]
게시물 보기 코드
게시물 보기 코드 설명
게시물 읽어 오기
String themeId = request.getParameter("id"); ThemeManager manager = ThemeManager.getInstance(); Theme theme = manager.select(Integer.parseInt(themeId));
리스트 18.23
사용하는 SQL Query 문
select * from THEME_MESSAGE where THEME_MESSAGE_ID = ? select CONTENT from THEME_CONTENT where THEME_MESSAGE_ID = ?
Theme 자바빈 구성
Theme theme = new Theme(); theme.setId(rsMessage.getInt("THEME_MESSAGE_ID")); theme.setGroupId(rsMessage.getInt("GROUP_ID")); . . theme.setContent(buffer.toString()); . . return theme;
게시물 보기 코드
게시물 보기 코드 설명
링크 구성 시 활용하는 폼
게시물 보기 코드
게시물 보기 코드 설명
다양한 링크 구성
| [답변] [수정] [삭제] [목록] |
리스트 18.23
게시물 입력 코드
게시물 입력 코드 설명
writeForm_view.jsp write.jsp
답변글일 경우 parentId 및 부모글의 제목 읽음
부모글은 theme 변수에 저장
폼 입력시 hidden 필드 구성
name="level" value="${theme.level + 1}"> param.groupId}"> name="groupId" value="${param.groupId}">
param.parentId}"> name="parentId" value="${param.parentId}">
리스트 18.20
폼 입력 내용에 대한 validation