BoardDetailAction
- BoardListForm.jsp입니다.
- 게시글 목록 구현하는 부분에 게시글 제목 부분에 <a> 태그를 삽입하여,
클릭 시 'BoardDetailAction.bo?num=${board.boardNum}&page=${page}'로 이동할 수 있게 했습니다.
- 여기서 'num'과 'page'의 value값인 '${board.boardNum}'과 '${page}'는
'BoardDetailAction에서 파라미터 값으로 전달됩니다.
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
|
package jsp.board.action;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import jsp.board.model.BoardBean;
import jsp.board.model.BoardDAO;
import jsp.common.action.Action;
import jsp.common.action.ActionForward;
public class BoardDetailAction implements Action{
@Override
public ActionForward execute(HttpServletRequest request, HttpServletResponse response) throws Exception {
ActionForward forward = new ActionForward();
//전달받은 num 파라미터 가져오기
int num = Integer.parseInt(request.getParameter("num"));
//전달받은 page 파라미터 가져오기
String page = request.getParameter("page");
BoardDAO bDAO = BoardDAO.getInstance();
//getDetail 메서드 실행
BoardBean board = bDAO.getDetail(num);
//조회수 증가를 위해 viewCount 메서드 실행
boolean result = bDAO.viewCount(num);
//request 객체에 BoardBean객체와 page 값 담기
request.setAttribute("board", board);
request.setAttribute("page", page);
if(result) {
forward.setRedirect(false);
forward.setPath("BoardDetailForm.bo");
}
return forward;
}
}
|
cs |
- BoardDetailAction.java입니다.
- 전달받은 파라미터 값을 이용해 클릭한 글의 정보를 조회하는 Action 클래스입니다.
- 'num'과 'page' 파라미터 값을 변수에 저장합니다. (17~20번째 줄)
- BoardDAO 객체를 생성하고, 파라미터로 전달받은 'num'값을 이용해
getDetail() 메서드를 실행해 BoardBean 객체에 저장합니다. (24번째 줄)
- 파라미터로 전달받은 'num'값을 이용해 viewCount() 메서드를 실행해
결과값으로 boolean 타입을 반환합니다. (26번째 줄)
- request 객체에 BoardBean 객체와 page 값을 담습니다. (29~30번째 줄)
- viewCount() 실행 결과 반환 값이 'true'라면 'BoardDetailForm.bo'로 데이터를 'forward'합니다. (32~35번째 줄)
- BoardDAO의 getDetail() 메서드입니다.
- 전달받은 'num' 값을 이용해 게시글의 내용을 조회합니다.
- 조회한 내용의 값을 BoardBean 객체에 저장하고 반환합니다.
- BoardDAO의 viewCount() 메서드입니다.
- 전달받은 'num'값을 이용해 조회수를 증가하고, 조회수를 증가시켰다면 'true' 값을 반환합니다.
BoardListForm
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
|
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>${board.boardSubject}</title>
<style type="text/css">
.container{
margin-top: 100px;
}
.input-group{
margin-bottom: 5px;
}
#btn{
margin-top: 20px;
}
#subject, #content{
background-color: white;
}
</style>
<script type="text/javascript">
function detailAction(value) {
if(value == 0)
{
location.href = "BoardUpdateFormAction.bo?num=${board.boardNum}&page=${page}";
}
else if(value == 1)
{
if(confirm("정말로 삭제하시겠습니까?"))
{
location.href="BoardDeleteAction.bo?num=${board.boardNum}";
return true;
}
else
{
return false;
}
}
else if(value == 2)
{
location.href = "BoardListAction.bo?page=${page}";
}
}
</script>
</head>
<body>
<div class="container">
<input type="hidden" name="boardID" value="${sessionScope.memberID}">
<!-- 제목, 작성날짜 -->
<div class="input-group">
<input id="subject" name="boardSubject" type="text" class="form-control" aria-label="Sizing example input" aria-describedby="inputGroup-sizing-default" value="${board.boardSubject}" readonly/>
<span class="input-group-text" id="basic-addon2">${board.boardDate}</span>
</div>
<!-- 첨부파일 -->
<div class="input-group mb-3">
<span type="text" class="form-control" placeholder="Recipient's username" aria-label="Recipient's username" aria-describedby="basic-addon2">
<a href="BoardDownloadAction.bo?boardFile=${board.boardFile}">${board.boardFile}</a>
</span>
<label class="input-group-text" for="inputGroupFile02">첨부파일</label>
</div>
<!-- 내용 -->
<div class="input-group">
<textarea id="content" name="boardContent" class="form-control" aria-label="With textarea" rows="20" readonly>${board.boardContent}</textarea>
</div>
<!-- 로그인 정보와 boardID 값이 일치하면 수정/삭제 버튼 출력 -->
<div id="btn" class="d-grid gap-2 d-sm-flex justify-content-sm-center">
<c:if test="${sessionScope.memberID!=null}">
<c:if test="${sessionScope.memberID == board.boardID}">
<button type="button" class="btn btn-primary btn-sm px-3 gap-3" onclick="detailAction(0)">수정</button>
<button type="button" class="btn btn-outline-secondary btn-sm px-3" onclick="detailAction(1)">삭제</button>
</c:if>
</c:if>
<button type="button" class="btn btn-outline-secondary btn-sm px-3" onclick="detailAction(2)">목록</button>
</div>
</div>
</body>
</html>
|
cs |
- BoardListForm.jsp입니다.
- 글 상세보기 화면에서는 글 제목, 글 작성 날짜, 첨부 파일, 글 내용을 출력합니다.
- session에 저장된 memberID의 값이 있고, session에 저장된 memberID와
BoardListAction 클래스에서 전달한 BoardBean 객체의 boardID 값을 가져와 값이 같다면
'수정', '삭제' 버튼을 출력합니다. (70~75번째 줄)
- session에 저장된 memberID 값과 상관없이 '목록' 버튼을 출력합니다. (76번째 줄)
- '수정' 버튼을 클릭하는 경우 BoardUpdateFormAction.bo로 이동하며,
파라미터 값으로 글 번호와 페이지 번호를 전달합니다. (26~29번째 줄)
- '삭제' 버튼을 클릭하는 경우 정말로 내용을 삭제할 것인지 확인창을 출력한 후
'확인' 버튼을 누르면 BoardDeleteAction.bo로 이동하면 파라미터 값으로 글 번호를 전달합니다. (32~36번째 줄)
- '목록' 버튼을 누를 경우 파라미터 값으로 페이지 번호를 전달하며 BoardListAction.bo로 이동합니다. (44번째 줄)
- 'boardFile'을 출력하는 곳에 <a> 태그를 삽입해 'BoardDownloadAction'을 수행할 수 있게 합니다.(60번째 줄)
BoardUpdateFormAction
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
|
package jsp.board.action;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import jsp.board.model.BoardBean;
import jsp.board.model.BoardDAO;
import jsp.common.action.Action;
import jsp.common.action.ActionForward;
public class BoardUpdateFormAction implements Action {
@Override
public ActionForward execute(HttpServletRequest request, HttpServletResponse response) throws Exception {
ActionForward forward = new ActionForward();
String page = request.getParameter("page");
int num = Integer.parseInt(request.getParameter("num"));
BoardDAO bDAO = BoardDAO.getInstance();
BoardBean board = bDAO.getDetail(num);
request.setAttribute("board", board);
request.setAttribute("page", page);
forward.setRedirect(false);
forward.setPath("BoardUpdateForm.bo");
return forward;
}
}
|
cs |
- BoardUpdateFormAction.java 클래스입니다.
- 파라미터로 전달받은 페이지 값과 글 번호를 변수에 저장합니다. (17~18번째 줄)
- BoardDAO 객체의 getDetail() 메서드를 실행합니다. (20~21번째 줄)
- 실행결과를 BoardBean 객체에 저장하여 request 객체에 저장하고,
전달받은 글 번호(page)도 request 객체에 저장합니다. (23~24번째 줄)
- 'BoardUpdateForm.bo'로 'forward'합니다.
BoardUpdateForm
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
|
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>수정페이지</title>
<style type="text/css">
.container{
margin-top: 100px;
}
.input-group{
margin-bottom: 5px;
}
#btn{
margin-top: 20px;
}
</style>
<script type="text/javascript">
function checkValue() {
/* form 태그 가져오기 */
const form = document.boardForm;
/* form 태그의 boardSubject, boardContent의 value 가져오기 */
const subject = form.boardSubject.value;
const content = form.boardContent.value;
/* 입력이 되지 않았다면 */
if(!subject) {
alert("제목을 입력해주세요.");
return false;
} else if(!content) {
alert("내용을 입력해주세요.");
return false;
}
}
function goToList() {
location.href = "BoardListAction.bo?page=${page}";
}
</script>
</head>
<body>
<div class="container">
<form method="post" action="BoardUpdateAction.bo?page=${page}" name="boardForm" enctype="multipart/form-data" onsubmit="return checkValue()">
<!-- 파라미터로 전달할 hidden 요소 값 -->
<input type="hidden" name="boardID" value="${sessionScope.memberID}">
<input type="hidden" name="boardFile" value="${board.boardFile}">
<input type="hidden" name="boardNum" value="${board.boardNum}">
<!-- 제목 -->
<div class="input-group">
<span class="input-group-text" id="inputGroup-sizing-default">제목</span>
<input name="boardSubject" type="text" class="form-control" aria-label="Sizing example input" aria-describedby="inputGroup-sizing-default" value="${board.boardSubject}"/>
</div>
<!-- 첨부파일 -->
<div class="input-group mb-3">
<input name="newBoardFile" type="file" class="form-control" id="inputGroupFile02">
<label class="input-group-text" for="inputGroupFile02">Upload</label>
</div>
<!-- 내용 -->
<div class="input-group">
<span class="input-group-text">내용</span>
<textarea name="boardContent" class="form-control" aria-label="With textarea" rows="20">${board.boardContent}</textarea>
</div>
<!-- 등록/취소 버튼 -->
<div id="btn" class="d-grid gap-2 d-sm-flex justify-content-sm-center">
<input type="submit" class="btn btn-primary btn-sm px-3 gap-3" value="등록"></button>
<input type="button" class="btn btn-outline-secondary btn-sm px-3" value="취소" onclick="goToList()"></input>
</div>
</form>
</div>
</body>
</html>
|
cs |
- BoardUpdateForm.jsp입니다.
- hidden 타입으로 memberID와 파일명, 글 번호를 전달합니다. (47~49번째 줄)
- '취소' 버튼을 누를 경우 페이지 번호를 파라미터 값으로 전달하며 게시판 목록 화면으로 이동합니다.
- '수정' 버튼을 누를 경우 제목과 내용이 모두 입력됐는지 확인합니다. (21~35번째 줄)
- 게시글 상세 보기에서 수정 버튼을 누르면 위와 같은 화면이 출력됩니다.
- 제목이나 내용을 입력하지 않고 등록 버튼을 누르면 위와 같이 경고창이 출력됩니다.
- 첨부 파일이 없던 글에 첨부 파일을 추가하고 등록 버튼을 눌러보겠습니다.
- 위와 같이 첨부파일이 추가된 것을 확인할 수 있습니다.
- 이 상황에서 로그아웃을 해보겠습니다.
- 로그아웃을 하면 세션에 저장된 회원의 아이디 값이 사라지기 때문에
'수정', '삭제' 버튼이 사라지고 '목록' 버튼만 출력됩니다.
BoardDownloadAction
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
|
package jsp.board.action;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import jsp.common.action.Action;
import jsp.common.action.ActionForward;
public class BoardDownloadAction implements Action {
@Override
public ActionForward execute(HttpServletRequest request, HttpServletResponse response) throws Exception {
// 다운로드할 파일명을 가져온다.
String fileName = request.getParameter("boardFile");
// 파일이 있는 절대경로를 가져온다.
// 현재 업로드된 파일은 UploadFolder 폴더에 있다.
String folder = request.getServletContext().getRealPath("UploadFolder");
// 파일의 절대경로를 만든다.
String filePath = folder + "/" + fileName;
try {
File file = new File(filePath);
byte b[] = new byte[(int) file.length()];
// page의 ContentType등을 동적으로 바꾸기 위해 초기화
response.reset();
// 한글 인코딩
String encoding = new String(fileName.getBytes("utf-8"),"iso-8859-1");
// 파일 링크를 클릭했을 때 다운로드 저장 화면이 출력되게 처리하는 부분
response.setHeader("Content-Disposition", "attachment;filename="+ encoding);
response.setHeader("Content-Type", "application/octet-stream; charset=utf-8");
response.setHeader("Content-Length", String.valueOf(file.length()));
if (file.isFile()) // 파일이 있을경우
{
FileInputStream fileInputStream = new FileInputStream(file);
ServletOutputStream servletOutputStream = response.getOutputStream();
// 파일을 읽어서 클라이언트쪽으로 저장한다.
int readNum = 0;
// byte 배열의 모든 바이트를 읽어들이기
while ( (readNum = fileInputStream.read(b)) != -1) {
//다 읽어들이면 버퍼를 0부터 byte의 길이만큼 출력
servletOutputStream.write(b, 0, readNum);
}
//stream 객체 닫기
servletOutputStream.close();
fileInputStream.close();
}
} catch (Exception e) {
System.out.println("Download Exception : " + e.getMessage());
}
return null;
}
}
|
cs |
- BoardDownloadAction.java 클래스입니다.
- 우선 파일의 절대경로를 얻어옵니다. (20~26번째 줄)
- 파일명을 이용해 파일 객체를 생성하고 Byte 배열을 파일의 길이만큼 생성합니다. (29~30번째 줄)
- response 객체를 초기화합니다.(33번째 줄)
- 다운로드 시 파일 헤더 처리를 어떻게 할 것인지 설정합니다.(39~41번째 줄)
- 파일이 존재하는 경우 'FileInputStream' 객체를 이용해 byte 배열의 모든 byte를 읽어 들이고,
'ServletOutputStream' 객체를 이용해 버퍼를 0부터 byte 배열의 길이만큼 출력합니다. (50~54번째 줄)
- 출력 후 Stream 객체를 닫습니다. (57~58번째 줄)
- 다운로드 시 아래와 같이 파일이 다운로드됩니다. (파일을 두 번 다운로드하여서 위와 같이 출력)
BoardDeleteAction
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
|
package jsp.board.action;
import java.io.File;
import java.io.FileInputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import jsp.board.model.BoardDAO;
import jsp.common.action.Action;
import jsp.common.action.ActionForward;
public class BoardDeleteAction implements Action {
@Override
public ActionForward execute(HttpServletRequest request, HttpServletResponse response) throws Exception {
ActionForward forward = new ActionForward();
BoardDAO bDAO = BoardDAO.getInstance();
//파라미터로 전달받은 페이지 값 저장
int num = Integer.parseInt(request.getParameter("num"));
//파일 가져오기
String file = bDAO.getFile(num);
//파일 삭제하기
boolean result = bDAO.deleteBoard(num);
//파일이 존재한다면
if(file != null) {
//절대 경로 가져오기
String folderPath = request.getServletContext().getRealPath("UploadFolder");
String filePath = folderPath + "/" +file;
//폴더+파일 네임으로 파일 찾기
File fileName = new File(filePath);
//파일이 존재한다면 파일 삭제
if(fileName.exists()) {
fileName.delete();
}
}
//삭제가 진행되었다면
if(result) {
//redirect
forward.setRedirect(true);
forward.setPath("BoardListAction.bo");
} else {
return null;
}
return forward;
}
}
|
cs |
- BoardDeleteAction.java 클래스입니다.
- 파라미터로 전달받은 페이지 번호를 변수에 저장합니다. (22번째 줄)
- BoardDAO 객체를 생성하고 getFile() 메서드를 실행합니다 (25번째 줄)
- 전달받은 페이지 번호를 이용해 deleteBoard() 메서드를 실행합니다. (27번째 줄)
- getFile() 결과 파일명이 존재한다면 폴더의 절대 경로와 파일명을 더해 파일 삭제를 진행합니다. (30~42번째 줄)
- deleteBoard() 메서드가 성공적으로 실행되면 'true'값이 반환되고,
'BoardListAction.bo'로 페이지가 'redirect'됩니다. (45~48번째 줄)
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
|
// 삭제할 파일명을 가져오기 위한 메서드
public String getFile(int num) {
String file = null;
DBConnection dbConnection = null;
Connection conn = null;
PreparedStatement pstmt = null;
ResultSet rs = null;
try {
dbConnection = DBConnection.getInstance();
conn = dbConnection.getConnection();
StringBuffer sql = new StringBuffer();
sql.append("SELECT BOARD_FILE FROM BOARD WHERE BOARD_NUM = ?");
pstmt = conn.prepareStatement(sql.toString());
pstmt.setInt(1, num);
rs = pstmt.executeQuery();
if(rs.next()) {
file = rs.getString("BOARD_FILE");
}
} catch (Exception e) {
e.printStackTrace();
} finally {
dbConnection.freeConnection(conn, pstmt, rs);
}
return file;
}
// 글을 삭제하기 위한 메서드
public boolean deleteBoard(int num) {
boolean result = false;
DBConnection dbConnection = null;
Connection conn = null;
PreparedStatement pstmt = null;
try {
dbConnection = DBConnection.getInstance();
conn = dbConnection.getConnection();
StringBuffer sql = new StringBuffer();
sql.append("DELETE FROM BOARD WHERE BOARD_NUM = ? ");
pstmt = conn.prepareStatement(sql.toString());
pstmt.setInt(1, num);
int updateCount = pstmt.executeUpdate();
if(updateCount > 0) {
result = true;
}
} catch (Exception e) {
e.printStackTrace();
} finally {
dbConnection.freeConnection(conn, pstmt);
}
return result;
}
|
cs |
- getFile(), deleteBoard() 메서드입니다.
- 두 메서드 모두 전달받은 페이지 번호를 파라미터로 사용합니다.
- getFile() 메서드는 file명을, deleteBoard() 메서드는 boolean 값을 리턴합니다.
- 글 삭제 버튼을 누르면 위와 같은 화면이 출력됩니다.
- 삭제 버튼을 누르면 위와 같이 게시판에 글이 삭제된 것을 확인할 수 있습니다.
오늘은 게시글 상세보기, 게시글 수정, 게시글 삭제, 파일 다운로드를 구현하는 방법을 살펴봤습니다.
해당 프로젝트는 여기까지 구현하려고 합니다.
이후에는 스프링을 이용해
웹페이지의 확실한 컨셉을 선정한 이후에
다중 첨부파일 구현이나
댓글 및 추천 기능 구현, 아이디 중복 검사 구현,
가입시 작성한 이메일로 아이디나 비번 찾기 기능 구현 등
다양한 API를 활용해 프로젝트를 확장해 볼 예정입니다.
스프링으로 웹 프로젝트를 진행하게 되면
블로그글도 바로 업데이트 하겠습니다.
다음 글은 해당 프로젝트 마지막 글로
프로젝트 배포를 할 예정입니다.
여기까지 긴 글 읽어주셔서 감사하고
이해가 안가는 내용은 댓글 부탁드립니다!
감사합니다!
댓글