[ITWILL : JSP]Javabean 8 : 게시판만들기(글내용보기, 글수정하기)

ITWILL학원 : 29강 JSP기초 BY 정규태강사

1. 순서

  1. content.jsp 생성
    • html 테이블작성
  2. boardDAO.java에 updateReadCount(int bno)메서드 생성
  3. boardDAO.java에 getBoard(int bno)메서드 생성
  4. 글수정할 수 있는 updateForm.jsp 생성
  5. 글수정할 수 있는 updatePro.jsp 생성
  6. boardDAO.java에 updateBoard(bb)메서드 생성

2. content.jsp 생성

글목록에서 제목을 눌렀을때 컨텐츠를 볼 수 있게 만드는 페이지이다.

  • 목록으로 되돌아가는 버튼 만들때 주의점
    • location.href=boardList.jsp만 하면 5페이지보고있다가 다시 1페이지로 돌아가버린다
    • 이때 historyback하면 조회수가 올라가지않는다.
    • 따라서 pageNum을 가져와서 사용하면된다
    • location.href=boardList.jsp?pageNum=<%=pageNum%>으로 해줘야한다.
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
<%
//1. html테이블작성

//글번호(pk제약조건의 컬럼필수)에 해당하는 글의 정보를 가져오기
//2. 전달된 데이터 저장(bno, pageNum)

int bno = Integer.parseInt(request.getParameter("bno"));
String pageNum = request.getParameter("pageNum");

//3. DAO객체생성
BoardDAO bdao = new BoardDAO();

//4. 글의 조회수정보를 1증가 : DB에서처리 -> DAO객체에 updateReadCount(bno)메서드 생성
bdao.updateReadCount(bno);

//5. 화면(테이블)에 출력 (getBoard(bno))
// DAO객체에 글정보를 가져오는 메서드 생성
BoardBean bb = bdao.getBoard(bno);
//System.out.println(bdao.getBoard(bno));
%>

<fieldset>
<legend>글 내용 보기</legend>
<table border="solid,1px">
<tr>
<th>글번호</th>
<td><%=bno%></td>
<th>조회수</th>
<td><%=bb.getReadcount()%></td>
</tr>
<tr>
<th>작성자</th>
<td><%=bb.getName() %></td>
<th>작성일</th>
<td><%=bb.getDate() %></td>
</tr>
<tr>
<th>제목</th>
<td colspan="3"><%=bb.getSubject() %></td>
</tr>
<tr>
<th>첨부파일</th>
<td colspan="3"><%=bb.getFile() %></td>
</tr>
<tr>
<th>내용</th>
<td colspan="3" height="300px"><%=bb.getContent() %></td>
</tr>
<tr>
<td colspan="4" style="text-align:center">
<input type="button" value="글수정" class="btn" onclick="location.href='updateForm.jsp?bno=<%=bb.getBno()%>&pageNum=<%=pageNum%>'">
<input type="button" value="글삭제" class="btn">
<input type="button" value="답글쓰기" class="btn">
<input type="button" value="목록으로" class="btn"
onclick="location.href='boardList.jsp?pageNum=<%=pageNum%>'">
<!-- location.href='boardList.jsp만 하면 5페이지보고있다가 다시 1페이지로 돌아가버린다
이때 historyback하면 조회수가 올라가지않는다.
따라서 pageNum을 가져와서 사용하면된다
-->
</td>
</tr>
</table>
</fieldset>

3. boardDAO.java에 updateReadCount(int bno)메서드 생성

조회수 올리는 메서드를 생성하자

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
public void updateReadCount(int bno){
try {
//1. 디비연결
getCon();
//2. sql작성 & pstmt생성
//select를 안하는 이유? 기존의 데이터를 굳이 가져올 필요가 없기 때문
sql = "update itwill_board set readcount=readcount+1 where bno=?";
pstmt = con.prepareStatement(sql);
pstmt.setInt(1, bno);
//3. 실행
pstmt.executeUpdate();
System.out.println("조회수 1증가 완료");
} catch (Exception e) {
System.out.println("조회수 1증가 실패");
e.printStackTrace();
} finally {
//4. 자원해제
closeDB();
}
}

4. boardDAO.java에 getBoard(int bno)메서드 생성

