19.05.11 JSP 게시판-전체글보기 (카운터) (동영상 52강~54강)

Back-End/JSP 2019. 5. 11. 20:01
728x90
반응형

 

 

 

 

 

리스트 파일에서 "글쓰기" 위치 조정하고, 하부에 "게시글 카운터" 만들기.

 

 

 

  -정리 (카운트 알고리즘)-

 

  EX) 총게시글이 184개라고 가정할 때

       int pageSize = 10;

       String pageNum = 1; //처음엔 null이지만 if문을 사용해서 null과 같을시에는 pageNum에 1값을 준다.

                                   //[다음]을 눌렀을때의 넘어간 페이지 숫자가 대입된다.

 

       int count = 0;    //전체 글의 갯수를 저장하는 변수

       int number = 184;   //페이지 넘버링 변수  (currentPage-1)*pageSize+1;

       int currentPage = 1

       Count = 184

       int startRow = 1 (currentPage-1)*pageSize+1;

       int endRow = currentPage * pageSize;

    

       int pageCount = 19 count / pageSize + (count%pageSize == 0 ? 0 : 1)

       int startPage = 1;

       int pageBlock = 10;

       int endPage = 10 startPage+pageBlock-1

 

 

       1 2 3 4 5 6 7 8 9 10 [다음]

       [다음] 을 누르면 startpage에 1을 더해서 넘어감 즉, 11페이지로 이동

