*JAVA/JSP 35번 글의 시점부터는 노트북이 고장나는 바람에.. 다른 분의 글과 이전에 올렸던 글들을 참고하여, 다른 데스크탑의 윈도우 환경에 환경설정을 다시 진행한 후 작성하였습니다. 환경설정 관련 글들은 아래를 참고해 주세요.
- JDK11 설치 및 환경 변수(JAVA_HOME) 설정 - CLASSPATH는 추가하지 않음
자바(JAVA) 11 설치 및 환경설정 | 자바 11 환경 변수
자바로 코딩 공부를 하려면 개발 할 수 있는 환경을 만들어 주어야 한다. 그 순서를 먼저 작성하자면JAVA SE JDK 설치 -> JAVA 환경 변수 설정 -> IDE 설치 이렇게 볼 수 있겠다. 이 포스팅은 자바로 개
velog.io

- 톰캣 설치, 이클립스 설치 - 이 글을 쓰는 시점에서는 Tomcat 8버전이 없어, Tomcat 9버전 설치
JSP) JDK, 이클립스(eclipse), 톰캣 설치 및 환경 설정
1. JDK 설치 → Path 설정 2.eclipse JAVA EE버전 다운로드 3.웹컨테이너 톰캣 설치 →톰캣 환경설정 1. JDK 설치 - JAVA) 1. JDK 참고하여 설치하고 설정한다. -https://storyblogger.tistory.com/15?category=984696 2. 구글에
storyblogger.tistory.com

- 이클립스 JDK 버전 설정 - JDK11로 설정
[이클립스] JDK 버전 바꾸는 법
스프링을 사용하는 에러가 난다? 그러면 JRE 버전을 확인해보자! 프로젝트의 JRE System Library의 오른쪽을 살펴보면 [JavaSE-17]이라고 되어있다. 스프링이나 하이버네이트를 사용할 때, 자바 8이나 자
myvelop.tistory.com
- JDK 설치 및 환경 변수(JAVA_HOME) 설정, 톰캣 설치, 이클립스 설치 및 JDK 버전 설정 이후~ ⇒ 톰캣 버전과 jsp 파일 경로는 글 내용과 다르게 아래 이미지와 같음

