[ITWILL : JSP]Javabean 9 : 게시판만들기(글삭제하기)

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

1. 글삭제하기기능구현 순서

  1. deleteForm.jsp 작성
  2. deletePro.jsp 작성
  3. BoardDAO.java에서 bdao.deleteBoard(bno, pw)메서드 생성
  4. 기존의 boardList.jsp에 id가 있을 경우 추가
  5. 기존의 content.jsp 로그인상태에 따라 다르게 보이는 버튼 추가

2. deleteForm.jsp 작성

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<%
//1. 한글처리
request.setCharacterEncoding("UTF-8");

//2. 파라미터저장
int bno = Integer.parseInt(request.getParameter("bno"));
String pageNum = request.getParameter("pageNum");

%>
<fieldset>
<legend>게시글 삭제</legend>
<form action="deletePro.jsp?pageNum=<%=pageNum%>" method="post">
<input type="hidden" name="bno" value="<%=bno%>">
비밀번호 : <input type="password" name="pw"><br>
<input type="submit" value="글삭제하기" class="btn">
<input type="button" value="뒤로가기" class="btn" onclick="history.back()">
</form>
</fieldset>

3. deletePro.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은 파라미터로)
int bno = Integer.parseInt(request.getParameter("bno"));
String pageNum = request.getParameter("pageNum");
String pw = request.getParameter("pw");
//3. DAO생성
BoardDAO bdao = new BoardDAO();
//4. 정보수정메서드 updateBoard(bb)
// -> 결과를 정수형 데이터로 리턴 (1=>정상처리, 0=>비번오류, -1=>해당글없음)
int result = bdao.deleteBoard(bno, pw);
if(result == 1){
%>
<script type="text/javascript">
alert("정상적으로 글 삭제되었습니다");
location.href="boardList.jsp";
</script>
<%
}else if(result == 0){
%>
<script type="text/javascript">
alert("비밀번호 오류");
history.back();
</script>
<%
}else{
%>
<script type="text/javascript">
alert("존재하지않는 게시글입니다");
history.back();
</script>
<%
}
%>