글 내용을 다 가져와서 오는 메서드를 만들어보자
이는 글제목을 클릭시 화면에 내용을 보여줄때 사용된다.

  • 내코드
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
public BoardBean getBoard(int bno){
BoardBean bb = new BoardBean();
try {
//1. 디비연결
getCon();
//2. sql작성, pstmt
//sql = "select * from itwill_board";
sql = "select * from itwill_board where bno=?";
pstmt = con.prepareStatement(sql);
pstmt.setInt(1, bno);
//3. 실행 -> rs저장
rs = pstmt.executeQuery();
//4. 데이터처리
if(rs.next()){
//4-1.BoardBean 객체생성해서 그 안에 rs데이터 저장
bb.setBno(rs.getInt("bno"));
bb.setContent(rs.getString("content"));
bb.setDate(rs.getDate("date"));
bb.setFile(rs.getString("file"));
bb.setIp(rs.getString("ip"));

bb.setName(rs.getString("name"));
bb.setPw(rs.getString("pw"));
bb.setRe_lev(rs.getInt("re_lev"));
bb.setRe_ref(rs.getInt("re_ref"));
bb.setRe_seq(rs.getInt("re_seq"));

bb.setReadcount(rs.getInt("readcount"));
bb.setSubject(rs.getString("subject"));
//여기까지가 한 행의 데이터를 저장한 것임

}
} catch (Exception e) {
e.printStackTrace();
} finally {
closeDB();
}
return bb;
}//getBoard닫음
  • 강사님코드
    • BoardBean객체를 언제 생성하는 지가 내 코드와 달랐다. BoardBean객체를 미리 생성할 필요가 없었다.
    • try catch로 예외가 발생하거나, rs에 데이터가 없는 경우에는 객체를 생성할 필요가 없기 때문이다.
    • 글정보 저장완료 후 리턴값 bb정보를 습관적으로 확인하자.
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
//글 정보를 가져오는 메서드구현
public BoardBean getBoard(int bno){
//rs에 데이터가 없으면 객체생성할 필요가 없음. 따라서 객채생성안하고 null함.
BoardBean bb = null;
try {
//1. 디비연결
getCon();
//2. sql작성, pstmt
//sql = "select * from itwill_board";
sql = "select * from itwill_board where bno=?";
pstmt = con.prepareStatement(sql);
pstmt.setInt(1, bno);
//3. 실행 -> rs저장
rs = pstmt.executeQuery();
//4. 데이터처리
if(rs.next()){
//4-1.BoardBean 객체생성해서 그 안에 rs데이터 저장
// 글내용에서 보이지 않는 컴럼들도 만들어야할까?
// 만들기를 추천함 why? 매개변수인 bno자체가 pk를 가졌다.
// 지금뿐만아니라 다음 기능이 필요할때 불러와서 사용할 수 있다.
// 재사용성
bb = new BoardBean();
bb.setBno(rs.getInt("bno"));

(중략)

bb.setSubject(rs.getString("subject"));
//여기까지가 한 행의 데이터를 저장한 것임
}
//글정보 저장완료 후 정보확인
System.out.println("해당 글 저장 완료");
System.out.println(bb);
} catch (Exception e) {
e.printStackTrace();
} finally {
closeDB();
}
return bb;
}//getBoard닫음

5. updateForm.jsp생성

글을 수정할수있는 페이지를 만들어보자.

  • 아래 태그 두개는 동일할까?

    • <input type="button" value="목록으로" class="btn" onclick="location.href='boardList.jsp?bno=<%=bno%>'">
    • <input type="button" value="목록으로" class="btn" onclick="location.href='boardList.jsp?bno=<%=bb.getBno()%>'">
  • YES! 동일하다!

  • 인풋 히튼타입 : 화면에는 보이지않지만 데이터 저장 및 전달이 가능해서 데이터 이동용으로 주로 사용

  • BoardBean안에 포함되지 않는 pageNum 변수등은 어떻게 전달할까?

    • 액션페이지 주소줄에 get방식으로 전달
    • 만약 (BoardBean에 포함되지않은) 전달될 데이터가 개인정보등 중요한 데이터라면 get방식으로 전달해선 절대 안된다(=>정보유출문제발생)
      • 그럼 중요한 정보들은 전달할수없는걸까? CAN! 1. 클로저이용 또는 2.BoardBean구조자체를 변경
    • 결론: 가능하면 BoardBean형태의 데이터만 저장해서 처리할 수 있도록 해야한다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<%//1. 파라미터저장
int bno = Integer.parseInt(request.getParameter("bno"));
String pageNum = request.getParameter("pageNum");

BoardDAO bdao = new BoardDAO();
BoardBean bb = bdao.getBoard(bno);
%>

<fieldset>
<legend>게시판 글쓰기</legend>
<form action="updatePro.jsp?pageNum=<%=pageNum %>" method="post" name="fr">
<!-- 인풋 히튼타입 : 화면에는 보이지않지만 데이터 저장 및 전달이 가능해서 데이터 이동용으로 주로 사용 -->
<input type="hidden" name="bno" value="<%=bb.getBno() %>">
글쓴이 : <input type="text" name="name" required value="<%=bb.getName() %>"><br>
비밀번호 : <input type="password" name="pw" required ><br>
제목 : <input type="text" name="subject" required value="<%=bb.getSubject() %>"><br>
내용 : <br>
<textarea rows="10" cols="35" name="content" placeholder="여기에 작성해주세요" required>
<%=bb.getContent() %></textarea><br>
<input type="submit" value="수정하기" class="btn">
<button type="reset" class="btn">초기화</button>
<input type="button" value="목록으로" class="btn" onclick="location.href='boardList.jsp'">
</form>
</fieldset>

6. updatePro.jsp생성

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
<%//1. 한글처리
request.setCharacterEncoding("UTF-8");
//2. 파라미터저장(액션태그사용 & pageNum은 파라미터로)
String pageNum = request.getParameter("pageNum");
%>
<jsp:useBean id="bb" class="com.itwillbs.board.BoardBean"></jsp:useBean>
<jsp:setProperty property="*" name="bb"/>
<% //3. DAO생성
BoardDAO bdao = new BoardDAO();
//4. 정보수정메서드 updateBoard(bb)
// -> 결과를 정수형 데이터로 리턴 (1=>정상처리, 0=>비번오류, -1=>해당글없음)
int result = bdao.updateBoard(bb);
if( result == 1){
%>
<script type="text/javascript">
alert("글 수정 완료!");
location.href="boardList.jsp?pageNum=<%=pageNum%>";
</script>
<%
}else if(result == 0){
%>
<script type="text/javascript">
alert("비번이 일치하지않습니다");
history.back();
</script>
<%
}else{
%>
<script type="text/javascript">
alert("존재하지 않는 글입니다");
history.back();
</script>
<%
}
%>

7. boardDAO.java에 updateBoard(bb)메서드 생성

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
public int updateBoard(BoardBean bb){
int result = 0;

try {
//DB연결
getCon();
System.out.println("디비연결완료");
//sql & pstmt
sql = "select pw from itiwill_board where bno=?";
pstmt = con.prepareStatement(sql);
System.out.println("pstmt 객체생성완료");
pstmt.setInt(1, bb.getBno());

rs = pstmt.executeQuery();
System.out.println("pstmt 실행");
if(rs.next()){
//비번비교 후 일치하면 update 쿼리실행
if(bb.getPw().equals(rs.getString("pw"))){
sql="update itwill_board set name=?, subject=?, content=? where bno=?";
pstmt = con.prepareStatement(sql);
pstmt.setString(1, bb.getName());
pstmt.setString(2, bb.getSubject());
pstmt.setString(3, bb.getContent());
pstmt.setInt(4, bb.getBno());
pstmt.executeUpdate();
System.out.println("글수정완료 - 비번일치");
//리컨값 변경
result =1;
}else{//비번불일치
System.out.println("글수정실패 - 비번불일치");
result = 0;
}
}else{
System.out.println("글수정실패 - 해당글없음");
result = -1;
}

} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
closeDB();
}
return result;
}//updateBoard닫음

[ITWILL : JSP]Javabean 7 : 게시판만들기(글 총갯수, 글목록, 페이징처리)

ITWILL학원 : 28강 JSP기초 BY 정규태강사

1. 순서

  1. 디비에서 전체 글목록을 읽어서 가져오기
    • 글을 읽어오는 작업은 많은 리소스를 필요로한다.
  2. BoardList.jsp 생성
  3. BoardDAO.java에 getBoardCount() 메서드 생성
    • 디비에 글이 있는지 확인 후 있으면 글 모두 가져오기, 없으면 가져오지않기
  4. BoardDAO.java에 getBoardList() 메서드 생성
  5. 최신 글이 위로 오게 정렬 (쿼리이용)
    • 데이터역순정렬의 방법은 두가지
      • 쿼리단계에서 가져올때부터 역순: 더욱 효율적
      • 쿼리로 가져와서 화면에 뿌릴때 역순
  6. 페이징처리하기
  7. 페이지블럭 만들기

2. BoardList.jsp생성

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
<%
//1. 디비에서 전체 글목록을 읽어서 가져오기
//2. BoardDAO 객체생성
BoardDAO bdao = new BoardDAO();
//3. 디비에 글이 있는지 확인 후 있으면 글 모두 가져오기,없으면 가져오지않기 : getBoardCount()
int cnt = bdao.getBoardCount();

//7. 페이징처리 (이미 유명한 알고리즘 공식, 사용법만 알면 됨)
//7-1. 한 페이지에서 보여줄 글의 개수 설정(5개, 변경가능)
int pageSize = 5;
//7-2. 지금 내가 몇페이지에 있는 확인
//페이지번호는 숫자인데 왜 String으로 하는지 ? => 연산을 할 것이 아니라서 String이 편함
String pageNum = request.getParameter("pageNum");
//7-3. 페이지번호정보가 없을 경우 내가 보는 페이지가 첫페이지가 되도록
if(pageNum == null){
pageNum ="1";
}
//7-4. 시작행번호계산
//10개씩 컬럼 나누고 2페이지에서 시작행이 11이되고 3페이지에서 시작행이 21이 되게끔 만들기
int currentPage = Integer.parseInt(pageNum); //String을 integer로 변환
int startRow = (currentPage-1)*pageSize + 1;
//currentPage가 2인경우, (2-1)x10+1 = 11
//currentPage가 3인경우, (3-1)x10+1 = 21

//7-5. 끈행번호계산
int endRow= currentPage * pageSize;
//currentPage가 2인경우, 2*10 = 20
//currentPage가 3인경우, 3*10 = 30


//4. 게시판 글의 수를 화면에 데이터 출력
//게시판 총 글의 수 : cnt개
//5. getBoardList() 메서드생성
System.out.println(bdao.getBoardList());

ArrayList boardList = null;

if(cnt != 0){
//일반적인 리스트호출방법, 아래는 페이징처리한 리스트호출방법
//boardList = bdao.getBoardList();
//7-6. 페이징 처리한 리스트 호출 => getBoardList()메서드만들기(메서드 오버로딩)
boardList = bdao.getBoardList(startRow, pageSize);
}

//6. 게시판 모든 내용을 화면에 출력

%>
<fieldset>
<legend>땡땡게시판</legend>
<div id="contents">
게시판 총 글의 수 : <%=cnt %> 개
<input id="writebtn" type="button" value="글쓰기" onclick="location.href='writeForm.jsp'">
<br>
<table>
<tr>
<th>글번호</th>
<th>제목</th>
<th>작성자</th>
<th>조회수</th>
<th>작성일</th>
<th>IP</th>
</tr>
<%//반복문
//ArrayList는 가변배열이므로 length가 없고 size가 존재한다.
//size()메서드는 배열의 요소의 갯수를 리턴
for(int i=0;i<boardList.size(); i++){
//ArrayList 한칸의 정보 ->BoardBean 객체 하나로 이동
BoardBean bb = (BoardBean) boardList.get(i);
%>
<tr>
<td><a href="content.jsp?bno=<%=bb.getBno()%>&pageNum=<%=pageNum%>"><%=bb.getSubject() %></a></td>
<td><%=bb.getSubject() %></td>
<td><%=bb.getName() %></td>
<td><%=bb.getReadcount() %></td>
<td><%=bb.getDate() %></td>
<td><%=bb.getIp() %></td>
</tr>
<%
}
%>
</table>
</div>
</fieldset>
<%
//8. 페이지 이동버튼
if(cnt != 0){ //cnt는 전체 글 갯수
//8-1. 페이지갯수처리
//전체페이지 50개이고 화면에 10개씩 출력 => 5페이지만 있으면됨
//전체페이지 57개이고 화면에 10개씩 출력 => 6페이지만 있으면됨
//삼항연산자로 처리
int pageCount = cnt/pageSize + (cnt%pageSize == 0? 0:1);

//8-2. 화면에 보여줄 페이지번호의 갯수(페이지블럭)
int pageBlock = 3; //페이지에 10개 페이지갯수 보여줌

//8-3. 페이지블럭의 시작페이지번호
//현재 11페이지면, (11-1)/10 * 10 + 1 = 11
int startPage = ((currentPage-1)/pageBlock) * pageBlock + 1;

//8-4. 페이지블럭의 끝페이지번호
int endPage = startPage + pageBlock - 1;
if(endPage > pageCount){
endPage = pageCount;
}

//8-5. 이전, 숫자, 다음처리
// 이전
%>
<div id="pageBlock">
<%
if(startPage > pageBlock){
%>
<a href="boardList.jsp?pageNum=<%=startPage-pageBlock%>"> 이전 </a>
<%
}

//숫자
for(int i=startPage; i<=endPage; i++){
%>
<a href ="boardList.jsp?pageNum=<%=i%>"> <%=i%> </a>
<%
}
//다음
if(endPage < pageCount){
%>
<a href ="boardList.jsp?pageNum=<%=startPage+pageBlock%>"> 다음 </a>
<%
}
%>
</div>
<%

}
%>

3. BoardDAO.java에 getBoardCount() 메서드생성

