글을 삭제할 때는 테이블의 글 뿐만 아니라 그 글의 자식 글과 이미지 파일도 함게 삭제 해야 합니다.
순서는
글 상세창(vieArticle.jsp)에서 삭제하기를 클릭하면 /board/removeArticle.do로 요청합니다.
컨트롤러에서는 글 상세창에서 전달받은 글 번호에 대한 글과 이에 관련된 지식 글들을 삭제합니다.
삭제된 글에 대한 이미지 파일 저장 폴더도 삭제합니다.
BoardController 클래스를 다음과 같이 작성합니다. 브라우저에서 삭젤르 요청하면 글 번호를 메서드로 전달해 글 번호에 대한 글과 그 자식 글을 삭제하기 전에 먼저 삭제할 글 번호와 자식 글 번호를 목록으로 가져옵니다. 그리고 글을 삭제한 후 글 번호로 이루어진 이미지 저장 폴더까지 모두 삭제합니다.
BoardService 클래스를 다음과 같이 작성합니다. 컨트롤러에서 removeArticle() 메서드 호출 시 매개변수 articleNO로 글 번호를 전달받아 BoardDAO의 selectRemovedArticles()를 먼저 호출해 글 번호에 대한 글과 그 자식 글의 번호를 articleNOList에 저장합니다. 그런 다음 deleteArticle() 메서드를 호출해 글 번호에 대한 글과 자식 글을 삭제하고 글 번호를 반환합니다.
BoardDAO클래스를 다음과 같이 작성합니다. selectRemovedArticles() 메서드는 삭제할 글에 대한 글 번호를 가져옵니다. deleteArticle() 메서드는 전달된 articleNO에 대한 글을 삭제합니다.
viewArticle.jsp에서 삭제하기를 클릭하면 fn_remove_article() 자바스크립트 함수를 호출해 글 번호인 articleNO를 컨트롤러로 전송하도록 구현합니다.
글 상세창(viewArticle.jsp)에서 수정하기를 클릭해 글 정보를 표시하는 입력창들을 활성화합니다.
글 정보와 이미지를 수정한 후 수정반영하기를 클릭해 컨트롤러에 /board/modArticle.do로 요청합니다.
컨트롤러는 요청에 대해 upload() 메서드를 이용하여 수정된 데이터를 Map에 저장하고 반환합니다.
컨트롤러는 수정된 데이터를 테이블에 반영한 후 temp폴더에 업로드된 수정 이미지를 글 번호 폴더로 이동합니다.
마지막으로 글 번호 폴더에 있던 원래 이미지 파일을 삭제합니다.
지금까지 해왔던 파일들을 복사하여 brd05패키지와 board04폴더에 넣어서 코드를 추가하도록 하겠습니다.
BoardController 클래스를 다음과 같이 작성하겠습니다. 컨트롤러에서 수정을 요청하면 upload() 메서드를 이용해 수정 데이터를 Map으로 가져옵니다. Map의 데이터를 다시 ArticleVO 객체의 속성에 저장한 후 SQL문으로 전달하여 수정 데이터를 반영합니다. 마지막으로 temp폴더에 업로드된 수정 이미지를 다시 글 번호 폴더로 이동하고 글 번호 폴더의 원래 이미지를 삭제 합니다.
BoardController 클래스에 추가하였습니다.
BoardService 클래스를 다음과 같이 작성합니다. 컨트롤러에서 modArticle() 메서드를 호출하면 다시 BoardDAO의 updateArticle() 메서드를 호출하면서 수정 데이터를 전달합니다.
BoardService클래스 추가
BoardDAO 클래스를 다음과 같이 작성합니다. 전달된 수정 데이터에 대해 이미지 파일을 수정하는 경우와 이미지 파일을 수정하지 않는 경우를 구분해 동적으로 SQL문을 생성하여 수정 데이터를 반영합니다.
글 목록창에서 글 제목을 클릭해 컨트롤러에 /board/viewArticle.do?articleNO=글번호로 요청합니다.
컨트롤러는 전송된 글 번호로 글 정보를 조회하여 글 상세창(viewArticle.jsp)으로 포워딩합니다.
글 상세창(viewArticle.jsp)에 글 정보와 이미지 파일이 표시됩니다.
이번에 사용할 클래스와 jsp파일은 위와 같습니다.
FileDownloadController 클래스는 다음과 같이 작성하겠습니다. viewArticle.jsp에서 전송한 글번호와 이미지 파일 이름으로 파일 경로를 만든 후 해당 파일을 내려 받습니다.
BoardController 클래스를 다음과 같이 작성합니다. /viewArticle.do로 요청하여 글 번호를 받아옵니다. 그리고 그 번호에 해당하는 글 정보를 가져와 article 속성으로 바인딩한 후 viewArticle.jsp로 전송합니다.
컨트롤러에서 전달받은 글 번호로 다시 selectArticle() 메서드를 호출합니다.
전달받은 글 번호를 이용해 글 정보를 조회합니다.
viewArticle.jsp를 다음과 같이 작성합니다. 컨트롤러에서 바인딩한 글 정보 속성을 이용해 표시합니다. 이미지 파일이 존재하는 경우는 글 번호와 이미지 파일 이름을 FileDownloadController로 전송한 후 <img> 태그에 다운로드 하여 표시합니다.
action 값이/articleForm.do면 글쓰기창을 브라우저에 표시하고, action 값이 /addArticle.do면 다음 과정으로 새 글을 추가합니다. upload() 메서드를 호출해 글쓰기창에서 전송된 글관련 정보를 Map에 key/value 쌍으로 저장합니다.
파일을 첨부한 경우 먼저 파일 이름을 Map에 저자한 후 첨부한 파일을 저장소에 업로드합니다. upload() 메서드를 호출한 후에는 반환한 Map에서 새 글 정보를 가져옵니다. 그런 다음 Service 클래스의 addAtricle() 메서드 인자로 새 글 정보를 전달하면 새 글이 등록됩니다.
BoardDAO클래스의 insertNewArticle() 메서드를 호출하면서 글 정보를 인자로 전달합니다.
insertNewArticle() 메서드의 SQL문을 실행하기 전에 getNewArticleNo() 메서드를 호출해 새 글에 대한 글 번호를 먼저 가져옵니다.
다음은 글쓰기와 관련된 JSP 페이지를 작성할 차례입니다. listArticles.jsp를 다음과 같이 작성합니다.
articleForm.jsp를 다음과 같이 작성합니다. 쇼핑몰 게시판에 글을 쓸 때는 보통 사진을 첨부하는 경우가 많습니다. 이처럼 글쓰기 작업을 할 때 첨부 파일도 같이 업로드할 수 있도록 반드시 <form>태그의 enctype속성을 multipart/form-data로 설정합니다.
/board/listArticle.do로 글 목록창을 요청한 후 다시 글쓰기를 클릭해 board/articleForm.do로 글쓰기 창을 요청합니다. 그리고 글쓰기 창에서 "상품후기입니다."라는 새 글을 작성하고 글쓰기를 클릭해/board/addArticle.do로 요청합니다.
글쓰기를 누르면 다음과 같은 창이 뜨고 파일을 선택할 수도 있습니다.
파일을 첨부해서 글을 쓰면 우리가 처음에 만들어 주었던
C:\board\article_image 에 파일이 업로드 됩니다.
하지만 이 글쓰기 기능에는 한 가지 문제가 있습니다.
바로 새 글에 첨부한 파일들이 같은 폴더에 저장된다는 것이빈다. 얼핏 보기엔 큰 무넺가 아닌것 같지만 이렇게 저장하면 다른 사용자가 첨부한 파일과 이름이 같아 구별하기가 어렵습니다.
따라서 이번에는 업로드한 파일이 각각의 글 번호를 이름으로 하는 폴더를 생성하고, 저장까지 할 수 있도록 구현해 보겠습니다.
과정은 다음과 같습니다.
글쓰기창에서 새 글 전송시 컨트롤러의 upload()메서드를 호출해 새 글 정보를 Map으로 반환받고 첨부한 파일은 임시로 temp 폴더에 업로드한다
컨트롤러는 Service 클래스의 addNewArticle() 메서드를 호출하면서 새 글 정보를 인자로 전달해 테이블에 추가한 후 새 글 번호를 반환받습니다.
컨트롤러에서 반환 받은 새 글 번호를 이용해 파일 저장소에 새 글 번호로 폴더를 생성하고 temp폴더의 파일을 새 글 번호 폴더로 이동합니다.
BoardController 클래스를 다음과 같이 작성합니다. upload() 메서드를 호출해 첨부한 파일을 temp 폴더에 업로드한 후 새 글정보를 Map으로 가져옵니다. 그리고 새 글을 테이블에 추가한 후 반환 받은 새 글 번호로 폴더를 생성하고 temp폴더의 이미지를 새 글 번호 폴더로 이동합니다.
BoardService 클래스를 다음과 같이 작성합니다. addArticle() 메서드의 반환 타입을 int로 변경합니다. 그리고 BoardDAO의 insertNewArticle() 메서드를 호출해 새 글 번호를 받아서 반환합니다.
BoardDAO 클래스에서는 insertNewArticle() 메서드를 호출해 SQL문을 실행한 후 새 글 번호를 반환합니다.
BoardController 클래스는 /board/listArticles.do로 요청 시 화면에 글 목록을 출력하는 역할을 합니다. getPathInfo() 메서드를 이용해 action 값을 가져오고 action값이 null이거나 /listArticles.do일 경우 BoardService 클래스의 lsitArticles() 메서드를 호출해 전체 글을 조회합니다. 그리고 조회한 글을 articlesList속성으로 바인딩하고 글 목록창으로 포워딩합니다.
BoardServce 클래스를 다음과 같이 작성합니다. BoardDAO 객체를 생성한 후 select AllArticle() 메서드를 호출해 전체 글을 가져옵니다.
BoardDAO 클래스를 작성하겠습니다
BoardService 클래스에서 BoardDAO의 selectAllArticles() 메서드를 호출하면 계층형 SQL문을 이용해 계층형 구조로 전체 글을 조회한 후 반환합니다.
ArticleVO 클래스를 다음과 같이 작성합니다. 조회한 글을 저장하는 ArticleVO 클래스에 글의 깊이를 저장하는 LEVEL 속성을 추가합니다.
VO의 자세한 사항은 깃허브 참조 요망.
이제 JSP에 글 목록을 표시해보겠습니다. listArticles.jsp를 다음과 같이 작성합니다.
첫 번째<forEeach> 태그를 이용해 articlesList 속성으로 포워딩된 글 목록을 차례로 전달받아 표시합니다. <forEach> 태그 반복 시 각 글의 level 값이 1보다 크면 답글이므로 다시 내부 <forEach>태그를 이용해 1부터 level 값까지 반복하면서 공백을 만들고(들여쓰기) 답글을 표시합니다. 이 때 level값이 1보다 크지 않으면 부모 글이므로 공백 없이 표시합니다.
이번에는 컨트롤러에서 회원 정보 조회뿐만 아니라 회원 정보 등록까지 구현해 보겠습니다. 앞에서 보다 브라우저로부터 전달되는 요청 사항이 많아졌기 때문에 우선은 컨트롤러가 브라우저로부터 어떤 요청을 받았는지 알아내야 합니다. 그런 다음 그 요청에 대해 해당하는 모델을 선택하여 작업을 요청해야 하는데, 이 역할을 하는 방법을 커맨트 패턴이라고 합니다.
커맨트 패턴이란 한마디로 브라우저가 URL패턴을 이용해 컨트롤러에게 수행 작업을 요청하는 방법입니다. 컨트롤러는 getPathInfo() 메서드를 이용해 URL 패턴에서 요청명을 받아와 작업을 수행합니다.
memberForm.jsp
MemberController
MemberDao
DB
회원 가입창에서 회원 정보를 입력하고 URL 패턴을 /member/addMember.do로 서버에 요청합니다.
MemberController에서 getPathInfo()메서드를 이용해 요청명인 /addMember.do를 받아옵니다.
요청명에 대해 MemberDAO의 addMember()메서드를 호출합니다.
addMember() 메서드에서 SQL문으로 테이블에 회원 정보를 추가합니다.
컨트롤러 역할을 하는 MemberController 클래스를 다음과 같이 작성합니다. 이 컨트롤러에서는 getPathInfo() 메서드를 이용해 두 단계로 이루어진 요청을 가져옵니다. action값에 따라 if문을 분기해서 요청한 작업을 수행하는데 action 값이 null이거나 /listMembers.do인 경우에 회원 조회 기능을 수행합니다. 만약 action값이 /memberForm.do면 회원 가입창을 나타내고 action 값이 /addMember.do면 전송된 회원 정보들을 테이블에 추가합니다.