3. BoardDAO.java에서 bdao.deleteBoard(bno, pw)메서드 생성

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
public int deleteBoard(int bno, String pw){
int result = -1;

try {
getCon();
sql="select pw from itwill_board where bno=?";
pstmt = con.prepareStatement(sql);
pstmt.setInt(1, bno);
rs = pstmt.executeQuery();
if(rs.next()){
if(pw.equals(rs.getString("pw"))){
sql="delete from itwill_board where bno=?";
pstmt = con.prepareStatement(sql);
pstmt.setInt(1, bno);
pstmt.executeUpdate();
System.out.println("글삭제 성공");
result = 1;
}else{
result = 0;
System.out.println("글삭제 중 비번오류");
}
}else{
result = -1;
System.out.println("글삭제 중 select오류");
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
closeDB();
}
return result;
}//deleteBoard()닫음

4. 기존의 main.jsp에 게시판바로가기 버튼 추가

글삭제의 경우 아무나 할 수 없어야한다.
따라서 로그인한 사람만이 글을 쓰고 글을 삭제할 수 있도록 구현해보자.
이전에 구현했던 main.jsp에 게시판글바로볼 수 있는 버튼을 추가하고 location.href='../board/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
<%//1.한글처리, 파라미터 
request.setCharacterEncoding("UTF-8");
String id = (String) session.getAttribute("id");//object를 string으로 다운캐스팅
String name = request.getParameter("name");
//1-1. id없이는 진입불가, id없는 경우 로그인페이지로 이동
if(id == null){
response.sendRedirect("loginForm.jsp");
}
%>
<h2><%=id %>님 환영합니다.</h2>
<%=name %><br>

<input type="button" value="ITWILL게시판가기" class="btn" onclick="location.href='../board/boardList.jsp'">
<input type="button" value="회원정보조회" class="btn" onclick="location.href='memberinfo.jsp'">
<input type="button" value="회원정보수정" class="btn" onclick="location.href='updateForm.jsp'">
<input type="button" value="로그아웃" class="btn" onclick="location.href='logout.jsp'">
<input type="button" value="회원탈퇴" class="btn" onclick="location.href='deleteForm.jsp'">

<!-- 관리자일때만 메뉴확인가능 -->
<% if(id != null){
if(id.equals("admin")){ %>
<input type="button" value="회원전체목록(관리자용)" class="btn" onclick="location.href='memberList.jsp'">
<%
}
}
%>

5. 기존의 boardList.jsp에 id가 있을 경우 추가

  • id가 없을 경우 : 로그인버튼만 표시
  • id가 있을 경우 : 로그아웃, 글쓰기버튼 표시
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
<fieldset>
<legend>땡땡게시판</legend>
<div id="contents">
게시판 총 글의 수 : <%=cnt%>
<%
if(id == null){
%>
<input class="btn" type="button" value="로그인" onclick="location.href='../member/main.jsp'">
<%
}else if( id != null){
%>
<input class="btn" type="button" value="로그아웃" onclick="location.href='../member/logout.jsp'">
<input class="btn" 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><%=bb.getBno()%></td>
<td><a href="content.jsp?bno=<%=bb.getBno()%>&pageNum=<%=pageNum%>"><%=bb.getSubject()%></a></td>
<td><%=bb.getName()%></td>
<td><%=bb.getReadcount()%></td>
<td><%=bb.getDate()%></td>
<td><%=bb.getIp()%></td>
</tr>
<%
}
%>
</table>
</div>
</fieldset>

6. 기존의 content.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
<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">

<% //현재페이지에 로그인 정보가 없거나 글쓴이 이름과 아이디가 다를 경우 수정,삭제버튼을 숨긴다
//1.세션값 가져오기
String id = (String) session.getAttribute("id");//objectstring으로 다운캐스팅
//2. 아이디가 존재하면서 이름과 아이디가 같은 경우
if( id != null && id.equals(bb.getName())){
%>
<input type="button" value="글수정" class="btn" onclick="location.href='updateForm.jsp?bno=<%=bb.getBno()%>&pageNum=<%=pageNum%>'">
<input type="button" value="글삭제" class="btn" onclick="location.href='deleteForm.jsp?bno=<%=bb.getBno()%>&pageNum=<%=pageNum%>'">
<input type="button" value="답글쓰기" class="btn" onclick="location.href='reWriteForm.jsp?bno=<%=bb.getBno()%>&re_ref=<%=bb.getRe_ref() %>&re_lev=<%=bb.getRe_lev()%>&re_seq=<%=bb.getRe_seq()%>'">
<%
}
%>
<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>

[ITWILL : JAVA]로깅, 디버깅

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

1. 로깅(Logging)

  • 로깅 : 사용자의 요청사항을 출력하는 것 이외에 애플리케이션에서 발생하는 사건들을 기록하는 것.

참고링크 : java.util.Logging.Logger의 메서드

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
public class SimpleLoggingFile {

private final static Logger logger = Logger.getLogger(SimpleLoggingFile.class.getName());

public static void main(String[] args) throws SecurityException, IOException {
FileHandler fHandler = new FileHandler("mylog_%g.log");
logger.addHandler(fHandler);
logger.log(Level.INFO, "INTO LOG");
logger.info("메서드 타입 인포 로그");
logger.warning("메서드 타입 경고 로그");
logger.severe("메서드 타입 시비어 로그");
}

}

//출력값
723, 2020 11:11:40 오전 ch9.SimpleLoggingFile main
정보: INTO LOG
723, 2020 11:11:40 오전 ch9.SimpleLoggingFile main
정보: 메서드 타입 인포 로그
723, 2020 11:11:40 오전 ch9.SimpleLoggingFile main
경고: 메서드 타입 경고 로그
723, 2020 11:11:40 오전 ch9.SimpleLoggingFile main
심각: 메서드 타입 시비어 로그
  • 더불어 mylog_0.log파일이 생성되었다.

  • 출력된 로그는 콘솔과 함께 파일에도 기록된다.

  • 실무에서는 logging패키지의 클래스보다 주로 logback과 같은 별도의 로깅 프레임워크들을 사용함.

2. 디버깅

  • 리커시브방법 : 함수가 자기 자신을 계속 호출하는 구조 = 재귀함수

  • break point : 프로그램 동작 중 디버깅을 위해서 동작을 멈추는 지점

    • 중단점을 지정해 놓으면 그 전까지 프로그램이 동작하다가 브레이크포인트에서 사용자의 다음동작을 기다린다.
    • step into를 하면 변수뷰창에서 valables가 어떻게 변화하는지 알수있다.

[ITWILL : JAVA]내부클래스

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

1. 내부클래스(p363)

  • 클래스가 서로 밀접한 관련이 있을때 객체생성없이 사용하기 용이하다
  • 주로 이미 만들어진 내부클래스라이브러리를 사용.
  • 공통점 : static 변수는 가질 수 없지만, final static 변수는 가질 수 있다.
    • 만약 상수가 아닌 변수형태로 선언이 되어있다면 그건 앞에 final이 생략되어진 것임.
    • 변수를 사용하고싶다면 차라리 외부클래스의 멤버변수로 선언하는 것이 낫다.
  • 내부클래스의 종류 4가지 :

https://github.com/burberry-check/java-basic/wiki/%EC%B6%94%EC%83%81%ED%81%B4%EB%9E%98%EC%8A%A4,-%EC%9D%B8%ED%84%B0%ED%8E%98%EC%9D%B4%EC%8A%A4

2. 인스턴스 내부클래스

  • 내부클래스를 외부클래스의 멤버변수 선언위치에 선언하는 것.

  • 인스턴스내부클래스는 외부클래스의 멤버변수를 자신의 멤버변수처럼 불러와서 쓸 수 있다.

  • 단독으로 사용하기도한다.

  • 내부클래스의 메서드 사용하는 방법 :

    1. 외부클래스 객체생성 : 외부클래스명 A = new 외부클래스명();
    2. 내부클래스 객체생성 : 내부클래스명 B = A.new 내부클래스명();
    3. 내부클래스의 메서드 사용 : B.method();
    • 이러한 것을 단독사용이라고 한다.
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
public class InstanceInner {
private int outerMember = 1;

private void outerMethod(){
Inner inner = new Inner();
inner.innnerMember = 11;
inner.innerMethod();
}

class Inner{
int innnerMember = 10;
//static int staticMember = 10; staitc멤버변수 선언 불가. 만약 상수가 아닌 변수형태로 선언이 되어있다면 그건 앞에 static이 생략되어진 것임.
static final int finalStaticMember = 20; //단 static final형태는 선언할 수 있다.

private void innerMethod(){
System.out.printf("out : %d, inner %d%n", outerMember, innnerMember);
}
}

//내부클래스 메서드 사용은 어떻게 할까?
public static void main(String[] args) {
InstanceInner ilt = new InstanceInner(); //1.외부클래스객체생성
Inner inner = ilt.new Inner(); //2.내부클래스객채생성
inner.innerMethod(); //3.내부클래스의 메서드사용

}
}

3. 지역클래스(local class)

  • 내부클래스가 외부클래스의 메서드안에서 정의되어지는 것.
  • 지역클래스는 단독으로 사용하지않고 내부에서 객체생성 후 호출해서 사용.
    • 단독사용의 의미 : 직접 메서드를 불러와서사용,
    • 지역클래스인 경우 메서드를 호출하는 순간 객채생성하고 바로 사용할 수 있게해야한다. 즉 단독사용처럼 직접 클래스이름을 불러 사용하는 것이 아니라 지역클래스가 속한 외부클래스메서드를 부르면서 그 속에 있는 클래스가 자동으로 사용되게끔 하는 것이다.
1
2
3
4
5
6
7
8
9
10
class OuterClass(){
...
public methodA(){ //멤버메서드
class InnerClass(){ //로컬클래스
...
}
}
}

//객체생성 후 호출해서 주로 사용

4. 익명클래스(p373)

  • 인터페이스를 구현할 목적으로 사용.
  • 실무에서 자주 사용.
  • 익명클래스의 override는 인터페이스 규칙에 의해 public을 붙여줘야한다
  • 익명클래스를 어떨때 사용할까?
    • 독립적인 클래스 사용 : 인터페이스를 구현한 클래스를 여러번 사용할때 용이.Intf a는 언제어디서나 불러서 사용가능
    • 익명클래스 사용 : 인터페이스를 구현한 클래스를 딱 한번 사용할때 용이. 익명클래스는 Intf b에서만 사용가능. 이름이 없기때문에 불러서 사용할 수 없다.
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
interface Intf{
void methodInf();
}

class A implements Intf{
@Override
public void methodInf() {
System.out.println("인터페이스 메서드 오버라이딩");
}
}

public class test {

public static void main(String[] args){

//기본적인 interface구현(독립적인 클래스사용)
Intf a = new A();
a.methodInf();

//익명클래스를 이용한 interface구현
Intf b = new Intf(){
@Override
public void methodInf() {
System.out.println("익명클래스로 인터페이스 메서드 오버라이딩");
}
};
b.methodInf();
}
}

5. 내부클래스 예시

다양한 내부클래스를 생성한 뒤 main메서드로 호출해보자

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
interface InfoPrintable{
public void printInfo();
}

public class VariousInnerClassTest {

//멤버메서드(매개변수가 인터페이스)
public void useInnerClass(InfoPrintable inner){
inner.printInfo();
}

//멤버메서드
public void useSpeakerTest(){

//로컬 내부클래스생성(메서드안에 선언한 내부클래스=로컬클래스)
class EngSpeaker implements InfoPrintable{
@Override
public void printInfo() {
System.out.println("로컬 내부 클래스");
}
}//EngSpeaker닫음

//멤버메서드사용하여 클래스 부르기
//1. 익명의 내부클래스 생성
useInnerClass(new InfoPrintable(){
@Override
public void printInfo() {
System.out.println("익명의 내부클래스");
}
});

//2. 로컬내부클래스부르기
useInnerClass(new EngSpeaker());

//3. 인스턴스내부클래스부르기
useInnerClass(new InstanceInnerClass());

//4. 걍 밖에있는클래스
useInnerClass(new SomeClass());

}//useSpeakerTest메서드닫음

//인스턴스 내부클래스(외부클래스의 멤버에 생성)
class InstanceInnerClass implements InfoPrintable{
@Override
public void printInfo() {
System.out.println("인스턴스 내부클래스 사용");
}

}//InstanceInnerClass닫음


//만든 내부클래스를 main메서드로 호출해보자
public static void main(String[] args){

VariousInnerClassTest vt = new VariousInnerClassTest();
vt.useSpeakerTest();

}

}//VariousInnerClassTest닫음

//걍 다른 클래스인데 인터페이스구현
class SomeClass implements InfoPrintable{

@Override
public void printInfo() {
System.out.println("걍 상관없는 일반 클래스");
}

}

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

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

1. 답글처리구현 순서

  • 일반글 = 답글이 아닌 글.
  • num : 일반글+답글 둘 다 작성할때마다 계속 증가된 값으로 사용(순차적)
  • re_ref : 답글의 그룹번호(일반글번호와 동일), 답글을 다는 원글의 그룹번호를 사용
  • re_lev (level) : 답글의 레벨값 (깊이), 원글을 기준으로한다 ex)한번내려가면1 두번내려가면 2
  • re_seq (sequence) : 답글의 순서, 원글에 답글이 몇개인지하는 순서대로 카운트.

