이미지 파일 업로드 폴더 => C:\board\article_image\temp
게시판 글쓰기 구현
글 추가는 한 개의 글을 추가하므로 /addArticle.do이고,
글 목록에 출력하는 경우는 여러 개의 글을 조회하므로
/listArticles.do이며 s를 붙여 표현.
게시판의 글쓰기 기능을 구현하는 과정
1. 글 목록창(listArticles.jsp)에서 글쓰기 창을 요청
"${contextPath}/board/articleForm.do"
2. 글쓰기 창에서 글을 입력하고
컨트롤러에 /board/listArticles.do 로 글쓰기를 요청
3. 컨트롤러에서 Service클래스로 글쓰기 창에서 입력한 글 정보를 전달해 테이블에 글을 추가
4. 새 글을 추가하고 컨트롤러에서
다시 board/listArticles.do 로 요청하여 전체 글을 표시
BoardControleer 클래스 : 컨트롤러 담당
*request.getPathInfo() : action값 추출
1. action 값이 / articleForm.do면 글쓰기 창을 브라우저에 표시
2. action값이 /addArticle.do면 다음 과정으로 새 글을 추가
* 사용자 정의 메서드 upload() 선언 .
3. upload() 메서드를 호출해 글쓰기 창에서 전송된 글 관련 정보를 Map에 key/value 쌍으로 저장.
* 저장소 : C:\board\article_image
4. 파일을 첨부한 경우 먼저 파일 이름을 Map에 저장한 후, 첨부한 파일을 저장소에 업로드
Map<String, String> articleMap에 정보를 저장하는 이유는 upload(request, response) 메서드에서
파일 업로드와 함께 전송된 기타 데이터들을 편리하게 처리하기 위함입니다.
웹 어플리케이션에서 클라이언트로부터 데이터를 받을 때는 여러 가지 데이터를 동시에 전송해야 하는 경우가
많습니다. 예를 들어, 글의 제목, 내용과 함께 이미지 파일을 업로드하는 경우가 그렇습니다.
이러한 다양한 데이터를 효율적으로 처리하기 위해서는 데이터를 구분하고 관리하는 방법이 필요합니다.
Map은 키-값 쌍으로 데이터를 저장하는 자료구조입니다. 이를 이용하여 articleMap에 각 데이터를 키-값
형태로 저장하면, 각 데이터를 쉽게 참조하고 관리할 수 있습니다.
주어진 코드에서는 articleMap에 "title", "content", "imageFileName" 등의 키를 사용하여 데이터를
저장한 것으로 보입니다.
예를 들어, 클라이언트에서 전송된 데이터가 다음과 같다고 가정해봅시다:
title: "제목입니다."
content: "내용입니다."
imageFileName: "example.jpg"
upload(request, response) 메서드에서는 이러한 데이터를 받아와 articleMap에 다음과 같이 저장할 수
있습니다:
arduino
Copy code
articleMap.put("title", "제목입니다.");
articleMap.put("content", "내용입니다.");
articleMap.put("imageFileName", "example.jpg");
그리고 articleMap.get("title"), articleMap.get("content"), articleMap.get("imageFileName")과
같이 각 키를 사용하여 데이터를 추출할 수 있습니다. 이를 통해 코드의 가독성과 유지 보수성이 향상되며,
데이터를 각각 개별 변수로 관리하는 것보다 더 효율적인 코드를 작성할 수 있습니다.
따라서, Map<String, String> articleMap에 정보를 저장하는 것은 다양한 데이터를 편리하게 관리하고
사용하기 위한 방법으로 선택된 것으로 볼 수 있습니다.
5. upload() 메서드를 호출한 후에는
반환한 Map에서 세 글 정보를 추출
6. 그런다음 Service클래스의 addAricle(0 메서드 인자로 새 글 정보를 전달하면 새 글이 등록
upload() 메서드 내에서 업로드를 담당하는 세가지 클래스
DiskFileItemFactory :
임시 파일이 저장될 디렉터리와 메모리에 보관할 최대크기 설정
setSizeThrehold(int sizeThreshlod) : 메모리에 저장할 수 있는 최대 크기 , byte단위로 값을 써야 함.
setRepository(File repository) : 메모리에 저장할 수 있는 최대 크기를 넘길 경우, 파일을 생성할 디렉터리 지정,
미지정시, 기본 임시 디렉터리를 사용 (위치를 지정해줘야 함)
다른 피시에서 이미지를 업로드하겠다 하면 바로 들어가는 게 아니라 임시 저장소에 저장되는 것임
메모리상에 있는 것을 다시 한 번 실제 파일에 넣어줘야 함
주의 : 업로드한 파일을 임시 파일이나 메모리에 저장된다는 점!!
업로드 파일 크기가 지정한 크기를 넘기 전까지는 업로드한 파일 데이터를 메모리에 저장하고,
지정한 크기를 넘길 경우, 임시 디렉터리에 파일로 저장!!
ServletFileUpload : 하나 혹은 여러 개 올릴 수 있으니 필요 예) 3개 업로드 시 얼마나 허용할 것인지
한 번에 업로드할 수 있는 전체 파일의 크기 및 각 파일별로 업로드할 수 있는 파일의 크기 설정
- setSizeMax (int sizeMax) : 전체 파일의 업로드 최대 크기
- setFileSizeMax (long fileSizeMax): 개별 파일별의 업로드 최대 크기
- 반드시 DiskFileItemFactory 객체를 받아야 한다고?
- 설정 안 해놓으면 서버 쪽 저장소가 꽉 차게 됨. 따라서 제한해 놓는 거임.
FileItem :
- isFormFiled() : 파일이 아닌 일반적인 입력 파라미터일 경우 true 리턴
- getFiledName() : 파라미터의 이름을 구한다.
- getString("UTF-8") : 기본 캐릭터 셋을 사용하여 파라미터의 값을 구한다.
- getName() : 업로드한 파일의 (경로를 제외한) 이름을 구한다. (객체명이 item) 실제 파일명만 꺼낼 때 사용
- getContentType() : text/plain, image/jpeg MIME 브라우저에서 열릴형식
- isInMemory() : 업로드 한 파일이 메모리에 저장된 경우, true / 임시 디렉터리에 저장된 경우 false를 리턴
- item.getSize() : 업로드한 파일의 byte를 구한다.
주의 : 파일의 크기가 0, 즉 업로드한 파일이 없는 파라미터에 대해서도 FileItem객체는 생성된다.
따라서 업로드한 파일을 처리할 때는 getSize()가 0 인경우, 예외처리 필수
> 파일을 업로드하지 않아도 fileItem객체는 생성된다. 그래서 ~~~?
<td align="right">이미지파일 첨부: </td>
<td> <input type="file" name="imageFileName" onchange="readURL(this);" /></td>
<td><img id="preview" src="#" width=200 height=200/></td>
this : 자기 자신을 그대로 넘김 input 저 한 줄이 그대로 함수의 매개변수로 들어감
files : 선택한 파일이 있는지 없는지 (현재 상태 "선택한 파일이 없음" ==> 파일 제목) : onchange : readURL로 가기
인덱스 번호 0번이 존재하는지 아닌지
/*사용자가 선택한 이미지 미리보기 기능 */
function readURL(input) { /*파일 선택 여부 확인 */
// input.files: 사용자가 여러개 파일을 동시에 선택하면,
// ["파일","파일","파일"]와 같이 반환된다. 그래서 filessss
// 단, <input type="file" /> 에 다중 선택할 수 있도록 설정해야 가능 !!
// <input type="file" /> 은 특정 파일 종류만 선택가능하게 설정도 가능!! ex) txt/ png / img
if (input.files && input.files[0]) {
var reader = new FileReader(); /*javascript (JQuery) java,util 아님*/
reader.onload = function (e) { /*지정파일을 읽고 준비가 끝나면 onload*/
// e : 매개변수명 변경 가능 => 이벤트에 관련된 모든 내용이 전달...누가? 어떤? 전부 전송 매개변수로
// <img id="preview" src="#" width=200 height=200/>
$('#preview').attr('src', e.target.result); // src라는 속성명에다가 fileReader가 갖고 있는 결과값을 넣어준다. # : 결과값이 들어감 파일 정보
// e.target : 이벤트를 발생시킨 주체 (대상)
// e.target.result : 이벤트를 발생시킨 주체(대상)가 보유한 값
}
reader.readAsDataURL(input.files[0]);
}
}
onload() 이벤트 로드가 다 끝나면!!?
준비가 완료가 되면 이벤트 발생
e.target : reader
result : 사용자가 선택한 파일
"backToList(this.form)" // 나를 포함하고 있는 폼의 정보를 보냄
폼 태그 안에 서밋 버튼을 여러 개 만들 수 없기 때문에 어쩌고?
<input type=button value="목록보기"onClick="backToList(this.form)" />
miiltiple / 확장자 세팅도 가능 img/txt/png... 등등
- 우리의 노트북이 하나의 서버
-
3개의 파라미터가 action="${contextPath}/board/addArticle.do로 날아감
if (input.files && input.files [0]) 여러 개 거나 1번째가 있으면?
boardDAO
1. 기본 글 번호 중 가장 큰 번호를 조회. +1을 해줘야 새 글의 no가 되므로,,,
2. 가장 큰 번호에 1을 더한 번호를 반환
3. 새 글을 추가하기 전에 새 글에 대한 글 번호를 가져온다.
4. insert 문을 이용해 글 정보를 추가
listArticles.jsp
: 글쓰기를 클릭하면 글쓰기 창인 articleForm.jsp가 나타나도록.
<a class="cls1" href="${contextPath}/board/articleForm.do">
<p class="cls2">글쓰기</p>
</a>
articleForm.jsp
: 첨부 파일도 같이 업로드할 수 있도록
반드시 <form> 태그의 enctype속성을 multipart/form-data로 설정
1. 제이쿼리 이용해 이미지 파일 첨부 시 미리 보기 기능을 구현
2. action 값을 /addArticle.do로 해서 '새 글 등록'을 요청
3. 파일 업로드 기능을 위한 것
4. 첨부한 이미지를 미리 보기로 표시
글쓰기 기능에는 한 가지 문제
바로 새 글에 첨부한 파일들이 같은 폴더에 저장된다는 것
이렇게 저장하면 다른 사용자가 첨부한 파일과 이름이 같아 구별하기가 어렵다.
업로드한 파일이 각각의 글번호를 이름으로 하는 폴더를 생성하고,
저장까지 할 수 있도록 구현
1. 글쓰기 창에서 새 글 전송 시,
컨트롤러의 upload() 메서드를 호출해 새 글 정보를 Map으로 반환받고
첨부한 파일은 임시로 temp폴더에 업로드 // upload()가 해주는 부분
2. 컨트롤러는 Service클래스의 addNewArticle() 메서드를 호출하면서
새 글 정보를 인자로 전달해 테이블에 추가한 후 새 글 번호를 반환받는다.
------------------------------------------------------------------------------------------------
3. 컨트롤러에서 반환받은 새 글 번호를 이용해
파일 저장소에 새 글 번호로 폴더를 생성하고
temp폴더의 파일을 새 글 번호 폴더로 이동
*로컬 PC파일 저장소 (C:\board\article_image)에 temp 폴더 생성
public class BoardController extends HttpServlet {
private static final long serialVersionUID = 1L;
private static String ARTICLE_IMAGE_REPO = "C:\\board\\article_image";
BoardService boardService;
ArticleVO articleVO;
}
// File uploadFile = new File(currentDirPath + "\\" + fileName); => 기존
// 1. new File(currentDirPath + "\\temp\\" + fileName); 해도 됨
// 2. repo주소에 temp까지 써줘도 되고
File uploadFile = new File(currentDirPath + "\\temp\\" + fileName);
글 상세 기능 구현
글 목록에서 글 제목을 클릭했을 때 글의 상세 내용을 보여주는 기능을 구현
글 상세 기능을 구현하는 과정
1. 글 목록창에서 글 제목을 클릭해
컨트롤러에 /board/viewArticle.do?articleNO=글번호로 요청
2. 컨트롤러는 전송된 글 번호로 글 정보를 조회하여 (service -> DAO)
글 상세 창(viewArticle.jsp)으로 포워딩
3. 글 상세창(viewArticle.jsp)에 글 정보와 이미지 파일이 표시.
FileDownloadController클래스 (분리)
viewArticle.jsp(상세보기)에서 전송한 글 번호와 이미지 파일 이름으로
파일 경로를 만든 후 해당 파일을 내려받는다.
1. 이미지 파일 이름과 글 번호(해당이미지가 글 번호 폴더에 들어가있기 때문)를 가져온다.
2. 글번호에 대한 파일 경로를 설정
3. 이미지 파일을 내려받는데 필요한 response에 헤더 정보를 설정
4. 버퍼를 이용해 한번에 8KB씩 전송
BoardController 클래스
1. /viewArticle.do로 요청하여 글 번호를 받아온다.
2. 그리고 그 번호에 해당하는 글 정보를 가져와 article속성으로 바인딩 한 후,
viewArticle.jsp로 포워딩
viewArticle.jsp
1. 컨트롤러에서 바인딩한 글 정보 속성을 이용해 표시.
2. 이미지 파일이 존재하는 경우는 글 번호와 이미지 파일 이름을 FileDownloadController로 전송한 후,
<img>태그에 다운로드 하여 표시
1. 글 제목을 표시.
2. 글 내용을 표시.
3. imageFileName 값이 있으면 이미지를 표시
4. <hidden>태그에 원래 이미지 파일이름을 저장
5. FileDownloadController 서블릿에 이미지 파일 이름과 글 번호를 전송해 이미지를 <img>태그에 표시
근데 왜 게시글의 사진을 다운 받지 ? 뭐하는 거지?
db저장용도인가? 우리 컴퓨터가 하나의 서버라고 생각하면 됨.
글 수정 기능 구현 sec03.brd05 / board05
기본에 작성한 글을 수정하는 기능을 구현
글 수정 기능을 구현하는 과정
1. 글 상세 창에서 수정 하기를 클릭해
글 정보를 표시하는 입력창들을 활성화
(fn_enable(this.form)이 칸들을 모두 활성화하는 역할을 함. )
2. 글 정보와 이미지를 수정한 후 수정 반영하기를 클릭해
컨트롤러에 /board/modArticle.do로 요청,
3. 컨트롤러는 요청에 대해
upload()메서드를 이용하여 수정된 데이터를 Map에 저장하고 반환,
4, 컨트롤러는 수정된 데이터를 테이블에 반영한 후,
temp 폴더에 업로드된 수정 이미지를 글 번호 폴더로 이동.
5. 마지막으로 글 번호 폴더에 있던 원래 이미지 파일을 삭제
BoardController클래스
1. 컨트롤러에서 수정을 요청하면 upload()메서드를 이용해 수정 데이터를 Map으로 가져온다.
2. Map의 데이터를 다시 ArticleVo객체의 속성에 저장한 후,
SQL문으로 전달하여 수정 데이터를 반영.
3, 마지막으로 temp폴더에 업로드 된 수정 이미지를 다시 글 번호 폴더로 이동하고 글 번호 폴더의 원래 이미지를 삭제
1. 전송된 글 정보를 이용해 글을 수정
2. 수정된 이미지 파일을 폴더로 이동.
3 . 전송된 orifinalImageFileName을 이용해 기존의 파일의 삭제
4. 글을 수정후 location객체의 href속성을 이용해 글 상세 화면을 나타낸다.
BoardService 클래스
컨트롤러에서 modArticle()메서드를 호출하면
다시 BoardDAO의 updateArticle()메서드를 호출하면서 수정 데이터를 전달
BoardDAO클래스
1. 수정된 이미지 파일이 있을 때만 imageFileName을 SQL문에 추가
2. 이미지 파일을 수정하는 경우와 그렇지 않은 경우를 구분해서 설정
ViewArticle.jsp
1. 수정하기를 클릭해 fn_enable() 함수를 호출하여
비활성화된 텍스트 박스를 수정할 수 있도록 활성화
2. 또한 글 정보와 이미지를 수정한 후,
수정반영하기를 클릭하면 fn_modify_article()
함수를 호출하여 컨트롤러로 수정 데이터를 전송
1. 수정하기 클릭 시 텍스트 박스를 활성화
2 텍스트 박스의 id로 접근 해 disabled속성을 false로 설정
3. 수정 반영하기 클릭 시 컨트롤러에 수정 데이터를 전송
4. 글 수정 시 글 번호를 컨트롤러로 전송하기 위해
미리 hidden 태그를 이용해 글 번호 저장
5. 이미지 수정에 대비해 미리 원래 이미지 파일 이름을 <hidden> 태그에 저장
6. 수정된 이미지 파일 이름을 전송.
**글 삭제 기능 구현**
게시판의 글을 삭제하는 과정을 구현
글을 삭제할 때에는 테이블의 글뿐만 아니라, 그 글의 자식 글과 이미지 파일도 함께 삭제
글 삭제 과정
1. 글 상세창(viewArticle.jsp)에서 삭제하기를 클릭하면 /board/removeArticle.do로 요청
2. 컨트롤러에서는 글 상세창에서 전달받은 글 번호에 대한 글과 이에 관련된 자식 글들을 삭제
3. 삭제된 글에 대한 이미지 파일 저장 폴더도 삭제
**BoardController** 클래스
1. 브라우저에서 삭제를 요청하면
2. 글 번호를 메서드로 전달해
3. 글 번호에 대한 글과 그 자식 글을 삭제하기 전에
4. 먼저 삭제할 글 번호와 자식 글 번호를 목록으로 가져옴
5. 그리고 글을 삭제한 후 글 번호로 이루어진 이미지 저장 폴더까지 모두 삭제
1. articleNO 값에 대한 글을 삭제한 후 삭제된 부모 글과 자식 글의 articleNO 목록을 가져온다
2. 삭제된 글들의 이미지 저장 폴더들을 삭제
**BoardService** 클래스
1. 컨트롤러에서 removeArticle() 메서드 호출 시
2. 매개변수 articleNO로 글 번호를 전달받아
3. BoardDAO의 selectRemovedArticles()를 먼저 호출해
4. 글 번호에 대한 글과 그 자식 글의 글 번호를 articleNOList에 저장
1. 그런 다음 deleteArticle() 메서드를 호출해
2. 글 번호에 대한 글과 자식 글을 삭제하고 글 번호를 반환
1. 글을 삭제하기 전 글 번호들을 ArrayList 객체에 저장
2. 삭제한 글 번호 목록을 컨트롤러로 반환
**BoardDAO** 클래스
1. selectRemovedArticles() 메서드는 삭제할 글에 대한 글 번호를 가져옴
2. deleteArticle() 메서드는 전달된 articleNO에 대한 글을 삭제
1. 오라클의 계층형 SQL문을 이용해 삭제 글과 관련된 자식 글까지 모두 삭제함
2. 삭제한 글들의 articleNO을 조회함
오라클 계층형 SQL문을 이용해 부모 글에 대한 자식 글을 삭제하는 SQL 문
```sql
DELETE FROM t_board
WHERE artiucleNO in (
SELECT artiucleNO FROM t_board
START WITH artiucleNO = 2 // 글 번호가 2인 글과 자식 글을 삭제
CONNECT BY PRIOR artiucleNO = prarentNO
)
```
delete문에서는 start with 다음에 articleNO의 값이 2이므로
글 번호가 2인 글과 그 자식 글들을 모두 삭제하라는 의미
**viewArticle.jsp**
1. 삭제하기를 클릭하면
2. fn_remove_article() 자바스크립트 함수를 호출해
3. 글 번호인 artiucleNO를 컨트롤러로 전송하도록 구현
fn_remove_article(url, artiucleNO) 함수 :
1. 자바스크립트를 이용해 동적으로 <form>태그를 생성
2. 자바스크립트를 이용해 동적으로 <input> 태그를 생성한 후, name과 value를 artiucleNO와 글 번호로 설정
3. 동적으로 생성된 <input> 태그를 동적으로 생성한 <form> 태그에 append
4. <form> 태그에 <body> 태그에 추가(append)한 후 서버에 요청
5. 삭제하기 클릭 시, fn_remove_article() 자바스크립트 함수를 호출하면서 artiucleNO를 전달
**답글 쓰기 기능 구현**
**답글 쓰는 기능 구현 과정**
1. 글 상세창(viewArticle.jsp)에서 답글쓰기를 클릭하면 요청명을 /board/replyForm.do로 하여 부모 글 번호(parentNO)를 컨트롤러로 전송
2. 답글 쓰기창(replyForm.jsp)에서 답변 글을 작성한, 후 요청명을 /board/addReply.do로 하여 컨트롤러로 요청
3. 컨트롤러에서는 전송된 답글 정보를 게시판 테이블에 부모 글 번호와 함께 추가
답글도 새 글이므로 답글 기능도 새 글 쓰기 기능과 유사
다른 점은
1. 답글창 요청(/replyForm.do) 시,
2. 미리 부모 글 번호를 parentNO 속성으로 세션(session)에 저장해 놓고,
3. 답글을 작성한 후 등록(/addReply.do)을 요청하면
4. 세션에서 parentNO를 가져와 테이블에 추가함
**BoardController** 클래스
1. 답글에 대한 부모 글 번호를 저장하기 위해 세션을 사용
2. 답글창 요청 시 미리 부모 글 번호를 parentNO 속성으로 세션에 저장
3. 답글 전송 시 세션에 저장된 parentNO를 가져옴
4. 답글의 부모 글 번호를 설정
5. 답글의 작성자 ID를 lee로 설정
6. 답글을 테이블에 추가
7. 답글에 첨부한 이미지를 temp 폴더에서 답글 번호 폴더로 이동
**BoardService** 클래스
**BoardDAO** 클래스
inserNewArticle(ArticleVO article)
"INSERT INTO t_board (articleNO, parentNO, title, content, imageFileName, id) VALUES (?, ?, ?, ?, ?, ?)"
**viewArticle.jsp**
1. 글 상세창(viewArticle.jsp)에서 답글쓰기를 클릭하면
2. fn_reply_form() 함수를 호출하면서 글 번호와 요청명을 함께 전달
3. 그리고 다시 <form> 태그와 <input> 태그를 이용해 글 번호를 parentNO 속성으로 컨트롤러에 전달
1. 전달된 요청명을 <form> 태그의 action 속성 값에 설정
2. 함수 호출 시 전달된 articleNO 값을 <input> 태그를 이용해 컨트롤러에 전달
3. 답글쓰기를 클릭 시 fn_reply_form() 함수를 호출하면서 요청명과 글 번호를 전달
**replyForm.jsp**
답글 입력 후, 전송 시 컨트롤러에 /board/addReply.do로 요청
게시판 페이징 기능 구현
어떤 게시판이든 목록의 글이 많아지면 한 페이지에 모든 글이 표시되는 것이 아니라 다음과 같이 [1], [2], [3] .. 이렇게 페이지 별로 표시,
이렇게 하는 것이 보기에도 더 좋고 사용자가 이용하기에도 편리하기 때문
글 목록에 페이징 기능이 어떻게 구현 원리
1. 하단에 보이는 숫자는 페이지 번호
2. 한 페이지 마다 10개의 글이 표시되고
3. 이 페이지가 10개가 모여 한 개의 섹션
4. 첫 번째 섹션은 첫 번째 페이지 부터 열 번째 페이지 까지
5. 두 번째 섹션은 열 한 번째 페이지 부터 스무 번째 페이지까지
6, 따라서 사용자가 글 목록 페이지에서 [2]를 클릭하면
브라우저는 서버에 section값으로는 1ㅇ을,pageNum값으로는 2 를 전송하는 것,
7. 그리고 글 목록에는 두번 째 페이지에 해당하는 글인 11에서 20번 째 글을 테이블에서 조회한 후, 표시
페이징 기능을 추가한 글 목록 조회 SQL문
section과 pageNum으로 글 목록 조회하는 SQL문
1. 계층형 으로 조회된 레코드의 ROWNUM(recNum)이 표시되도록 조회.
2. 계층형 SQL문으로 글을 계층별로 조회
3. section과 pageNum값으로 조건식의 recNu 범위를 전한 후,
조회된 글 중 해당하는 값이 있는 경우 최종적으로 조호
4. section값이 1이고, pageNum값이 1인 경우
서브쿼리문의 실행순서
1. 기존 계층형 구조로 글 목록을 일단 조회
2. 그 결과에 대해
다시 ROWNUM(recNum)이 표시되도록 서브 쿼리문을 이용해 다시 한 번 조회
3. ROWNUM이 표시된 두번 째 결과에서
section과 pageNum으로 계산된 Where 절의 between 연산자 사이의 값에 해당하는 ROWNUM이 있는 레코드들만 최종적으로 조회
참고 : MySQL 의 경우
[1] [2] [3] x=1
SELECT * FROM t_board LIMIT 0, 10; 1페이지 x-1*10 => 0
SELECT * FROM t_board LIMIT 10, 10; 2페이지 x-1*10 => 10
SELECT * FROM t_board LIMIT 20, 10; 3페이지 x-1*10 => 20
SELECT *FROM (
SELECT ROWNUM as recNum, <=1
LVL, articleNO, parentNO, title, content, id, writedate
FROM (
SELECT LEVEL as LVL, <= 2
articleNO, parentNO, title, content, id, writedate
FROM t_board
START WITH parentNO=0
CONNECT BY PRIOR articleNO=parentNO
ORDER SIBILINGS BY articleNO DESC
)
)
SELECT *FROM (
SELECT
ROWNUM as recNum, <=1
LVL, articleNO, parentNO, title, content, id, writedate
FROM (
SELECT LEVEL as LVL, <= 2
articleNO, parentNO, title, content, id, writedate
FROM t_board
START WITH parentNO=0
CONNECT BY PRIOR articleNO=parentNO
ORDER SIBILINGS BY articleNO DESC
)
)
WHERE
recNum between(section-1)*100+ (pageNum -1)*10+1 (section-1)*100+pageNum*10; <==3
=>section=1 , pageNum=1: 1 1 1 1
=>section=1 , pageNum=3:
=>section=1 , pageNum=7:
=>section=2 , pageNum=1:
=>section=2 , pageNum=5:
=>section=2 , pageNum=9:
=> recNum between 1and 10; <== 4
<<< [1] [2] [3] [4] [5] [6] [7] [8] [9] [10] >>>
1 11 21 91
10
페이징 기능을 구현하기 위해 서브 쿼리문(inner query)과 오라클에서 제공하는 가상 컬럼인 ROWNUM을 이용.
ROWNUM은
Select 문으로 조회된 레코드 목록에 대해 오라클 자체에서 순서를 부여하여 레코드 번호를 순서대로 할당.
BoardController 클래스
1. /listArticle.do 로 최초 요청시
2. section 과 pageNum 의 기본 값을 1로 초기화
3. 컨트롤러에서는 전달된 section과 pageNum을 HashMap에 저장한 후,
4. DAO로 전달
1. 최초 요청시 또는 /listArtilcle.do로 요청 시 section값과 pageNum 값을 구함.
2. 최초 요청 시 section값과 pageNum값이 없으면 각각 1로 초기화
3. section값과 pageNum값을 HashMap에 저장한 후 메서드로 놈긴다.
4. section 값과 pageNum값으로 해당 섹션과 페이지에 해당되는 글 목록을 조회
5. 브라우저에서 전송 ㄷ된 section 과 pageNum값을 articlaMap에 저장.
7. 글목록에서 명시적으로 페이지 번호를 눌러서 요청한 경우,
section값과 pageNum값을 가져온다.
BoardService클래스
1. 페이징 기능에 필요한 글 목록과 전체 글 수를 각각 조회할 수 있도록 구형,
2. HashMap을 생성한 후, 조회한 두 정보를 각각 속성으로 저장.
JSP로 넘겨줘야 할 정보가 많을 경우에는
각 Request 에 바인딩 해서 넘겨도 되지만
HashMap 을 사용해 같은 종류의 정보를 묶어서 넘기면 편리
1. 전달된 pagingMap을 사용해 글 목록을 조회
2. 테이블에 존재하는 전체 글 수를 조회
3. 조회된 글 목록을 articlsMap으로 바인딩 하여 listArticlels.jsp로 넘긴다.
4. 전체 글 수를 articlesMap에 저장.
BoardDAO클래스
1. 전달받은 section과 pageNum 값을 가져온다.
2. section 과 pageNum값으로 레코드 번호의 범위를 조건으로 정한다.
(이들 값이 각각 1로 전송되었으면 between 1 and 10이 된다. )
3. 전체 글 수를 조회
listArticles,jsp
1. 전체 글 수 (totArticles)가 100개를 넘는 경우,
100개인 경우
100개를 넘지 않는 경우로 나누어 페이지 번호를 표시하도록 구션,
2. 전체 글 수가 100개가 넘지 않으면.
전체 글 수를 10으로 나눈 몫에 1을 더한 값이 페이지 번호로 표시
예를 들어 전체 글 수가13개이면
10으로 나우었을 때의 몫인 1에 1을 더해 2가 페이지 번호로 표시된다.
3. 만약 전체 글 수가 100개일 때는 정확히 10개의 페이지가 표시되며,
100개를넘을 떄는 다음 section으로 이동할 수 있도록 마지막 페이지 번호 옆에 next를 표시
1. HashMap으로 저장해서 넘어온 값들은 이름이 길어 사용하기 불편하므로
<c:set>태그를 이용해 각 값드을 짧은 변수 이름으로 저장
2. 선택된 페이지 전호를 빨간핵으로 표시
3. 전체글 수에 따라 페이징 표시를 다르게 구현
4. 전체 글 수가 100보다 클때
5. 섹션 값 2부터는 앞 섹션으로 이동할 수 있는pre를 표시
6. 페이지 번호 10 오른쪽에는 다음 섹션으로 이동할 수 있는 next를 표시
7. 전체 글 숙가 100개일 째는 첫번 때 섹션의 10개 페이지만 표시하면 된다 .
8. 전체 글 수가 100개보다 적을 때 페이징을 표시
9. 글 수가 100개가 되지 않으므로 표시되는 페이지는 10개가 되지 않고,
전체 글 수를 10으로 나누어 구한 몫에 1을 더한 페이지 까지 표시
10. 페이지 번호와 컨트롤러에서 넘어온
'🚀 부트캠프 - PLAYDATA > 📒 수업 내용 정리' 카테고리의 다른 글
[Spring] REST API (0) | 2023.08.28 |
---|---|
[Spring] RedirectAttributes / 로그인 기능 구현 (0) | 2023.08.28 |
[PLAYDATA / JavaWeb] Oracle, elclipse DB 연결방법 (0) | 2023.07.29 |
[day12 / Java Web] 폴더, ServletRequest , ServletResponse (0) | 2023.07.12 |
[day 12 / Java Web] Servlet, HTTP, Request & Response (0) | 2023.07.12 |