BoardDAO.java에 getBoardCount() 메서드 생성

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
public int getBoardCount(){

int count = 0;

try {
//디비연결
getCon();
//sql작성, pstmt
sql = "select count(*) from itwill_board";
pstmt = con.prepareStatement(sql);
//실행 -> rs저장
rs = pstmt.executeQuery();
//데이터처리
if(rs.next()){
count = rs.getInt(1); // 데이터가 없으면 null이고 return 0값이 된다.
//count = rs.getInt("count(*)"); 위와 동일한 결과
System.out.println("게시판 글 갯수 확인 :"+ count);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
closeDB();
}
return count;
}//getBoardCount닫기

4. BoardDAO.java에 getBoardList() 메서드생성

BoardDAO.java에 getBoardList() 메서드 생성

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
//DB에서 게시글 전체 가져오는 메서드 구현
public ArrayList getBoardList(){
//가변길이 배열 생성
ArrayList boardList = new ArrayList();

try {
//1. 디비연결
getCon();
//2. sql작성, pstmt
//sql = "select * from itwill_board";
//정렬(최신글이 가장 위쪽으로 보이게) : re_ref(그룹번호) 내림차순
sql = "select * from itwill_board order by re_ref desc";
pstmt = con.prepareStatement(sql);
//3. 실행 -> rs저장
rs = pstmt.executeQuery();
//4. 데이터처리
//정보의 갯수가 몇개인지 모르기때문에 while 반복문을 사용
while(rs.next()){
//4-1.BoardBean 객체생성해서 그 안에 rs데이터 저장
BoardBean bb = new BoardBean();
bb.setBno(rs.getInt("bno"));
bb.setContent(rs.getString("content"));
bb.setDate(rs.getDate("date"));
bb.setFile(rs.getString("file"));
bb.setIp(rs.getString("ip"));

bb.setName(rs.getString("name"));
bb.setPw(rs.getString("pw"));
bb.setRe_lev(rs.getInt("re_lev"));
bb.setRe_ref(rs.getInt("re_ref"));
bb.setRe_seq(rs.getInt("re_seq"));

bb.setReadcount(rs.getInt("readcount"));
bb.setSubject(rs.getString("subject"));
//여기까지가 한 행의 데이터를 저장한 것임. while로 모든 행을 반복

//가변배열(ArrayList)에 위의 데이터 저장
//즉 배열 한칸에 회원 1명의 정보를 저장함.
boardList.add(bb); //업캐스팅
}
} catch (Exception e) {
e.printStackTrace();
} finally {
closeDB();
}
return boardList;
}//getBoardcontent닫기

5. 페이징처리 : BoardDAO.java에 getBoardList(int startRow, int pageSize) 오버로딩 메서드 만들기

getBoardList(int startRow, int pageSize) 오버로딩 메서드만들고 sql구문 변경하기

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
//DB에서 게시글 전체 가져오는데 페이징처리한 메서드 구현 (메서드 오버로딩)
public ArrayList getBoardList(int startRow, int pageSize){
//가변길이 배열 생성
ArrayList boardList = new ArrayList();

try {
//1. 디비연결
getCon();
//2. sql작성, pstmt
//게시판의 데이터 목록중에서 10개씩 정렬해서 가져오기
//re_ref(그룹번호) 내림차순 + re_seq(답글순서결정)오름차순으로 정렬
//데이터 짤라서 가져오기 limit 시작행-1, 페이지갯수 => 해당 위치부터 개수만큼 가져오기
sql = "select * from itwill_board order by re_ref desc, re_seq asc"
+"limit ?,?";
pstmt = con.prepareStatement(sql);
pstmt.setInt(1, startRow-1);
pstmt.setInt(2, pageSize);
//3. 실행 -> rs저장
rs = pstmt.executeQuery();

while(rs.next())이후로 getBoardList()와 동일
}
}

[ITWILL : JSP]자료구조2 : Stack클래스, Queue인터페이스, Map인터페이스

ITWILL학원 : 27강 JSP기초 BY 정규태강사

https://slidesplayer.org/slide/11290986/

1. 자료구조 : Stack 클래스

  • top에서만 데이터의 입출력 발생하기 때문.
  • LIFO 구조(FILO 구조) : 가장 먼저 들어온 데이터가 가장 마지막에 나가는 구조.
    • 데이터 입력 -> push
    • 데이터 빼내기 -> pop
  • 장점 : 특정 자료구조의 형태로 처리했을때 데이터처리가 가장 효율적이다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
Stack st = new Stack();

//데이터삽입
st.push("1-java");
st.push("2-jsp");
st.push("3-web");
st.push("4-db");
System.out.println(st);

//데이터 빼내기
while(! st.isEmpty()){ //스택클래스가 비어있지 않은 경우
System.out.println(st.pop()); //LIFO
}
System.out.println(st);

//출력값
[1-java, 2-jsp, 3-web, 4-db]
4-db
3-web
2-jsp
1-java
[]

출력값을 보면 데이터가 빠져나가는 순서가 LIFO이다.

2. 자료구조 : Queue 인터페이스

  • FIFO/LILO : 먼저 들어온 데이터가 먼저 처리되는 구조. 즉 입력된 순서대로 처리되는 구조
    • First Input First Output
    • Last Input Last Output
  • 스택은 클래스이지만 큐는 인터페이스이다 -> 따라서 큐는 객체생성을 할수없지만 구현을 통해서 생성가능하다
    • LinkedList 클래스 : 큐인터페이스를 구현한 클래스
    • 인터페이스는 업캐스팅이 가능할까? ㅇㅇ 가능!
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
Queue que = new LinkedList(); //업캐스팅(LinkedList클래스->Queue인터페이스)
//데이터입력
que.offer("1-java");
que.offer("2-jsp");
que.offer("3-web");
que.offer("4-db");
System.out.println(que);

//데이터빼내기
//peek() : Queue안에 데이터가 있는지 없는지 판단하는 메서드 -> 없으면 null리턴
while(que.peek() != null){ // 큐 안에 데이터가 있는지 없는지 판단, 없을경우 null
System.out.println(que.poll());
}

//출력값
[1-java, 2-jsp, 3-web, 4-db]
1-java
2-jsp
3-web
4-db

출력값을 보면 빠져나가는 순서가 FIFO이다.

3. 자료구조 : Map인터페이스

  • Map, table 접미어가 붙은 자료구조이다.
  • 데이터저장시 (키, 데이터)쌍으로 저장하여 사용하는 구조
  • map은 인터페이스이므로 객체생성을 할수없지만 구현을 통해서 생성가능하다
    • hashtable 클래스 : 맵인터페이스를 구현한 클래스
  • 키값을 사용해서 검색 인덱스생성 -> 데이터 검색시간이 짧음.
  • 참고링크 : 컬렉션 프레임워크 Map계열 자세히

https://lelumiere.tistory.com/3

  • 예시 : Map계열의 hashtable
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    Map m = new Hashtable(); //업캐스팅

    //데이터입력
    m.put("사과", "apple");
    m.put("오렌지", "orange");
    m.put("복숭아", "peach");
    System.out.println(m);

    //데이터출력하기
    System.out.println(m.get("복숭아"));
    System.out.println(m.get("바나나"));

    //출력값
    {오렌지=orange, 사과=apple, 복숭아=peach}
    peach
    null

[ITWILL : JSP]Javabean 6 : 게시판만들기(글쓰기)

ITWILL학원 : 27강 JSP기초 BY 정규태강사

1. 웹 개발의 기초 : CRUD

https://newstars.tistory.com/436

  • 기본 로직 :

    1. 게시판 글쓰기 = 데이터입력
    2. 글 리스트 = 데이터검색
    3. 글 본문보기 = 데이터검색
    4. 글 수정 = 데이터 수정
    5. 글 삭제 = 데이터 삭제
  • 추가할 로직 :

    1. 답글쓰기 (댓글과 다른 답글기능)
    2. 파일업로드 / 썸네일

위와 같은 두 개의 로직은 요구사항분석이라고도 부른다

1-1. 개발순서

  1. 사용자 요구사항 분석
  2. 데이터 테이블 설계 = DB
    1. 테이블생성 테이블명 itwill_board
    2. 글번호 : bno
    3. 글쓴이 : name
    4. 글 비밀번호 : pw
    5. 글 제목 : subject
    6. 글 내용 : content
    7. 조회수 : readcount
    8. 답글 : re_ref, re_lev, re_seq
    9. 글쓴날짜 : date
    10. 파일 : file
      • varchar(200)를 쓰는 이유는
    11. 글쓴이의 IP주소 : ip
  3. writeForm.jsp 작성
  4. writePro.jsp 작성
  5. BoardBean.java 생성
  6. BoardDAO.java 에서 getCon() DB연결메서드 구현
  7. BoardDAO.java 에서 insertBoard() 글쓰기메서드 구현

1-2. 데이터 테이블 설계 = DB

테이블생성 테이블명 itwill_board을 생성한 뒤 아래처럼 컬럼을 작성한다.

  1. 글번호 : bno - INT NOT NULL, PRIMARY KEY (bno)
    • 글번호는 AI(Auto Increment)를 해야한다 말아야한다는 의견이 분분하다. 실습에선 AI없이 진행.
  2. 글쓴이 : name - VARCHAR(45) NOT NULL
  3. 글 비밀번호 : pw - VARCHAR(45) NOT NULL
  4. 글 제목 : subject - VARCHAR(45) NOT NULL
  5. 글 내용 : content - VARCHAR(2000) NOT NUL
  6. 조회수 : readcount - INT NULL
  7. 답글 : re_ref, re_lev, re_seq - 세 컬럼 다 INT NULL
  8. 글쓴날짜 : date - DATE NULL
  9. 파일 : file - VARCHAR(200) NULL
    • varchar(200)를 쓰는 이유는 파일은 DB가 아닌 서버에 저장되고 DB는 이름만 저장해놓기때문.
  10. 글쓴이의 IP주소 : ip - VARCHAR(45) NULL

1-3. writeForm.jsp 작성

1
2
3
4
5
6
7
8
9
10
11
12
<fieldset>
<legend>게시판 글쓰기</legend>
<form action="writePro.jsp" method="post" name="fr">
글쓴이 : <input type="text" name="name"><br>
비밀번호 : <input type="password" name="pw"><br>
제목 : <input type="text" name="subject"><br>
내용 : <br>
<textarea rows="10" cols="35" name="content" placeholder="여기에 작성해주세요"></textarea><br>
<input type="submit" value="글쓰기">
<button type="reset">초기화</button>
</form>
</fieldset>

1-4. writePro.jsp 작성

글쓰기를 처리하는 페이지이다.
입력창에서 받은 데이터를 DB로 이동시킨 뒤 사용자는 글목록페이지로 이동

  • jsp:setProperty 의 동작방식

      1. String name = request.getParameter(“bno”)
      1. bb.setbno(bno)
    • 모든 변수에 위의 1번,2번동작을 처리
  • 전달정보 확인위한 출력

    • System.out.println(bb)
    • System.out.println(bb.toString())
    • 위의 두 코드는 동일한 출력값을 가진다.
  • 로그인한사람만 글쓸수있게 처리

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
<%//1. 한글처리
request.setCharacterEncoding("UTF-8");
%>

//6. 로그인한사람만 글쓸수있게처리
String id = (String) session.getAttribute("id");
if( id == null){
%>
<script type="text/javascript">
alert("로그인 후 이용가능합니다");
history.back();
</script>
<%
}

<!-- 2. 액션태그사용 : 전달된 정보를 저장(bno, name, pw 등등) - 자바빈객체에 저장-->
<jsp:useBean id="bb" class="com.itwillbs.board.BoardBean" />
<!-- 2-1. 파라미터 값 저장 : jsp:setProperty -->
<jsp:setProperty property="*" name="bb"/>
<%//2-2. 전달정보 확인위한 출력 : null인 값들은 별로도 추가해줘야한다.
System.out.println(bb); //bb.toString()과 동일한 동작
//2-3. IP정보를 추가
System.out.println(request.getRemoteAddr());
bb.setIp(request.getRemoteAddr());
System.out.println(bb);
//2-4. date정보

//3. 디비처리작업진행 : boardDAO객체 생성
BoardDAO bdao = new BoardDAO();

//4. 데이터처리 : BoardDAO객체 안의 메서드 중 글스기 기능을 하는 메서드 호출
bdao.insertBoard(bb);

// 5. 글목록 페이지로 이동
response.sendRedirect("boardList.jsp");

1-5. BoardBean.java 생성

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
//1번규칙만족 : 클래스는 public
public class BoardBean {
//2번규칙만족 : 멤버변수선언 private
private int bno;
private String name;
private String pw;
private String subject;
private String content;
private int readcount;
private int re_ref;
private int re_lev;
private int re_seq;
private Date date;
private String file;
private String ip;

//4번규칙만족 : 기본생성자존재하지만 생략됨
//public BoardBean(){}

//3번규칙만족 : 멤버변수마다 별도의 get/set메소드가 존재해야한다.
public int getBno() {
return bno;
}
public void setBno(int bno) {
this.bno = bno;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}

//(중략)

public String getIp() {
return ip;
}
public void setIp(String ip) {
this.ip = ip;
}

//5. toString()
@Override
public String toString() {
return "BoardBean [bno=" + bno + ", name=" + name + ", pw=" + pw + ",
subject=" + subject + ", content=" + content + ", readcount=" + readcount + ",
re_ref=" + re_ref + ", re_lev=" + re_lev + ", re_seq=" + re_seq + ",
date=" + date + ", file=" + file + ", ip=" + ip + "]";
}

1-6. BoardDAO.java 에서 getCon() DB연결메서드 구현

드라이브로드, DB연결 메서드인 getCon()구현

  • getCon() 작성순서 : 리턴값없이 진행

      1. 라이브러리설치 (WEB-INF, LIB에 추가)
      1. /META-INF/context.xml 파일생성
      1. /WEB-INF/web.xml 파일수정
      1. DAO 처리
  • 예외처리 throws 방법 : 메서드를 호출하는 시점에 예외처리를 함

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
public class BoardDAO {
Connection con = null;
String sql = "";
PreparedStatement pstmt = null;
ResultSet rs = null;

//DB연결메서드 구현
private void getCon() throws Exception{
//Context 객체 생성
//Context인터페이스이기때문에 직접객체생성할 수 없어서 InitialContext클래스를 사용해서 객채생성
//예외처리 : throws사용하는 방법
Context init = new InitialContext(); //업캐스팅
//디비연결정보를 불러오기 ->DataSource 타입으로 저장
// 고정문구"java:comp/env/다른문구context파일의 name값입력"
DataSource ds = (DataSource) init.lookup("java:comp/env/jdbc/mysqlDB");
//ds 사용해서 연결
//멤버변수는 static이 아니기때문에 new BoardDAO();객체생성 후에 멤버변수들이 생성된다.
//그리고 getCon()메서드를 하면 멤버변수 con에 데이터(ds.getConnection();)가 담기게 된다.
//따라서 이때 return하지 않고 써도된다.
con = ds.getConnection();
System.out.println("디비연결성공 + con");
}//getCon닫음

//자원해제 메서드 구현
public void closeDB(){
try{
if(rs != null) rs.close();
if(pstmt != null) pstmt.close();
if(con != null) con.close();
} catch (SQLException e) {
e.printStackTrace();
}
}//closeDB닫음

}BoardDAO클래스닫음

1-7. BoardDAO.java 에서 insertBoard() 글쓰기 메서드 구현

insertBoard()메서드 구현

  • if(rs.next())가 끝나는 종료되는 순간은?
    • 글이 없으면 null인데 어떻게 조건문이 true가 되어 구현될수있을까?
    • rs가 faluse가 되는 시점은 EOF만나는 순간이다.
    • 즉, NULL이 있어도 진행된다.
  • getInt()사용법 두가지
    • getInt(컬럼명)사용 : num = rs.getInt(“max(bno)”)+1;
    • getInt(idx)사용 : 둘다 동일한 결과. idx사용하면 컬럼명보다 데이터 처리속도도 빠르다- /getInt => 데이터 값을 리턴, 값이 SQL-NULL경우 0리턴
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
//글쓰기 메서드 구현
public void insertBoard(BoardBean bb){
//글번호를 저장하는 변수 생성
int num = 0;

try {
//1. 디비연결
getCon();
//2. SQL구문작성 & pstmt
//3. 글번호계산 : 지금 있는 글 번호중 가장 큰 번호가 뭔지 확인하기만 하면 되니까
sql = "select max(bno) from itwill_board";
pstmt = con.prepareStatement(sql);
//4. 글번호계산한거 실행
rs = pstmt.executeQuery();

//5. 데이터처리(글번호 계산)
if(rs.next()){
//글이 없으면 null이 어떻게 조건문을 돌수있을까? rs가 faluse가 되는 시점은 EOF만나는 순간이다.
//즉, NULL이 있어도 진행된다.

//getInt(컬럼명)사용 : num = rs.getInt("max(bno)")+1;
//getInt(idx)사용 : 둘다 동일한 결과. idx사용하면 컬럼명보다 데이터 처리속도도 빠르다
//getInt => 데이터 값을 리턴, 값이 SQL-NULL경우 0리턴
num = rs.getInt(1)+1;
}

System.out.println("글번호 : "+num);
//6. 글쓰기(저장) : 실무에서는 물음표가 기본 20개이상이다. 5개씩 잘라서 String연결하면 헷갈리지않는다.
//Date는 now()메서드를 이용한다.
//now() : 자동으로 SQL구문 실행시 시스템시간 정보를 불러옴
sql = "insert into itwill_board value("
+"?,?,?,?,?,"
+"?,?,?,?,now(),"
+"?,?)";
pstmt = con.prepareStatement(sql);
pstmt.setInt(1, num);//bno는 가지고있는게 아니라 계산해서 만든것이므로 num사용
pstmt.setString(2, bb.getName());
pstmt.setString(3, bb.getPw());
pstmt.setString(4, bb.getSubject());
pstmt.setString(5, bb.getContent());
pstmt.setInt(6, 0);//조회수는 글쓰지마자 올라가지않는다. 글쓰는 당시에는 조회수가 0이니까 초기화한다.
pstmt.setInt(7, num);//답변글 그룹번호이므로 일반글번호와 동일하다.
pstmt.setInt(8, 0);//답변글 들여쓰기(처음 작성하는 일반 글의 들여쓰기는 0이므로 초기화한다)
pstmt.setInt(9, 0);//답변글순서(처음 작성하는 일반글이므로 일반글 제일위쪽(0)으로 초기화한다)
pstmt.setString(10, bb.getFile());
pstmt.setString(11, bb.getIp());

//7. 실행
pstmt.executeUpdate();
System.out.println("게시판글쓰기 성공");
} catch (Exception e) {
// TODO Auto-generated catch block
System.out.println("게시판글쓰기 실패");
e.printStackTrace();
} finally {
//자원해제
closeDB();
}
} //insertBoard메서드닫음

2. 예외처리 차이점(try catch와 throws)

  • try catch 방법
  • throws 방법

자바 예외처리(try catch, throws)
try catch는 예외를 직접 처리하기 때문에 메서드를 호출해도 더 이상 예외처리를 할 필요가 없습니다.
하지만 throws같은 경우는 호출하는 쪽에다가 예외처리를 맡겨버리는(?) 느낌?
그래서 호출하는 메소드에 throws가 있으면
호출하는 쪽에서도 예외처리를 다시 해줘야되요!

[ITWILL : JAVA]기본클래스 이외에 자바 구성요소2 : enum

ITWILL학원 : 18강 JAVA BY 윤미영강사

1. enum(이넘)의 정의

  • enum은 열거형 데이터 타입이라고 한다.
  • 데이터가 몇 가지 한정된 상수값으로 구성될때 주로 사용.
  • ex) 계절을 나타낼때 String타입보다 enum을 생성하여 봅, 여름, 가을, 겨울의 딱 4개의 값만 설정하는 것이다.