JAVA/JSP 1. 개발 환경 구축 - 이클립스 기본 설정
*JDK 설치 및 환경 변수(JAVA_HOME) 설정, 톰캣 설치, 이클립스 설치를 완료한 상태OpenJDK 11: 자바 프로그램을 컴파일하고 실행해주는 기본 도구*이클립스 JDK-17이 설치되어있어서, https://coding-house.tisto
keep-programming-study.tistory.com
JAVA/JSP 1. 개발 환경 구축 - JSP 예제 테스트
1. 프로젝트 생성1) [File] → [New] → [Dynamic Web Project] 선택 2) 프로젝트 설정 화면 → Project name: HelloJSP, Target runtime: Apache Tomcat v9.0, Dynamic web module version: 4.0으로 설정 후 Next 클릭 3) 자바 소스 파일
keep-programming-study.tistory.com
JAVA/JSP 1. 개발 환경 구축 - 마지막 추가 설정
1. 외부 웹 브라우저로 실행하기-크롬이클립스는 웹 애플리케이션 실행 시, 자체 브라우저를 통해 실행 결과 출력웹 애플리케이션 배포 시 사용자는 크롬/파이어폭스 같은 전용 웹 브라우저로
keep-programming-study.tistory.com
- 오라클(Oracle Database 11gR2 Express Edition) 설치 및 설정
JAVA/JSP 14. 데이터베이스 - 특징, 오라클 설치(Oracle Database 11gR2 Express Edition), 사용자 계정 생성 및
1. 데이터베이스의 특징우리가 매일 PC나 스마트폰을 통해 접하는 거의 모든 웹 애플리케이션에서 사용함매일 업데이트되는 뉴스나 날씨 등의 정보는 데이터베이스가 없다면 클라이언트에 전달
keep-programming-study.tistory.com
JAVA/JSP 15. 데이터베이스 - 테이블 및 시퀀스 생성, JDBC 설정 및 데이터베이스 연결
*회원제 게시판 만들기-회원 인증 필요4. 테이블 및 시퀀스 생성1) 테이블 생성(1) member 테이블 - 아이디, 패스워드, 이름, 가입 날짜테이블 정의컬럼명데이터 타입 null 허용 키 기본값 설명idvarchar2
keep-programming-study.tistory.com
JAVA/JSP 16. 데이터베이스 - 커넥션 풀로 성능 개선, 간단한 쿼리 작성 및 실행
6. 커넥션 풀로 성능 개선웹은 클라이언트의 요청에 서버가 응답하는 구조→ Connection 객체 생성 때마다 네트워크 통신이 이뤄지며, 시간이 걸리는 작업들이 수반됨 == 시스템 성능에 큰 영향을
keep-programming-study.tistory.com
- 시퀀스 설정
JAVA/JSP 15. 데이터베이스 - 테이블 및 시퀀스 생성, JDBC 설정 및 데이터베이스 연결
*회원제 게시판 만들기-회원 인증 필요4. 테이블 및 시퀀스 생성1) 테이블 생성(1) member 테이블 - 아이디, 패스워드, 이름, 가입 날짜테이블 정의컬럼명데이터 타입 null 허용 키 기본값 설명idvarchar2
keep-programming-study.tistory.com
1. 파일 다운로드
- 목록 보기나 상세 보기 화면에서 첨부 파일의 [다운로드] 링크 클릭 시 실행
1) 모델 작성 - DAO에 메서드 추가
// Java Resources/src/mvcboard/MVCBoardDAO.java
package mvcboard;
... 임포트 생략 ...
public class MVCBoardDAO extends DBConnPool { // 커넥션 풀 상속
... 생략 ...
// 일련번호를 인수로 받아 다운로드 횟수 1 증가
public void downCountPlus(String idx) {
String query = "UPDATE mvcboard SET "
+ "downcount = downcount+1"
+ "where idx=?";
try {
psmt = con.prepareStatement(query);
psmt.setString(1, idx);
psmt.executeUpdate();
} catch (Exception e) {}
}
}
2) FileUtil.java 메서드 추가
// Java Resources/src/file/FileUtil.java
package file;
... 임포트문 생략 ...
public class FileUtil {
... 생략 ...
// 명시한 파일을 찾아 다운로드
public static void download(HttpServletRequest req, HttpServletResponse resp,
String directory, String sfileName, String ofileName) {
String sDirectory = req.getServletContext().getRealPath(directory);
try {
// 파일을 찾아 입력 스트림 생성
File file = new File(sDirectory, sfileName);
InputStream iStream = new FileInputStream(file);
// 한글 파일명 깨짐 방지
String client = req.getHeader("User-Agent");
if (client.indexOf("WOW64") == -1) {
ofileName = new String(ofileName.getBytes("UTF-8"), "ISO-8859-1");
} else {
ofileName = new String(ofileName.getBytes("KSC5601"), "ISO-8859-1");
}
// 파일 다운로드용 응답 헤더 설정
resp.reset();
resp.setContentType("application/octet-stream");
resp.setHeader("Content-Disposition",
"attachment; filename=\"" + ofileName + "\"");
resp.setHeader("Content-Length", "" + file.length() );
// response 내장 객체로부터 새로운 출력 스트림 생성
OutputStream oStream = resp.getOutputStream();
// 출력 스트림에 파일 내용 출력
byte b[] = new byte[(int)file.length()];
int readBuffer = 0;
while ( (readBuffer = iStream.read(b)) > 0 ) {
oStream.write(b, 0, readBuffer);
}
// 입/출력 스트림 닫음
iStream.close();
oStream.close();
} catch (FileNotFoundException e) {
System.out.println("파일을 찾을 수 없습니다.");
e.printStackTrace();
} catch (Exception e) {
System.out.println("예외가 발생하였습니다.");
e.printStackTrace();
}
}
}
3) 컨트롤러(파일 다운로드 서블릿) 작성
// Java Resources/src/mvcboard/DownloadController.java
package mvcboard;
.. 임포트문 생략 ...
import file.FileUtil;
@WebServlet("/board/download.board")
public class DownloadController extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
// 매개변수 받기
String ofile = req.getParameter("ofile"); // 원본 파일명
String sfile = req.getParameter("sfile"); // 저장된 파일명
String idx = req.getParameter("idx"); // 게시물 일련번호
// 파일 다운로드
FileUtil.download(req, resp, "/Uploads", sfile, ofile);
// 해당 게시물의 다운로드 수 1 증가
MVCBoardDAO dao = new MVCBoardDAO();
dao.downCountPlus(idx);
dao.close();
}
}
4) Default.jsp 실행 후 동작 확인
(1) 오류 1: 게시물 조회수 업데이트 중 예외 발생
-> 어제 몰랐던 오류를 발견했다. DAO 메서드의 SQL 쿼리문에서, SET 키워드 다음에 공백이 없어 문제가 생겼다.
java.sql.SQLSyntaxErrorException: ORA-00971: missing SET keyword
at oracle.jdbc.driver.T4CTTIoer.processError(T4CTTIoer.java:440)
at oracle.jdbc.driver.T4CTTIoer.processError(T4CTTIoer.java:396)
at oracle.jdbc.driver.T4C8Oall.processError(T4C8Oall.java:837)
at oracle.jdbc.driver.T4CTTIfun.receive(T4CTTIfun.java:445)
at oracle.jdbc.driver.T4CTTIfun.doRPC(T4CTTIfun.java:191)
at oracle.jdbc.driver.T4C8Oall.doOALL(T4C8Oall.java:523)
at oracle.jdbc.driver.T4CPreparedStatement.doOall8(T4CPreparedStatement.java:207)
at oracle.jdbc.driver.T4CPreparedStatement.executeForRows(T4CPreparedStatement.java:1010)
at oracle.jdbc.driver.OracleStatement.doExecuteWithTimeout(OracleStatement.java:1315)
at oracle.jdbc.driver.OraclePreparedStatement.executeInternal(OraclePreparedStatement.java:3576)
at oracle.jdbc.driver.OraclePreparedStatement.executeQuery(OraclePreparedStatement.java:3620)
at oracle.jdbc.driver.OraclePreparedStatementWrapper.executeQuery(OraclePreparedStatementWrapper.java:1491)
at org.apache.tomcat.dbcp.dbcp2.DelegatingPreparedStatement.executeQuery(DelegatingPreparedStatement.java:123)
at org.apache.tomcat.dbcp.dbcp2.DelegatingPreparedStatement.executeQuery(DelegatingPreparedStatement.java:123)
at mvcboard.MVCBoardDAO.updateVisitCount(MVCBoardDAO.java:157)
at mvcboard.ViewController.service(ViewController.java:21)
...