---------------------------------------------------------------------------------------------------

      

       넘어간 다음

 

       총게시글이 184개로 변함없음

       int pageSize = 10;

       String pageNum = 11; //처음엔 null이지만 if문을 사용해서 null과 같을시에는 pageNum에 1값을 준다.

                                   //[다음]을 눌렀을때의 넘어간 페이지 숫자가 대입된다.

 

       int count = 0;    //전체 글의 갯수를 저장하는 변수

       int number = 84;   //페이지 넘버링 변수  (currentPage-1)*pageSize+1;

       int currentPage = 11

       Count = 184

       int startRow = 101 (currentPage-1)*pageSize+1;

       int endRow = 110 currentPage * pageSize;

    

       int pageCount = 19 count / pageSize + (count%pageSize == 0 ? 0 : 1)

       int startPage = 11;

       int pageBlock = 10;

       int endPage = 19 startPage+pageBlock-1  //원래는 20이지만 if문에 의해서 pageCount의 값이 들어가 19가 된다.

 

 

       [이전] 11 12 13 14 15 16 17 18 19 [다음]

       [다음] 을 누르면 startpage에 1을 더해서 넘어감 즉, 20페이지로 이동

 

 

 

 

 

 

 

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
135
136
137
138
139
140
141
142
143
144
145
146
147
148
<%@page import="java.util.Vector"%>
<%@page import="model.BoardDAO"%>
<%@page import="model.BoardBean"%>
<%@ page language="java" contentType="text/html; charset=EUC-KR"
    pageEncoding="EUC-KR"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<body>
 
 
    <center>
        <h2>전체 게시글 보기</h2>
        <!-- 게시글 보기에 카운터링을 설정하기위한 변수들을 선언 -->
 
        <%
            //10개씩 끊어서 화면에 보여주기
            //화면에 보여질 게시글의 개수를 지정
            int pageSize = 10;
 
            //현재 카운터를 클릭한 번호값을 읽어옴 (예를들어 1을 클릭하면 1~10개 까지 나오고, 2를 클릭하면 11~20개 까지 나오도록 하는것)
 
            String pageNum = request.getParameter("pageNum");
            //만약 처음 boardlist.jsp를 클릭하거나 수정 삭제 등 다른 게시글에서 이 페이지로 넘어오면 pageNum값이 없기에 null 처리를 해줌
            //다른페이지에서 num을 넘긴적이 없기때문에 최초의 list페이지를 보여주어야 한다.
 
            if (pageNum == null) {
                pageNum = "1";
            }
            int count = 0//전체 글의 갯수를 저장
            int number = 0//페이지 넘버링 변수
 
            //현재 보고자 하는 페이지 숫자를 저장 (원래 String 타입이이었으니 타입변환을 시킨다.)
            int currentPage = Integer.parseInt(pageNum);
 
            //전체 게시글의 내용을 jsp쪽으로 가져와야함
            //길이를 정확히 알 수 없기 때문에 가변길이인 벡터로 받는다.
            BoardDAO bdao = new BoardDAO();
 
            //전체 게시글의 갯수를 읽어들이는 메소드 호출 (카운터링할려면 전체 게시글의 숫자가 필요하기 때문)
            count = bdao.getAllCount();
 
            //현재 페이지에 보여줄 시작번호를 설정(최신글을 보여주기 위해서. 예를 들면 77번째글이 최신이면 77부터 67번째까지의 게시글을 첫페이지에 보여줌)
            int startRow = (currentPage - 1* pageSize + 1;
            int endRow = currentPage * pageSize;
 
            //최신글 10개를 기준으로 게시글을 리턴 받아주는 메소드 호출
            Vector<BoardBean> vec = bdao.getAllBoard(startRow, endRow);
 
            //테이블에 표시할 번호를 지정
            number = count - (currentPage - 1* pageSize;
        %>
 
        <table width="700" border="1" bgcolor="skyblue">
            <tr height="40">
                <td align="right" colspan="5">
                    <!-- 버튼을 클릭하면 BoardWriteForm.jsp파일로 넘어간다.--> <input type="button"
                    value="글쓰기" onclick="location.href='BoardWriteForm.jsp'">
                </td>
            </tr>
            <tr height="40">
 
                <td width="50" align="center">번호</td>
                <td width="320" align="center">제목</td>
                <td width="100" align="center">작성자</td>
                <td width="150" align="center">작성일</td>
                <td width="80" align="center">조회수</td>
            </tr>
            <%
                for (int i = 0; i < vec.size(); i++) {
                    BoardBean bean = vec.get(i); //벡터에 저장되어있는 bean클래스를 하나씩 추출
            %>
            <tr height="40">
                <!-- 리스트 맨위의 숫자가 가장크고 밑으로 내려오면 감소되기때문에 숫자를 감소시켜서 표시한다. -->
                <td width="50" align="center"><%=number--%></td>
                <!-- 숫자가 하나씩 올라가게 하기위해서 i+1을 해준다 -->
                <!-- getNum()을 쓰면 순서가 복잡해지기 때문 -->
                <td width="320" align="center"><a
                    href="BoardInfo.jsp?num=<%=bean.getNum()%>"
                    style="text-decoration: none"> <!-- 리플 옆에 선을 사라지게 만드는 코드 --> <%
     //답변 들여쓰기를 하기위한 for문
         if (bean.getRe_step() > 1) {
             for (int j = 0; j < (bean.getRe_step() - 1* 5; j++) {
 %>&nbsp; <%
     }
 
         }
 %> <%=bean.getSubject()%></a></td>
                <!-- BoardInfo.jsp파일(정보를 확인하기 위한파일)에 Num값을 넘겨준다 -->
                <td width="100" align="center"><%=bean.getWriter()%></td>
                <td width="150" align="center"><%=bean.getReg_date()%></td>
                <td width="80" align="center"><%=bean.getReadcount()%></td>
            </tr>
            <%
                }
            %>
 
        </table>
        <p>
            <!-- 페이지 카운터링 소스를 작성 -->
            <%
                if (count > 0) {
                    int pageCount = count / pageSize + (count % pageSize == 0 ? 0 : 1); //카운터링 숫자를 얼마까지 보여줄건지 결정
 
                    //시작 페이지 숫자를 설정
                    int startPage = 1;
 
                    if (currentPage % 10 != 0) {
                        startPage = (int) (currentPage / 10* 10 + 1;
 
                    } else {
                        startPage = ((int) (currentPage / 10- 1* 10 + 1;
                    }
 
                    int pageBlock = 10//카운터링 처리 숫자
                    int endPage = startPage + pageBlock - 1//화면에 보여질 페이지의 마지막 숫자
 
                    if (endPage > pageCount)
                        endPage = pageCount;
 
                    //이전이라는 링크를 만들건지 파악
                    if (startPage > 10) {
            %>
            <a href="BoardList.jsp?pageNum=<%=startPage - 10%>"> [이전] </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 + 10%>"> [다음] </a>
            <%
                }
 
                }
            %>
        
    </center>
</body>
</html>
 
cs

 

 

BoardDAO.java (DB연결)

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
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
package model;
 
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.Vector;
 
import javax.naming.InitialContext;
import javax.sql.DataSource;
import javax.naming.Context;
 
public class BoardDAO {
 
    // 데이터베이스에 연결하기 위한 설정
    Connection con;
    PreparedStatement pstmt;
    ResultSet rs;
 
    // 데이터베이스의 커넥션들을 사용하도록 설정하는 메소드
    public void getCon() {
 
        try { // 데이터베이스에 접속할때는 예외처리를 해주어야한다.
 
            Context initctx = new InitialContext(); // 외부에서 데이터를 읽어들어야 하기 때문에 Context 객체 생성
            // 톰캣 서버에 정보를 담아놓은 곳으로 이동함
            Context envctx = (Context) initctx.lookup("java:comp/env"); // lookup메소드를 이용해서 자료를 읽어오는 코드
            DataSource ds = (DataSource) envctx.lookup("jdbc/pool"); // datasource 객체를 선언 , 오브젝트 타입이기 때문에 타입변환을 한다.
 
            con = ds.getConnection(); // 데이터 소스를 기준으로 커넥션을 연결함
        } catch (Exception e) {
            e.printStackTrace(); // 어느부분이 잘못되었는지 알려주는 예외처리
        }
    }
 
    // 하나의 새로운 게시글이 넘어와서 저장되는 메소드
    public void insertBoard(BoardBean bean) {
        getCon();
        // 빈클래스에 넘어오지 않았던 데이터들을 초기화 해주어야 한다.
 
        int ref = 0// 글그룹을 의미한다, 쿼리를 실행시켜서 가장 큰 ref값을 가져온후 +1을 더해주면 된다.
        int re_step = 1// 새글이고, 부모글은 글 스텝(Re_step), 글 레벨(Re_level)은 1이기 때문에 초기값을 1을 준다.
        int re_level = 1// 새글이고, 부모글은 글 스텝(Re_step), 글 레벨(Re_level)은 1이기 때문에 초기값을 1을 준다.
 
        try {
 
            // 가장큰 ref값을 읽어오는 쿼리 준비함 (새로운 글은 ref가 가장크기 때문)
            String refsql = "select max(ref) from board"// board테이블로부터 가장큰 ref를 검색
            // 쿼리를 실행할 객체
            pstmt = con.prepareStatement(refsql);
            // 쿼리 실행후 결과를 리턴
            rs = pstmt.executeQuery();
            if (rs.next()) { // 쿼리(rs)가 결과값이 있다면 실행하는 구문
                ref = rs.getInt(1+ 1// 최대값에 1을 더해서 글그룹을 설정. 새로운글은 ref숫자가 하나씩 올라가야 하기 때문
            }
 
            // 실제로 게시글 전체값을 테이블에 저장
            String sql = "insert into board values(board_seq.NEXTVAL,?,?,?,?,sysdate,?,?,?,0,?)"// 첫번째 값은 ?가 아니라 시퀀스를
                                                                                                    // 사용해
                                                                                                    // 시퀀스에 이미 들어가있는값의
                                                                                                    // 다음값을 자동으로 매핑해서
                                                                                                    // 넣어준다.
            pstmt = con.prepareStatement(sql);
            // ?에 값을 매핑한다. //0은 카운트값이기때문 0을 넣어주었다
            pstmt.setString(1, bean.getWriter());
            pstmt.setString(2, bean.getEmail());
            pstmt.setString(3, bean.getSubject());
            pstmt.setString(4, bean.getPassword());
            pstmt.setInt(5, ref);
            pstmt.setInt(6, re_step);
            pstmt.setInt(7, re_level);
            pstmt.setString(8, bean.getContent());
 
            // 쿼리를 실행하시오.
            pstmt.executeUpdate();
            // 자원 반납
            con.close();
 
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
 
    // 모든 게시글을 리턴해주는 메소드 작성
    public Vector<BoardBean> getAllBoard(int start, int end) {
        // 리턴할 객체 선언
        Vector<BoardBean> v = new Vector<>();
 
        getCon();
 
        try {
            // 쿼리 준비 (컬럼에 Rownum Rnum을 추가하고, 괄호()안의 결과를 A에 넣는다.)
            String sql = "select * from (select A.*, Rownum Rnum from (select * from board order by ref desc, re_step asc)A)"
                    + "where Rnum >= ? and Rnum <= ?";
            // 쿼리를 실행할 객체 선언
            pstmt = con.prepareStatement(sql);
            pstmt.setInt(1, start);
            pstmt.setInt(2, end);
            // 쿼리 실행후 결과 저장
            rs = pstmt.executeQuery();
            // 데이터 개수가 몇개인지 모르기에 반복문을 이용하여 데이터를 추출
            while (rs.next()) {
                // 데이터를 패키징 시키기(가방 = Boardbean 클래스를 이용) 패키지 안에 넣는다는 의미
                BoardBean bean = new BoardBean();
                bean.setNum(rs.getInt(1));
                bean.setWriter(rs.getString(2));
                bean.setEmail(rs.getString(3));
                bean.setSubject(rs.getString(4));
                bean.setPassword(rs.getString(5));
                bean.setReg_date(rs.getDate(6).toString()); // reg데이터가 String타입으로 변한다.
                bean.setRef(rs.getInt(7));
                bean.setRe_step(rs.getInt(8));
                bean.setRe_level(rs.getInt(9));
 
                bean.setReadcount(rs.getInt(10));
                bean.setContent(rs.getString(11));
                // 패키징한 데이터를 벡터에 저장
                v.add(bean);
            }
 
            con.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
 
        return v;
    }
 
    // BoardInfo를 사용할 때 하나의 게시글을 리턴하는 메소드
    public BoardBean getOneBoard(int num) {
        // 리턴타입 선언(객체 생성)
        BoardBean bean = new BoardBean();
        getCon();
        try {
 
            // 조회수 증가 쿼리
            String readsql = "update board set readcount = readcount+1 where num=?"// 읽은 게시글의 조회수를 늘리기 위한 sql문
            pstmt = con.prepareStatement(readsql);
            pstmt.setInt(1, num);
            pstmt.execute();
 
            // 쿼리 준비
            String sql = "select * from board where num=?";
            // 쿼리 실행 객체
            pstmt = con.prepareStatement(sql);
            pstmt.setInt(1, num);
            // 쿼리 실행후 결과를 리턴
            rs = pstmt.executeQuery();
 
            if (rs.next()) { // 게시글에대한 모든 정보를 하나씩 가져옴
                bean.setNum(rs.getInt(1));
                bean.setWriter(rs.getString(2));
                bean.setEmail(rs.getString(3));
                bean.setSubject(rs.getString(4));
                bean.setPassword(rs.getString(5));
                bean.setReg_date(rs.getDate(6).toString()); // reg데이터가 String타입으로 변한다.
                bean.setRef(rs.getInt(7));
                bean.setRe_step(rs.getInt(8));
                bean.setRe_level(rs.getInt(9));
                bean.setReadcount(rs.getInt(10));
                bean.setContent(rs.getString(11));
 
            }
 
            con.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
 
        return bean;
    }
 
    // 답변글이 저장되는 메소드
    public void reWriteBoard(BoardBean bean) {// re_step와 re_level을 먼저 수정해야 한다.
                                                // 답변글은 부모글의 step와 level보다 1씩 증가하기 때문이다.
                                                // 부모글그룹과 글레벨 글스텝을 읽어들인다.
        int ref = bean.getRef();
        int re_step = bean.getRe_step();
        int re_level = bean.getRe_level();
 
        getCon();
 
        try {
            ///////////////////// 핵심코드///////////////////////////
            // 부모글보다 큰 re_level의 값을 전부 1씩 증가시켜줌(같은 레벨에 있는 것들만)
            String levelsql = "update board set re_level=re_level+1 where ref=? and re_level > ?";
            // 코드해석 = board 테이블에 있는 re_level을 1씩 증가시켜라 (단, ref가 같고 re_level보다 작은것만)
            pstmt = con.prepareStatement(levelsql);
            // 쿼리 실행 객체 선언
            pstmt.setInt(1, ref);
            pstmt.setInt(2, re_level);
            // 쿼리 실행
            pstmt.executeUpdate();
            // 답변글 데이터를 저장
            String sql = "insert into board values(board_seq.NEXTVAL,?,?,?,?,sysdate,?,?,?,0,?)";
            // 첫번째 값은 ?가 아니라 시퀀스를 사용해
            // 시퀀스에 이미 들어가있는값의
            // 다음값을 자동으로 매핑해서
            // 넣어준다.
 
            pstmt = con.prepareStatement(sql);
            // ?에 값을 매핑한다
            pstmt.setString(1, bean.getWriter());
            pstmt.setString(2, bean.getEmail());
            pstmt.setString(3, bean.getSubject());
            pstmt.setString(4, bean.getPassword());
            pstmt.setInt(5, ref); // 부모의 ref값을 넣어줌
            pstmt.setInt(6, re_step + 1); // 답글이기 때문에 부모글 re_step에 1을 더해준다.
            pstmt.setInt(7, re_level + 1); // 답글이기 때문에 부모글 re_level에 1을 더해준다.
            pstmt.setString(8, bean.getContent());
            pstmt.executeUpdate(); //
            con.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
 
    }
 
    // boardupdate용 Delete시 하나의 게시글을 리턴
 
    public BoardBean getOneUpdateBoard(int num) {
        // 리턴타입 선언(객체 생성)
        BoardBean bean = new BoardBean();
        getCon();
        try {
 
            // 쿼리 준비
            String sql = "select * from board where num=?";
            // 쿼리 실행 객체
            pstmt = con.prepareStatement(sql);
            pstmt.setInt(1, num);
            // 쿼리 실행후 결과를 리턴
            rs = pstmt.executeQuery();
 
            if (rs.next()) { // 게시글에대한 모든 정보를 하나씩 가져옴
                bean.setNum(rs.getInt(1));
                bean.setWriter(rs.getString(2));
                bean.setEmail(rs.getString(3));
                bean.setSubject(rs.getString(4));
                bean.setPassword(rs.getString(5));
                bean.setReg_date(rs.getDate(6).toString()); // reg데이터가 String타입으로 변한다.
                bean.setRef(rs.getInt(7));
                bean.setRe_step(rs.getInt(8));
                bean.setRe_level(rs.getInt(9));
                bean.setReadcount(rs.getInt(10));
                bean.setContent(rs.getString(11));
 
            }
 
            con.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
 
        return bean;
    }
 
    // update 와 delete 시 필요한 패스워드값을 리턴해주는 메소드
    public String getPass(int num) {// 리턴할 변수 객체 선언
        String pass = "";
        // DB연결
        getCon();
 
        try {
 
            // 쿼리 준비
            String sql = "select password from board where num=?";
            // 쿼리 실행할 객체 선언
            pstmt = con.prepareStatement(sql);
            pstmt.setInt(1, num);
            rs = pstmt.executeQuery();
            // 패스워드 값을 저장
            if (rs.next()) {
                pass = rs.getString(1);
            }
            // 자원 반납
            con.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
 
        return pass;
 
    }
 
    // 하나의 게시글을 수정하는 메소드
    public void updateBoard(BoardBean bean) {
        getCon();
 
        try {
            // 쿼리 준비
            String sql = "update board set subject=? , content=? where num=?";
            pstmt = con.prepareStatement(sql);
 
            // ?값을 대입
            pstmt.setString(1, bean.getSubject());
            pstmt.setString(2, bean.getContent());
            pstmt.setInt(3, bean.getNum());
 
            pstmt.executeUpdate();
 
            con.close();// 자원반납
 
        } catch (Exception e) {
            e.printStackTrace();
        }
 
    }
 
    // 하나의 게시글을 삭제 하는 메소드
    public void deleteBoard(int num) {
        getCon();
        try {
            // 쿼리 준비
            String sql = "delete from board where num=?";
            pstmt = con.prepareStatement(sql);
 
            // 쿼리 실행을 위한 인덱스와 값을 넣어주기
            pstmt.setInt(1, num);
 
            // 쿼리 실행
            pstmt.executeUpdate();
 
            // 자원 반납
            con.close();
 
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
 
    // 전체 글의 갯수를 리턴하는 메소드
    public int getAllCount() {
        getCon();
        // 게시글 전체수를 저장하는 변수
        int count = 0;
 
        try {
            // 쿼리 준비
            String sql = "select count(*) from board";
            // 쿼리를 실행할 객체 선언
            pstmt = con.prepareStatement(sql);
 
            // 쿼리 실행후 결과를 리턴
            rs = pstmt.executeQuery();
 
            if (rs.next()) {
                count = rs.getInt(1); // 전체 게시글의 수
            }
 
            con.close();
 
        } catch (Exception e) {
            e.printStackTrace();
        }
 
        return count;
 
    }
 
}
 
cs

 

 

728x90
반응형
: