*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. 파일 업로드 포함 글쓰기(서블릿 매핑에 web.xml 사용)
1) 요청명/서블릿 매핑(web.xml)
<!-- src/main/webapp/WEB-INF/web.xml -->
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd" id="WebApp_ID" version="4.0">
<display-name>HelloJSP</display-name>
... 생략 ...
<servlet> <!-- 서블릿 등록 -->
<servlet-name>MVCBoardWrite</servlet-name> <!-- 1. 서블릿 매핑을 위한 서블릿명 -->
<servlet-class>mvcboard.WriteController</servlet-class> <!-- 2. 요청을 처리할 서블릿을 패키지를 포함하여 명시 -->
</servlet>
<servlet-mapping> <!-- 서블릿과 요청명 매핑 -->
<servlet-name>MVCBoardWrite</servlet-name> <!-- 3. 1과 동일한 서블릿명 -->
<url-pattern>/board/write.board</url-pattern> <!-- 4. 컨텍스트 루트를 제외한 요청명 작성 -->
</servlet-mapping>
</web-app>
2) 업로드할 파일의 제한 용량을 컨텐스트 초기화 매개변수로 추가(web.xml)
<!-- src/main/webapp/WEB-INF/web.xml -->
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd" id="WebApp_ID" version="4.0">
<display-name>HelloJSP</display-name>
... 생략 ...
<!-- 업로드할 파일의 제한 용량: 1024바이트 x 1000 = 1MB -->
<context-param>
<param-name>maxPostSize</param-name>
<param-value>1024000</param-value>
</context-param>
</web-app>
3) 컨트롤러 작성 1 - 작성 폼으로 진입
// Java Resources/src/mvcboard/WriteController.java
package mvcboard;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class WriteController extends HttpServlet{
//1. 글쓰기 페이지로 진입
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
req.getRequestDispatcher("/board/Write.jsp").forward(req, resp);
}
}
4) 뷰(JSP 파일) 작성
<!-- src/main/webapp/board/Write.jsp -->
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>파일 첨부형 게시판</title>
</head>
<body>
<h2>파일 첨부형 게시판 - 글쓰기</h2>
<form name="writeFrm" method="post" enctype="multipart/form-data"
action="../board/write.board">
<table border="1" width="90%">
<tr>
<td>작성자</td>
<td>
<!-- 필수 항목 입력 확인을 required로 진행 -->
<input type="text" name="name" style="width:150px;" required />
</td>
</tr>
<tr>
<td>제목</td>
<td>
<!-- 필수 항목 입력 확인을 required로 진행 -->
<input type="text" name="title" style="width:90%;" required />
</td>
</tr>
<tr>
<td>내용</td>
<td>
<!-- 필수 항목 입력 확인을 required로 진행 -->
<textarea name="content" style="width:90%; height:100px;" required></textarea>
</td>
</tr>
<tr>
<td>첨부 파일</td>
<td>
<input type="file" name="ofile" />
</td>
</tr>
<tr>
<td>비밀번호</td>
<td>
<!-- 필수 항목 입력 확인을 required로 진행 -->
<input type="password" name="pass" style="width:100px;" required />
</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>
JSP 파일 실행 결과
5) 모델 작성(DAO에 기능 추가)
// Java Resources/src/mvcboard/MVCBoardDAO.java
package mvcboard;
import java.util.List;
import java.util.Map;
import java.util.Vector;
import common.DBConnPool;
public class MVCBoardDAO extends DBConnPool { // 커넥션 풀 상속
... 생략 ...
// 게시글 데이터를 받아 DB에 추가(파일 업로드 지원)
// 1. Write.jsp에서 전송한 폼값을 서블릿이 받아 DTO에 저장한 후 DAO로 전달
public int insertWrite(MVCBoardDTO dto) {
int result = 0;
try {
// 2. INSERT 쿼리문
String query = "INSERT INTO mvcboard ("
+ "idx, name, title, content, ofile, sfile,pass) "
+ "VALUES ("
+ "seq_board_num.NEXTVAL, ?, ?, ?, ?, ?, ?)";
// 3. 쿼리문을 인수로 PreparedStatement 객체 생성 후 인파라미터 설정
psmt = con.prepareStatement(query);
psmt.setString(1, dto.getName());
psmt.setString(2, dto.getTitle());
psmt.setString(3, dto.getContent());
psmt.setString(4, dto.getOfile());
psmt.setString(5, dto.getSfile());
psmt.setString(6, dto.getPass());
// 4. 쿼리문을 실행하여 테이블에 입력
result = psmt.executeUpdate();
} catch (Exception e) {
System.out.println("게시물 입력 중 예외 발생");
e.printStackTrace();
}
// 5. 입력된 결과를 서블릿으로 반환
return result;
}
}
6) 컨트롤러 작성 2 - 폼값 처리(doPost)
(1) 파일 업로드용 유틸리티 클래스 작성
// Java Resources/src/file/FileUtil.java
package file;
import javax.servlet.http.HttpServletRequest;
import com.oreilly.servlet.MultipartRequest;
public class FileUtil {
// 파일 업로드(multipart/form-data 요청) 처리
public static MultipartRequest uploadFile(HttpServletRequest req,
String saveDirectory, int maxPostSize) {
try {
// 파일 업로드
return new MultipartRequest(req, saveDirectory, maxPostSize, "UTF-8");
} catch (Exception e) {
// 파일 업로드 실패
e.printStackTrace();
return null;
}
}
}
(2) 컨트롤러에 글쓰기 메서드 추가
// Java Resources/src/mvcboard/WriteController.java
package mvcboard;
... 임포트문 생략 ...
public class WriteController extends HttpServlet{
... 생략 ...
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
// 파일 업로드 처리
// 1. 업로드 디렉토리의 물리적 경로 확인
String saveDirectory = req.getServletContext().getRealPath("/Uploads");
// 2. web.xml에 초기화 매개변수로 설정한, 첨부 파일 최대 용량 확인
ServletContext application = getServletContext();
int maxPostSize = Integer.parseInt(application.getInitParameter("maxPostSize"));
// 3. 파일 업로드
MultipartRequest mr = FileUtil.uploadFile(req, saveDirectory, maxPostSize);
if (mr == null) {
// 4. 파일 업로드 실패
JSFunction.alertLocation(resp, "첨부 파일이 제한 용량을 초과합니다.", "../board/write.board");
return;
}
// 파일 업로드 외 처리
// 5. 폼값을 DTO에 저장
MVCBoardDTO dto = new MVCBoardDTO();
dto.setName(mr.getParameter("name"));
dto.setTitle(mr.getParameter("title"));
dto.setContent(mr.getParameter("content"));
dto.setPass(mr.getParameter("pass"));
// 원본 파일명과 저장된 파일 이름 설정
// 5. 폼값을 DTO에 저장
String fileName = mr.getFilesystemName("ofile");
// 6. DAO를 통해 폼값을 데이터베이스에 기록
if (fileName != null) {
// 7. 파일명 변셩
// 첨부 파일이 있을 경우 파일명 변경
// 새로운 파일명 생성
String now = new SimpleDateFormat("yyyMMdd_HmsS").format(new Date());
String ext = fileName.substring(fileName.lastIndexOf("."));
String newFileName = now + ext;
// 8. 원래 파일명과 저장된 파일명 따로 기록, DTO에 저장
File oldFile = new File(saveDirectory + File.separator + fileName);
File newFile = new File(saveDirectory + File.separator + newFileName);
oldFile.renameTo(newFile);
dto.setOfile(fileName);
dto.setSfile(newFileName);
}
// 9. DAO를 통해 DB에 게시 내용 저장
MVCBoardDAO dao = new MVCBoardDAO();
int result = dao.insertWrite(dto);
dao.close();
// 10. 성공/실패 확인
if (result == 1) {
resp.sendRedirect("../board/list.board");
} else {
resp.sendRedirect("../board/write/board");
}
}
}
(3) JSFunction에 메서드 2개 추가
// Java Resources/src/utils/JSFunction.java
package utils;
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.jsp.JspWriter;
public class JSFunction {
... 생략 ...
// 메시지 알림창을 띄운 후 명시한 URL로 이동
public static void alertLocation(HttpServletResponse resp, String msg, String url) {
try {
resp.setContentType("text/html;charset=UTF-8");
PrintWriter writer = resp.getWriter();
String script = "<script>"
+ " alert('" + msg + "');"
+ " location.href='" + url + "';"
+ "</script>";
writer.print(script);
} catch (Exception e) {}
}
// 메시지 알림창을 띄운 후 이전 페이지로 돌아감
public static void alertBack(HttpServletResponse resp, String msg) {
try {
resp.setContentType("text/html;charset=UTF-8");
PrintWriter writer = resp.getWriter();
String script = "<script>"
+ " alert('" + msg + "');"
+ " history.back();"
+ "</script>";
writer.print(script);
} catch (Exception e) {}
}
}
7) 글쓰기 기능 최종 실행 결과
오류 해결 : web.xml에 오타가 있어서.. WriteController의 37번째줄의 매개변수명을 정상적으로 가져오지 못한 것이었다
java.lang.NumberFormatException: null
at java.base/java.lang.Integer.parseInt(Integer.java:614)
at java.base/java.lang.Integer.parseInt(Integer.java:770)
at mvcboard.WriteController.doPost(WriteController.java:37)
실행 성공!
2. 상세 보기(서블릿 매핑에 어노테이션 사용)
1) 모델 작성(DAO)
// Java Resources/src/mvcboard/MVCBoardDAO.java
package mvcboard;
... 임포트 생략 ...
public class MVCBoardDAO extends DBConnPool { // 커넥션 풀 상속
... 생략 ...
// 주어진 일련번호에 해당하는 게시물을 DTO에 담아 반환
public MVCBoardDTO selectView(String idx) {
// dto 객체 생성
MVCBoardDTO dto = new MVCBoardDTO();
// 쿼리문 템플릿 준비
String query = "SELECT * FROM mvcboard WHERE idx=?";
try {
psmt = con.prepareStatement(query); // 쿼리문 준비
psmt.setString(1, idx); // 인파라미터 설정
rs = psmt.executeQuery();
if (rs.next()) { // 결과를 DTO 객체에 저장
dto.setIdx(rs.getString(1));
dto.setName(rs.getString(2));
dto.setTitle(rs.getString(3));
dto.setContent(rs.getString(4));
dto.setPostdate(rs.getDate(5));
dto.setOfile(rs.getString(6));
dto.setSfile(rs.getString(7));
dto.setDowncount(rs.getInt(8));
dto.setPass(rs.getString(9));
dto.setVisitcount(rs.getInt(10));
}
} catch (Exception e) {
System.out.println("게시물 상세보기 중 예외 발생");
e.printStackTrace();
}
return dto; // 결과 반환
}
// 주어진 일련번호에 해당하는 게시물의 조회수를 1 증가시킴
public void updateVisitCount(String idx) {
String query = "UPDATE mvcboard SET"
+ "visitcount = visitcount+1"
+ "WHERE idx=?";
try {
psmt = con.prepareStatement(query);
psmt.setString(1, idx);
psmt.executeQuery();
} catch (Exception e) {
System.out.println("게시물 조회수 업데이트 중 예외 발생");
e.printStackTrace();
}
}
}
2) 컨트롤러 작성(WebServlet 어노테이션 사용)
// Java Resources/src/mvcboard/ViewController.java
package mvcboard;
... 임포트 생략 ...
// 어노테이션으로 요청명과 서블릿 매핑
@WebServlet("/board/view.board")
public class ViewController extends HttpServlet{
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
// 게시물 불러오기
MVCBoardDAO dao = new MVCBoardDAO(); // DAO 객체 생성
String idx = req.getParameter("idx"); // 게시물의 일련번호를 매개변수로 받기
dao.updateVisitCount(idx); // 조회수 1 증가
MVCBoardDTO dto = dao.selectView(idx); // 게시물 내용 가져오기(상세보기)
dao.close();
// 줄바꿈 처리(일반 텍스트 문서의 줄바꿈문자를 HTML이 인식)
dto.setContent(dto.getContent().replaceAll("\r\n", "<br>"));
// 게시물(DTO) 저장 후 뷰로 포워드
req.setAttribute("dto", dto); // DTO 객체를 request 영역에 저장
req.getRequestDispatcher("/board/View.jsp").forward(req, resp);
}
}
3) 뷰(JSP 파일) 작성
<!-- src/main/webapp/board/View.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>
<body>
<h2>파일 첨부형 게시판 - 상세 보기</h2>
<table border="1" width="90%">
<colgroup>
<col width="15%" /> <col width="35%" />
<col width="15%" /> <col width="*" />
</colgroup>
<!-- 게시글 정보 -->
<tr>
<td>번호</td><td>${ dto.idx }</td>
<td>작성자</td><td>${ dto.name }</td>
</tr>
<tr>
<td>작성일</td><td>${ dto.postdate }</td>
<td>조회수</td><td>${ dto.visitcount }</td>
</tr>
<tr>
<td>제목</td><td colspan="3">${ dto.title }</td>
</tr>
<tr>
<td>내용</td><td colspan="3" height="100">${ dto.content }</td>
</tr>
<!-- 첨부파일 -->
<tr>
<td>첨부파일</td>
<td>
<c:if test="${ not empty dto.ofile }">
${ dto.ofile }
<a href="../board/download.board?ofile=${ dto.ofile }&sfile=${ dto.sfile }&idx=${ dto.idx }">
[다운로드]
</a>
</c:if>
</td>
<td>다운로드수</td><td>${ dto.downcount }</td>
</tr>
<!-- 하단 메뉴(수정/삭제/목록으로 돌아가기 버튼) -->
<tr>
<td colspan="4" align="center">
<button type="button" onclick="location.href='../board/pass.board?model=edit&idx=${param.idx}';">
수정하기
</button>
<button type="button" onclick="location.href='../board/pass.board?model=delete&idx=${param.idx}';">
삭제하기
</button>
<button type="button" onclick="location.href='../board/list.board';">
목록으로 돌아가기
</button>
</td>
</tr>
</table>
</body>
</html>
4) Default.jsp 실행 후 동작 확인: 원하는 글의 제목을 클릭하면, 해당 글의 내용을 상세보기 페이지에서 볼 수 있음