2. enum 사용법

  • 키워드 class대신 enum사용,
  • enum내부에는 상수값 나열 -> 이 상수값들을 enum상수라고 부름
  • 대소문자 구분함
1
2
3
enum Season{
SPRING, SUMMER, FALL, WINTER //=>각각 0,1,2,3의 ordinal값을 가짐
}
  • 선언위치에 따른 변화
    • 같은 클래스 내부에서 enum사용시 (innerEnum) : Season.SPRING
    • 외부 클래스에서 enum사용시 (OuterEnum) : 해당클래스명.Season.SPRING

3. 일반 클래스와 enum 차이점

  • 접근제어자 : public, default만 사용가능
  • 내부적으로 java.lang.Enum클래스 상속 -> 따라서 별도로 다른 클래스 상속받을 수 없다.
  • 여러 인터페이스를 구현하는 것은 상관없다.
  • enum을 이용하면 비교할때 단순히 값만을 비교하는 것이 아니라 타입까지 비교한다. => 안정적인 프로그래밍가능

4. enum메서드

enum타입들은 java.lang.Enum 클래스를 기본적으로 상속받고 있기 때문에 java.lang.Enum 클래스에 선언된 메서드들을 사용가능하다.

메서드명 선언부 설명
name() public final String name() enum상수의 이름을 문자열로 리턴한다
ordinal() public final int ordinal() 0부터 시작하는 enum 상수의 순서를 리턴한다
comparedTo() public final int com[aredTo(E o) enum상수의 ordinal 차이를 리턴한다
values() public static T[] values() enum타입에 선언된 enum상수를 배열로 리턴한다
valueOf() public static T<extends Enum<T>> T valueOf(Class<T> enumType, String name) 문자열로 매핑된 enum상수 객체를 리턴한다

5. enum상수를 이용한 연산

  • enum상수는 주로 비교연산에서 사용된다.

enum을 사용하여 계절별로 다른 출력값을 나타내는 코드를 작성해보자.

  1. OuterEnum사용
  2. 첫번째방법 : if조건문 + comparedTo()
  3. 두번째방법 : switch
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
enum Season{
SPRING, SUMMER, FALL, WINTER
}

public class SeasonEnumTest {

//첫번째방법 : if조건문 + comparedTo()
public void compareEnum(Season s){
if(s.equals(Season.SPRING)){
System.out.println(s.compareTo(Season.WINTER));
System.out.println("따뜻한 봄");
}else if(s.compareTo(Season.WINTER) < 0){
System.out.println(s.compareTo(Season.WINTER));
System.out.println("최소한 겨울은 아니잖아요");
}else{
System.out.println(s.compareTo(Season.WINTER));
System.out.println("추운 겨울");
}
}

//두번째방법 : switch
public void enumSwitch(Season s){
switch(s){
case SPRING :
System.out.println("봄");
break;
case SUMMER :
System.out.println("여름");
break;
case FALL :
System.out.println("가을");
break;
default:
System.out.println("겨울");
}
}

public static void main(String[] args) {
// TODO Auto-generated method stub
SeasonEnumTest set = new SeasonEnumTest();
set.compareEnum(Season.SPRING);
set.enumSwitch(Season.SPRING);
}
}

6. enum에 멤버 추가 가능

  • enum에도 사용자가 원하는 멤버변수와 멤버메서드를 추가할 수 있다
  • 주의점 : enum상수들만을 정의할때는 세미콜론이 필료없지만 별도의 멤버를 추가하는 경우에는 세미콜론을 추가해서 상수 선언이 끝나는 것을 표시해줘야한다.

7. enum에 생성자 추가 가능

  • enum의 생성자의 접근 제어자 : private만 가능하고 생략가능.
  • 외부에서 해당 생성자를 호출할 수는 없으며 내부에서 상수를 정의하면서 파라미터로 전달.