글목록 예시

  • 일반글은 ref만 num값과 동일하게 초기화
  • 답글은 lev, seq는 0으로 초기화

만약 여기서 3번글의 답글 1개를 추가한다면?
6 / 답급3-1 / 3 / 1 / 1

만약 여기서 3번글의 답글 1개를 추가한다면?
6 / 답글3-1 / 3 / 1 / 1

만약 여기서 3번글의 답글 1개를 또 추가한다면?
7 / 답글3-2 / 3 / 1 / 2

만약 여기서 3번답글인 3-1에 답글 1개를 추가한다면?
8 / 답글3-1-1 / 3 / 2 / 3

만약 여기서 4번밑에 답글을 단다면?
9 / 답글4-1 / 4 / 1 / 1

만약 여기서 일반글 작성한다면?
10 / 일반글 / 10 / 0 / 0

만약 여기서 답글4-1에 답글을 단다면?
11 / 답글4-1-1 / 4 / 2 / 2

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

//전달한 데이터 저장 (bno,re_ref, re_lev, &re_seq)
int bno = Integer.parseInt(request.getParameter("bno"));
int re_ref = Integer.parseInt(request.getParameter("re_ref"));
int re_lev = Integer.parseInt(request.getParameter("re_lev"));
int re_seq = Integer.parseInt(request.getParameter("re_seq"));

//어떻게 가져갈 것인가? 폼태그안에 담아갈까? 주소창에 GET방식으로 가져갈까?
//bean의 멤버변수에 있는 변수는 폼태그안에 담아가면된다. =>hidden 인풋태그
%>
<fieldset>
<legend>게시판 답글쓰기</legend>
<form action="reWritePro.jsp" method="post" name="fr">
<input type="hidden" name="bno" value="<%=bno%>">
<input type="hidden" name="re_ref" value="<%=re_ref%>">
<input type="hidden" name="re_lev" value="<%=re_lev%>">
<input type="hidden" name="re_seq" value="<%=re_seq%>">
글쓴이 : <input type="text" name="name" required><br>
비밀번호 : <input type="password" name="pw" required><br>
제목 : <input type="text" name="subject" maxlength="15" value="[답글] " required><br>
내용 : <br>
<textarea rows="10" cols="35" name="content" placeholder="여기에 답글을 작성해주세요" required></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>

3. reWritePro.jsp 작성

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<%
// 한글 처리
request.setCharacterEncoding("UTF-8");
// 액션태그 사용 파라미터값 저장
// useBean,setProperty
%>
<jsp:useBean id="bb" class="com.itwillbs.board.BoardBean"/>
<jsp:setProperty property="*" name="bb"/>
<%
System.out.println(bb);
// ip 정보 저장
bb.setIp(request.getRemoteAddr());