- 공백을 추가한 후 조회수가 증가하는 모습.

(2) 파일이 다운로드되고 다운로드 횟수가 증가한 모습(다운로드를 두 번 클릭하여 2로 증가한 것)


2. 삭제하기
1) 요청명/서블릿 매핑 컨트롤러(서블릿) 작성
- mode 매개변수 값을 request 영역에 저장한 다음, Pass.jsp로 포워드
// Java Resources/src/mvcboard/PassController.java
package mvcboard;
.. 임포트문 생략 ...
@WebServlet("/board/pass.board")
public class PassController extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
req.setAttribute("mode", req.getParameter("mode"));
req.getRequestDispatcher("/board/Pass.jsp").forward(req, resp);
}
}
2) 뷰(JSP 파일) 작성
<!-- src/main/webapp/board/Pass.jsp -->
<%@ 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>파일 첨부형 게시판</title>
<script type="text/javascript">
function validateForm(form) {
if (form.pass.value == "") {
alert("비밀번호를 입력하세요.");
form.pass.focus();
return false;
}
}
</script>
</head>
<body>
<h2>파일 첨부형 게시판 - 비밀번호 검증(Pass)</h2>
<form name="writeFrm" method="post" action="../board/pass.board" onsubmit="return validateForm(this);">
<input type="hidden" name="idx" value="${ param.idx }" />
<input type="hidden" name="mode" value="${ param.mode }" />
<table border="1" width="90%">
<tr>
<td>비밀번호</td>
<td>
<input type="password" name="pass" style="width:100px;" />
</td>
</tr>
<tr>
<td colspan="2" align="center">
<button type="submit">검증하기</button>
<button type="reset">초기화</button>
<button type="button" onclick="location.href='../board/list.board';">
목록 바로가기
</button>
</td>
</tr>
</table>
</form>
</body>
</html>
3) 모델 작성(DAO 클래스에 메서드 추가)
// Java Resources/src/mvcboard/MVCBoardDAO.java
package mvcboard;
... 임포트 생략 ...
public class MVCBoardDAO extends DBConnPool { // 커넥션 풀 상속
... 생략 ...
// 입력한 비밀번호가, 특정 일련번호 게시물의 비밀번호와 일치하는지 확인
public boolean confirmPassword(String pass, String idx) {
boolean isCorr = true;
try {
String query = "SELECT COUNT(*) FROM mvcboard WHERE pass=? AND idx=?";
psmt = con.prepareStatement(query);
psmt.setString(1, pass);
psmt.setString(2, idx);
rs = psmt.executeQuery();
rs.next();
if (rs.getInt(1) == 0) {
isCorr = false;
}
} catch (Exception e) {
isCorr = false;
e.printStackTrace();
}
return isCorr;
}
// 지정한 일련번호의 게시물 삭제
public int deletePost(String idx) {
int result = 0;
try {
String query = "DELETE FROM mvcboard WHERE idx=?";
psmt = con.prepareStatement(query);
psmt.setString(1, idx);
result = psmt.executeUpdate();
} catch (Exception e) {
System.out.println("게시물 삭제 중 예외 발생");
e.printStackTrace();
}
return result;
}
}
4) FileUtil.java 메서드 추가
// Java Resources/src/file/FileUtil.java
package file;
... 임포트문 생략 ...
public class FileUtil {
... 생략 ...
// 지정한 위치의 파일 삭제
public static void deleteFile(HttpServletRequest req,
String directory, String filename) {
String sDirectory = req.getServletContext().getRealPath(directory);
File file = new File(sDirectory + File.separator + filename);
if (file.exists()) file.delete();
}
}
5) 컨트롤러(서블릿) 추가 작성
// Java Resources/src/mvcboard/PassController.java
package mvcboard;
.. 임포트문 생략 ...
@WebServlet("/board/pass.board")
public class PassController extends HttpServlet {
... 생략 ...
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
// 매개변수 저장
String idx = req.getParameter("idx");
String mode = req.getParameter("mode");
String pass = req.getParameter("pass");
// 비밀번호 확인
MVCBoardDAO dao = new MVCBoardDAO();
boolean confirmed = dao.confirmPassword(pass, idx);
dao.close();
if (confirmed) { // 비밀번호 일치
if (mode.equals("edit")) { // 수정 모드
HttpSession session = req.getSession();
session.setAttribute("pass", pass);
resp.sendRedirect("../board/edit.board?idx=" + idx);
} else if (mode.equals("delete")) { // 삭제 모드
dao = new MVCBoardDAO();
MVCBoardDTO dto = dao.selectView(idx);
int result = dao.deletePost(idx); // 게시물 삭제
dao.close();
if (result == 1) { // 게시물 삭제 성공 시 첨부파일도 삭제
String saveFileName = dto.getSfile();
FileUtil.deleteFile(req, "/Uploads", saveFileName);
}
JSFunction.alertLocation(resp, "삭제되었습니다.", "../mvcboard/list.do");
}
} else { // 비밀번호 불일치
JSFunction.alertBack(resp, "비밀번호 검증에 실패했습니다.");
}
}
}
6) Default.jsp 실행 후 동작 확인