// BoardDAO 객체 생성 - reInsertBoard(객체)
BoardDAO bdao = new BoardDAO();
bdao.reInsertBoard(bb);

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

4. BoardDAO.java에서 reInsertBoard(BoardBean 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
46
47
48
49
50
51
52
53
54
55
56
public void reInsertBoard(BoardBean bb){
//1.지역변수생성
int num = 0;
//2. 디비연결
try {
getCon();
//sql(게시판의 글번호 중 최댓값 계산) & pstmt
//2-1. 답글번호 계산
sql = "select max(bno) from itwill_board";
pstmt = con.prepareStatement(sql);
// 실행
rs = pstmt.executeQuery();
// 데이터 처리
if(rs.next()){
num = rs.getInt(1)+1;
}
System.out.println(" 답글 번호 : "+num);

//2-2. 답글 순서 재배치
//re_ref(같은 그룹기준)으로 re_seq값이 기존의 값보다 큰 값이 있을경우 seq값을 1증가시킴
sql = "update itwill_board set re_seq=re_seq+1 "
+ "where re_ref=? and re_seq>?";
pstmt = con.prepareStatement(sql);

pstmt.setInt(1, bb.getRe_ref());
pstmt.setInt(2, bb.getRe_seq());

pstmt.executeUpdate();

//2-3. 답글 추가 동작
sql="insert into itwill_board "
+ "values(?,?,?,?,?"
+ ",?,?,?,?,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, bb.getReadcount());
pstmt.setInt(7, bb.getRe_ref()); //기존 원글의 그룹번호와 동일
pstmt.setInt(8, bb.getRe_lev()+1); // 기존의 값 + 1
pstmt.setInt(9, bb.getRe_seq()+1); // 기존의 값 + 1
pstmt.setString(10, bb.getFile());
pstmt.setString(11, bb.getIp());

//3. 실행
pstmt.executeUpdate();
System.out.println("답글쓰기 성공");
} catch (Exception e) {
e.printStackTrace();
} finally {
closeDB();
}
} //reInsertBoard닫음

5. BoardList.jsp에서 답글 들여쓰기 추가 구현

이미지와 조건문을 통해 구현

  • img src=”level.gif” width=”<%=wid%>” height=”15”
  • img src=”re.gif”
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
<fieldset>
<legend>땡땡게시판</legend>
<div id="contents">
게시판 총 글의 수 : <%=cnt%> 개
<%
if(id == null){
%>
<input class="btn" type="button" value="로그인" onclick="location.href='../member/main.jsp'">
<%
}else if( id != null){
%>
<input class="btn" type="button" value="로그아웃" onclick="location.href='../member/logout.jsp'">
<input class="btn" 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><%=bb.getBno()%></td>
<td>
<%
//답글일때만 이미지넣기
//변수 wid를 이용하여 들여쓰기 처리
int wid = 0;
if(bb.getRe_lev() > 0){
wid= 10 * bb.getRe_lev(); //레벨값의 10을 곱한 값만큼 이미지 가로길이를 길게해줌
%>
<img src="level.gif" width="<%=wid%>" height="15">
<img src="re.gif">
<% } %>
<a href="content.jsp?bno=<%=bb.getBno()%>&pageNum=<%=pageNum%>"><%=bb.getSubject()%></a></td>
<td><%=bb.getName()%></td>
<td><%=bb.getReadcount()%></td>
<td><%=bb.getDate()%></td>
<td><%=bb.getIp()%></td>
</tr>
<%
}
%>
</table>
</div>
</fieldset>

[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닫음

[JAVA]예외처리기법3가지 및 Error와 Exception 차이

1. 오류 Error

  • 발생하면 복구하거나 되돌릴 수 없는 심각한 상황.
  • 발생상황 예시 : 메모리부족, 메서드끼리 호출을 무한반복등등.
  • 처리방법 : 오류를 발생하는 요인을 찾아서 업애는 디버깅.
  • 예방법 : 코드 짜임새있게 짜기.
    즉, 프로그램을 잘 짜는 것만이 대안이기때문에 예외처리와 무관하다.

2. 예외 Exception

  • 오류와 비교하면 심각도가 낮으며 프로그램의 정상적인 흐름을 방해하는 상황.
  • 발생상황 예시 : 네트워크 연결 끊기는 상황, 해당 파일을 읽지 못하는 상황등등.
  • 예외처리란 : 예외가 발생했을때 비정상적인 종료를 막고 계속해서 사용할 수 있도록 처리하는 것
  • 예외처리 라이브러리 = 최상위 클래스 = Throwable

https://deftkang.tistory.com/44

  • RuntiomeException = unchecked Exception : 중간에 throws 할 필요없다
  • 그 외 예외 = checked Exception

3. 예외 처리 기법

3-1. try catch finally구문

  • 단축키 : ctrl + space
  • try catch finally :
    • finally블록은 무조건 실행. 예외 발생 여부와 상관없이 반드시 실행되어야하는 내용을 작성.
    • 심지어 return문을 만날때에도 먼저 finally 블록을 실행 후 메서드가 리턴된다.
    • finally 주요 목적 : try블록에서 사용한 시스템 자원(System Resource)의 반납처리.
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
public class TryCatchFinallyFlow {

public static void main(String[] args) {

int num = new Random().nextInt(2);
try{
System.out.println("코드1 : "+ num);
int i = 1/num;
System.out.println("랜덤숫자 1일경우 예외없음");
return;
} catch (ArithmeticException e){
System.out.println("랜덤숫자0일경우 예외처리완료");
} finally {
System.out.println("코드4 : 파이널리 항상 실행");
}
System.out.println("코드5");
}

}
//랜덤숫자가 1일경우 출력값 - return때문에 코드5출력되지않음
코드1 : 1
랜덤숫자 1일경우 예외없음
코드4 : 파이널리 항상 실행

//랜덤숫자가 0일경우 출력값
코드1 : 0
랜덤숫자0일경우 예외처리완료
코드4 : 파이널리 항상 실행
코드5

3-2. Exception 객체 정보 활용

참고링크 : Throwable 메서드

  1. getMessage()사용
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public class SimpleException {
public static void main(String[] args) {
int[] intArr = {10};
try {
System.out.println(intArr[2]);
} catch (Exception e) {
System.out.println("예외발생 - 배열확인필요 : "+ e.getMessage());
}
System.out.println("프로그램을 종료합니다.");
}
}

//출력값
예외발생 - 배열확인필요 : 2
프로그램을 종료합니다.
  1. printStackTrace()사용
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public class SimpleException {
public static void main(String[] args) {
int[] intArr = {10};
try {
System.out.println(intArr[2]);
} catch (Exception e) {
e.printStackTrace();
}
System.out.println("프로그램을 종료합니다.");
}
}
//출력값
java.lang.ArrayIndexOutOfBoundsException: 2
프로그램을 종료합니다.
at ch9.SimpleException.main(SimpleException.java:8)

3-3. try with resources 구문

  • try catch finally 코드가 길다.
  • 따라서 java 7버전에서 새롭게 추가된 기능이 try with resources구문이다.
1
2
3
4
5
try (리소스타입1 res1 = 초기화; 리소스타입2 res2 = 초기화; ...){
//예외 발생 코드
}catch(Exception e){
//예외 처리 코드
}

4. throws 키워드를 통한 예외처리 위임

예외 처리의 두번째방법은 throws 키워드를 통한 위임 또는 전달이다.

  1. throws 키워드
  • throws는 메서드에서 처리해야 할 하나 이상의 예외를 메서드를 호출한 곳으로 던져버린다.
  • 이러한 위임은 처리와는 다름.
  • 첫번째 방법이었던 try catch 에서 catch블록은 예외를 처리해서 없애 버림
  • BUT 위임은 예외를 없애지 못하고 그냥 호출한 곳으로 예외를 전달만 함.
  • 예외를 전달받은 메서드는 다시 예외 처리 책임이 발생함.
  1. throws를 왜 사용할까?
  • 항상 try catch로 처리하는 것은 좋지않다
  • WHY? 특히 API나 다른 모듈에서 사용되는 기능을 제공하는 경우 예외를 전달해서 그 예외에 대해 적절히 대응할 수 있는 코드를 작성할 수 있게 해줄 필요가 있기때문이다.
  • 예 : 어떤 프로그램을 install할때

5. 사용자 정의 예외

  • 예외가 unchecked exception계열이면 중간에 throws절차가 필요없다. (ex : runtiomeException)
  • 고급스러운 코딩이 가능하다.

6. throw와 throws 차이

둘 다 Exception을 발생시키지만 큰 차이가 있다.

  • throws : 예외를 위임하는 예약어
  • throw : 억지로 예외를 발생시키는 예약어, 즉 사용자 정의에 의한 exception = 인위적인 exception이다.
    • 생성자에 exception을 넣으면 예외 문구로 출력된다.
1
throw = new throw("나만의 예외메세지");

[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()와 동일
}
}