틀린 비밀번호 입력

올바른 비밀번호 입력(2345): 알림창이 안 뜨고 삭제처리가 안되는 오류발생?? 콘솔창에 오류가 뜨지 않음
-> JSFunction.java의 alertLocation 메서드 예외처리 부분 catch (Exception e) {} 안에 System.out.println("Exception: " + e.getMessage()); e.printStackTrace(); 추가해도 오류가 뭔지 뜨지 않음...

View.jsp의 파라미터에 오타가 있었음... 오타 수정 후 오류 해결!: model -> mode로 수정



3. 수정하기
1) 요청명/서블릿 매핑 컨트롤러(서블릿) 작성
// Java Resources/src/mvcboard/EditController.java
package mvcboard;
.. 임포트문 생략 ...
@WebServlet("/board/edit.board")
public class EditController extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
String idx = req.getParameter("idx");
MVCBoardDAO dao = new MVCBoardDAO();
MVCBoardDTO dto = dao.selectView(idx);
req.setAttribute("dto", dto);
req.getRequestDispatcher("/board/Edit.jsp").forward(req, resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
// 파일 업로드 처리
// 업로드 디렉토리의 물리적 경로 확인
String saveDirectory = req.getServletContext().getRealPath("/Uploads");
// 초기화 매개변수로 설정한 첨부 파일 최대 용량 확인
ServletContext application = this.getServletContext();
int maxPostSize = Integer.parseInt(application.getInitParameter("maxPostSize"));
// 파일 업로드
MultipartRequest mr = FileUtil.uploadFile(req, saveDirectory, maxPostSize);
// 파일 업로드 실패
if (mr == null) {
JSFunction.alertBack(resp, "첨부 파일이 제한 용량을 초과합니다.");
return;
}
// 파일 업로드 외 처리
// 수정 내용을 매개변수에서 얻어옴
String idx = mr.getParameter("idx");
String prevOfile = mr.getParameter("prevOfile");
String prevSfile = mr.getParameter("prevSfile");
String name = mr.getParameter("name");
String title = mr.getParameter("title");
String content = mr.getParameter("content");
// 비밀번호는 session에서 가져옴
HttpSession session = req.getSession();
String pass = (String)session.getAttribute("pass");
// DTO에 저장
MVCBoardDTO dto = new MVCBoardDTO();
dto.setIdx(idx);
dto.setName(name);
dto.setTitle(title);
dto.setContent(content);
dto.setPass(pass);
// 원본 파일명과 저장된 파일 이름 설정
String fileName = mr.getFilesystemName("ofile");
if (fileName != null) {
// 첨부 파일이 있을 경우 파일명 변경
// 새로운 파일명 생성
String now = new SimpleDateFormat("yyyyMMdd_HmsS").format(new Date());
String ext = fileName.substring(fileName.lastIndexOf("."));
String newFileName = now + ext;
// 파일명 변경
File oldFile = new File(saveDirectory + File.separator + fileName);
File newFile = new File(saveDirectory + File.separator + newFileName);
oldFile.renameTo(newFile);
// DTO에 저장
dto.setOfile(fileName); // 원래 파일 이름
dto.setSfile(newFileName); // 서버에 저장된 파일 이름
// 기존 파일 삭제
FileUtil.deleteFile(req, "/Uploads", prevSfile);
} else {
// 첨부 파일이 없으면 기존 이름 유지
dto.setOfile(prevOfile);
dto.setSfile(prevSfile);
}
// DB에 수정 내용 반영
MVCBoardDAO dao = new MVCBoardDAO();
int result = dao.updatePost(dto);
dao.close();
// 성공 or 실패?
if (result == 1) { // 수정 성공
session.removeAttribute("pass");
resp.sendRedirect("../board/view.board?idx=" + idx);
} else { // 수정 실패
JSFunction.alertLocation(resp, "비밀번호 검증을 다시 진행해주세요.",
"../board/view.board?idx=" + idx);
}
}
}
2) 뷰(JSP 파일) 작성
<!-- src/main/webapp/board/Edit.jsp -->
<%@ 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>파일 첨부형 게시판</title>
</head>
<h2>파일 첨부형 게시판 - 수정하기(Edit)</h2>
<form name="writeFrm" method="post" enctype="multipart/form-data" action="../board/edit.board">
<input type="hidden" name="idx" value="${ dto.idx }"/>
<input type="hidden" name="prevOfile" value="${ dto.ofile }" />
<input type="hidden" name="prevSfile" value="${ dto.sfile }" />
<table border="1" width="90%">
<!-- 필수 입력값인 작성자/제목/내용의 유효성 검사는, 모두 html의 required로 처리 -->
<tr>
<td>작성자</td>
<td>
<input type="text" name="name" style="width:150px;" value="${ dto.name }" required />
</td>
</tr>
<tr>
<td>제목</td>
<td>
<input type="text" name="title" style="width:90%;" value="${ dto.title }" required/>
</td>
</tr>
<tr>
<td>내용</td>
<td>
<textarea name="content" style="width:90%;height:100px;" required>${ dto.content }</textarea>
</td>
</tr>
<tr>
<td>첨부 파일</td>
<td>
<input type="file" name="ofile" />
</td>
</tr>
<tr>
<td colspan="2" align="center">
<button type="submit">작성 완료</button>
<button type="reset">모두 초기화</button>
<button type="button" onclick="location.href='../board/list.board';">
목록 바로가기
</button>
</td>
</tr>
</table>
</form>
</body>
</html>
3) 모델 작성(DAO에 메서드 추가)
// Java Resources/src/mvcboard/MVCBoardDAO.java
package mvcboard;
... 임포트 생략 ...
public class MVCBoardDAO extends DBConnPool { // 커넥션 풀 상속
... 생략 ...
// 게시글 데이터를 받아 DB에 저장되어 있던 내용을 수정(파일 업로드 지원).
public int updatePost(MVCBoardDTO dto) {
int result = 0;
try {
// 쿼리문 템플릿 준비
String query = "UPDATE mvcboard"
+ " SET title=?, name=?, content=?, ofile=?, sfile=? "
+ " WHERE idx=? and pass=?";
// 쿼리문 준비
psmt = con.prepareStatement(query);
psmt.setString(1, dto.getTitle());
psmt.setString(2, dto.getName());
psmt.setString(3, dto.getContent());
psmt.setString(4, dto.getOfile());
psmt.setString(5, dto.getSfile());
psmt.setString(6, dto.getIdx());
psmt.setString(7, dto.getPass());
// 쿼리문 실행
result = psmt.executeUpdate();
} catch (Exception e) {
System.out.println("게시물 수정 중 예외 발생");
e.printStackTrace();
}
return result;
}
}
4) Default.jsp 실행 후 동작 확인 (비밀번호 1234, 틀린 비밀번호 입력 시 알림은 삭제하기와 같음)





'자바(JAVA) > JSP 웹 프로그래밍 공부 (성낙현의 JSP 자바 웹 프로그래밍 참고)' 카테고리의 다른 글
JAVA/JSP 45. SMTP를 활용한 이메일 전송하기 - 개요 및 프로젝트 구상, 네이버 SMTP 설정, 이메일 전송 프로그램 작성 (2) | 2025.05.13 |
---|---|
JAVA/JSP 44. 웹소켓으로 채팅 프로그램 만들기 - 사전 지식, 프로젝트 구상, 채팅 서버/채팅 클라이언트 구현 (3) | 2025.05.12 |
JAVA/JSP 42. 모델2 방식(MVC 패턴)의 자료실형 게시판 만들기 - 파일 업로드 포함 글쓰기, 상세 보기 (0) | 2025.05.08 |
JAVA/JSP 41. 모델2 방식(MVC 패턴)의 자료실형 게시판 만들기 - 프로젝트 구상, 목록 보기 구현 (3) | 2025.05.02 |
JAVA/JSP 40. 서블릿(Servlet) 작성 - MVC 패턴을 적용한 회원인증 구현 (2) | 2025.05.01 |