벡엔드 웹프로그래밍/JSP

JSP 웹프로그래밍 62일차 (25/2/13)

wkun 2025. 2. 13. 17:58

contents

 

PART 03 페이지 처리 기법

chapter 07 파일 업로드: 도서 이미지 등록하기

01.파일 업로드의 개요

02.MultipartRequest를 이용한 파일 업로드

03.Commons-FileUPload를 이용한 파일 업로드

04.북마켓 도서 이미지 등록하기

 

 

------------------------------------------------

 

PART 03 페이지 처리 기법

 

chapter 07 파일 업로드: 도서 이미지 등록하기

 

01.파일 업로드의 개요

-파일 업로드(file upload)는 웹 브라우저에서 서버로 파일을 전송하여 서버에 저장하는 것을 말함. 서버로 업로드할 수 있는 파일에는 텍스츠 파일, 바이너리 파일, 이미지 파일, 문서 등 다양한 유형이 있음. 웹 브라우저에서 서버로 파일을 전송하기 위해 JSP 페이지에 폼 태그를 사용하고, 전송된 파일을 서버에 저장하기 위해 오픈 라이브러리를 이용해야 함

*문자열: 1.text 2.바이너리(010101)->숫자(2진수): 이미지 x n=> 영상

                                                                                실행파일: .exe

                                                                                                 .class 

 

1)파일 업로드를 위한 JSP 페이지

-웹 브라우저에서 서버로 파일을 전송하기 위해 JSP 페이지에 폼 태그를 작성할 때 몇 가지 중요한 규칙을 따라야 하며 그 형식은 다음과 같음

<form action="JSP 파일" method="POST" enctype="multipart/form-date">
       <input type="file" name="요청 파라미터 이름">
</form>

 

(1)form 태그의 method 속성은 반드시 POST 방식으로 설정해야 함

(2)form 태그의 enctype 속성은 반드시 multipart/form-data로 설정해야 함

(3)form 태그의 action 속성은 파일 업로드를 처리할 JSP 파일로 설정해야 함

(4)파일 업로드를 위해 input 태그의 type 속성을 file로 설정해야 함. 만약 여러 파일을 업로드하려면 2개 이상의 input 태그를 사용하고 name 속성에 서로 다른 값을 설정함

 

2)파일 업로드 처리 방법

-웹 브라우저에서 서버로 파일을 업로드하면 서버는 요청 파라미터를 분석하여 파일을 찾고 서버의 자원(파일 저장 폴더)에 저장하는 과정을 거침. 이러한 파일 업로드의 처리는 단순한 자바 코드로 작성하여 처리할 수 없어 다음과 같이 오픈 라이브러리인 cos.jar 또는 commonsfileupload.jar를 사용해야 함

 

파일 업로드 처리 방법

종류 특징 필요한 라이브러리
MultipartRequest 이용하기 가장 간단한 방법 cos.jar
아파치 API 이용하기 편리하고 강력한 API 제공 commons-fileupload.jar
commons-io.jar

*text+숫자 섞여있는 거 가져올 수 있는 방법: 둘 중 하나 써야함

 

◎JavaEE에서 JakartaEE로 마이그레이션하는 방법

-마이그레이션이란 데이터나 소프트웨어를 현행 시스템 환경에서 새로운 환경으로 시스템을 전환하는 것을 의미함. 그래서 톰캣 10전번을 사용할 경우 기존에 톰캣 9번전 이하에서 사용하던 라이브러리를 새로운 환경 시스템에 맞게 다음과 같이 마이그레이션해야 함

-톰캣 9와 톰캣 10은 API 구현체가 완전히 달라짐. 톰캣 9까지는 JavaEE가 적용되고, 톰캣 10부터는 JakartaEE가 적용됨. 서블릿 5.0은 JakartaEE부터 지원되므로, 해당 버전의 시블릿을 JavaEE로 구동하거나, 더 낮은 버전의 서블릿을 JakartaEE로 구동하면 서블릿이 정상적으로 동작하지 않아 404 오류가 발생함

  JavaEE JakartaEE
서블릿(Servlet) javax.servlet Jakarta.servlet
톰캣 버전 10.0버전 10.0 이후부터

 

-JavaEE와 JakartaEE는 자바 코드의 내부 로직이나 구조적으로 많은 것이 변경되었음. 대표적으로 직접 확인 할 수 있는 것은 패키지의 변경임. 따라서 Javax.*을 Jakarta.*로 변경하는 것만으로도 마이그레이션이 가능함

 

02.MultipartRequest를 이용한 파일 업로드

-MultipartRequest는 웹 페이지에서 서버로 업로드되는 파일 자체만 다루는 클래스임. 웹 브라우저가 전송한 Multipart/form-data 유형과 POST 방식의 요청 파라미터 등을 분석한 후 일반 데이터와 파일 데이터를 구분하여 파일 데이터에 접근함. 또한 한글 인코딩 값을 얻기 쉽고, 서버의 파일 저장 폴더에 동일한 파일명이 있으면 파일명을 자동으로 변경함

-MultipartRequest 클래스는 cos(com.oreilly.servlet) 패키지에 포함되어 있는 파일 업로드 컴포넌트로, 오픈 라이브러리 cos.jar를 다음 배포 사이트에서 직접 다운로드해서 사용함. 그리고 JSP 페이지에 page 디렉티브 태그의 import 속성을 사용하려 패키지 com.oreilly.servlet.*을 설정해야 함

*라이브러리에 직접 넣어야 함(자동x)

 

·배포 사이트: http://www.servlets.com/cos

·다운로드 파일: cos-22.05.zip

·설치방법: 압축 푼 파일의 lib 폴더에 있는 cos.jar 찾기 -> /src/main/webapp/WEB-INF/lib/ 폴더에 cos.jar 파일 포함

 

Servlets.com | com.oreilly.servlet

 

www.servlets.com

 

-MultipartRequest 클래스를 이용하여 파일을 업로드하려면 먼저 MultipartRequest 객체를 생성함. 그리고 생성된 객체를 통해 MultipartRequest 클래스가 제공하는 메소드를 사용하여 웹 브라우저가 전송한 Multipart/form-data 유형의 요청 파라미터를 읽어오고 파일을 업로드함

 

1)MultipartRequest 클래스 생성

-MultipartRequest 클래스는 다양한 생성자를 제공함. 그중에서 한글 인코딩 값을 쉽게 얻을 수 있고, 업로드되는 파일이 서버에 저장된 기존 파일과 중복될 때 자동으로 변경해주는 생성자의 형식은 다음과 같음

MultipartRequest(javax.servlet.http.HttpServletRequest request, java.lang.String saveDirectory, int maxPostSize, java.lang.String encodingFileRenamePolicy policy)

 

MultipartRequest  생성자의 매개변수

매개변수 설명
request Request 내장 객체를 설정함
saveDirectoty 서버의 파일 저장 경로를 설정함
maxPostSize 파일의 최대 크기(바이트 단위)를 설정함. 최대 크기를 초과하면 IOException이 발생함
encoding 인코딩 유형을 설정함
policy 파일명 변경 정책을 설정함. saveDirectory에 파일명이 중복되는 경우 덮어쓰기 여부를 설정하며, 설정하지 않으면 덮어씀

 

-다음은 MultipartRequest 클래스를 생성하는 예임. 웹 브라우저에서 전송되는 파일을 서버의 C:\upload\ 경로에 저장하며, 파일의 최대 크기는 5MB(5 X 1,024 X 1,024B)이고, 파일명의 인코딩 유형은 utf-8로 설정함. 또한 서버에 저장된 파일명 중복을 처리하기 위해 DefaultFileRenamePolicy 클래스를 사용함. 즉 DefaultFileRenamePolicy 클래스는 서버에 동일한 파일이 존재하면 웹 브라우저에서 전송된 파일명 뒤에 숫자를 덧붙여 파일명이 중복되지 않게 함. DefaultFileRenamePolicy 클래스를 사용하려면 JSP 페이지에 page 디렉티브 태그의 import 속성으로 패키지 com.oreilly.servlet.multipart.*를 설정해야 함

 

[MultipartRequest 클래스 생성 예]

<% page import="com.oreillyservlet.*" %>
<% page import="com.oreillyservlet.multipart*" %>
   ··· (생략) ···
MultipartRequest  multi=new MultipartRequest(request, "C:\\upload", 5*1024*1024, "utf-8", new DefaultFileRenamePolicy())

cf)5*1024kb*1024kb = 5MB

 

2)MultipartRequest 메소드

-웹 브라우저에서 전송한 multipart/form-data 유형의 요청 파라미터를 쉽게 읽어오고 파일을 업로드할 수 있도록 MultipartRequest 클래스에는 다양한 메소드가 있음. 웹 브라우저에서 전송되는 요청 파라미터 중 일반 데이터는 getParameter() 메소드로 값을 받을 수 있지만 파일의 경우 getFileNames() 메소드를 이용하여 데이터를 받음

 

MultipartRequest 메소드의 종류

메소드 유형 설명
getContentType(String name) String 업로드된 파일의 콘텐츠 유형을 반환함. 업로드된 파일이 없으면 null을 반환함
getParameter(String name) String 요청 피라미터 이름이 name인 값을 전달받음
getParameterNames() java.util.Enumeration 요청 피라미터 이름을 Enumeration 객체 타입으로 반환함
getFile(String name) java.io.File 서버에 업로드된 파일에 대한 파일 객체를 반환함. 업로드된 파일이 없으면 null을 반환함
getFileNames() java.util.Enumeration 폼 페이지에 input 태그 내 type 속성 값이 file로 설정된 요청 파라미터의 이름을 반환함
getFilesystemName(String name)
String 사용자가 설정하여 서버에 실제로 업로드된 파일명을 반환함. 파일명이 중복되면 변경된 파일명을 반환함
getOriginalFileName(String name)
String 사용자가 업로드한 실제 파일명을 반환함. 파일명이 중복되면 변경 전의 파일명을 반환함

 

예제 7-1.MultipartRequest 클래스를 이용하여 파일 업로드 및 정보 출력하기

JSPBook/src/main/webapp/ch07/fileupload01.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>File Upload</title>
</head>
<body>
<form name="fileForm" method="post" enctype="multipart/form-data" action="ch07_1">
<p> 이 름 : <input type="text" name="name">
<p> 제 목 : <input type="text" name="subject">
<p> 파 일 : <input type="file" name="filename">
<p> <input type="submit" value="전송">
</form>
</body>
</html>

 

ch07_1_controller.java

package controller.ch07;


import java.io.File;
import java.io.IOException;
import java.util.Enumeration;


import com.oreilly.servlet.MultipartRequest;
import com.oreilly.servlet.multipart.DefaultFileRenamePolicy;


import jakarta.servlet.RequestDispatcher;
import jakarta.servlet.ServletException;
import jakarta.servlet.annotation.WebServlet;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;


@WebServlet("/ch07_1")
public class ch07_1_controller extends HttpServlet{


@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {


RequestDispatcher ds = req.getRequestDispatcher("ch07/fileupload01.jsp");
ds.forward(req, resp);
}


@Override
protected void doPost(HttpServletRequest request, HttpServletResponse resp) throws ServletException, IOException {
//멀티파츠리퀘스트 객체를 생성 : WEB-INF>lib폴더에 라이브러리 확보 여부 중요(jar: 자바 아카이브 압축파일: class설계도)
String save = request.getServletContext().getRealPath("resources/images"); //JSPBook 서버 주소 경로
System.out.println(save);
MultipartRequest multi = new MultipartRequest(request, save, 5*1024*1024, "utf-8", new DefaultFileRenamePolicy());

//텍스트 가져오기 : key(HTML 태그의 name 속성)를 알 때

String name1 = multi.getParameter("name");
String subject1 = multi.getParameter("subject");
System.out.println(name1);
System.out.println(subject1);

//텍스트 가져오기 : key(HTML 태그의 name 속성)를 모를 때
/*
Enumeration en = multi.getParameterNames();
while(en.hasMoreElements()) {
String name2 = (String) en.nextElement();
String value = multi.getParameter(name2);
System.out.println(name2 + ":" + value);
}
*/
//이미지 정보 가져오기 : key(HTML 태그의 name 속성)를 알 때

String sysname = multi.getFilesystemName("filename");
String oriname = multi.getOriginalFileName("filename");
String type = multi.getContentType("filename");
File file = multi.getFile("filename");
System.out.println(sysname);
System.out.println(oriname);
System.out.println(type);
System.out.println(file);

//이미지 정보 가져오기 : key(HTML 태그의 name 속성)를 모를 때
/*
Enumeration en2 = multi.getFileNames();
while(en2.hasMoreElements()) {
String key = (String) en2.nextElement();
String sysname2 = multi.getFilesystemName(key);
String oriname2 = multi.getOriginalFileName(key);
String type2 = multi.getContentType(key);
File file2 = multi.getFile(key);
System.out.println(key);
System.out.println(sysname2);
System.out.println(oriname2);
System.out.println(type2);
System.out.println(file2);
}
*/

}


}

*알 때/ 모를 때 따로 실행하기

 

실행 결과

1)알 때

D:\SaveLocation\jsp\.metadata\.plugins\org.eclipse.wst.server.core\tmp0\wtpwebapps\JSPBook\resources\images
홍길순
펭귄
pengun.jpg
pengun.jpg
image/jpeg
D:\SaveLocation\jsp\.metadata\.plugins\org.eclipse.wst.server.core\tmp0\wtpwebapps\JSPBook\resources\images\pengun.jpg

 

2)모를 때

D:\SaveLocation\jsp\.metadata\.plugins\org.eclipse.wst.server.core\tmp0\wtpwebapps\JSPBook\resources\images
name:홍길순
subject:펭귄
filename
pengun.jpg
pengun.jpg
image/jpeg
D:\SaveLocation\jsp\.metadata\.plugins\org.eclipse.wst.server.core\tmp0\wtpwebapps\JSPBook\resources\images\pengun.jpg

 

예제 7-2.MultipartRequest 클래스를 이용하여 여러 파일 업로드 및 정보 출력하기

JSPBook/src/main/webapp/ch07/fileupload02.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<form name="fileForm" method="post" enctype="multipart/form-data" action="ch07_2">
<p> 이 름1 : <input type="text" name="name1">
제 목1 : <input type="text" name="subject1">
파 일1 : <input type="file" name="filename1">
<p> 이 름2 : <input type="text" name="name2">
제 목2 : <input type="text" name="subject2">
파 일2 : <input type="file" name="filename2">
<p> 이 름3 : <input type="text" name="name3">
제 목3 : <input type="text" name="subject3">
파 일3 : <input type="file" name="filename3">
<p> <input type="submit" value="파일 올리기">
</form>
</body>
</html>

 

ch07_2_controller.java

package controller.ch07;


import java.io.IOException;


import com.oreilly.servlet.MultipartRequest;
import com.oreilly.servlet.multipart.DefaultFileRenamePolicy;


import jakarta.servlet.RequestDispatcher;
import jakarta.servlet.ServletException;
import jakarta.servlet.annotation.WebServlet;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;


@WebServlet("/ch07_2")
public class ch07_2_controller extends HttpServlet{


@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

RequestDispatcher ds = req.getRequestDispatcher("ch07/fileupload02.jsp");
ds.forward(req, resp);
}


@Override
protected void doPost(HttpServletRequest request, HttpServletResponse resp) throws ServletException, IOException {
String save = request.getServletContext().getRealPath("resources/images"); //JSPBook 서버 주소 경로
System.out.println(save);
MultipartRequest multi = new MultipartRequest(request, save, 5*1024*1024, "utf-8", new DefaultFileRenamePolicy());

String name1 = multi.getParameter("name1");
String subject1 = multi.getParameter("subject1");

String name2 = multi.getParameter("name2");
String subject2 = multi.getParameter("subject2");

String name3 = multi.getParameter("name3");
String subject3 = multi.getParameter("subject3");

String filename1 = multi.getFilesystemName("filename1");
String filename2 = multi.getFilesystemName("filename2");
String filename3 = multi.getFilesystemName("filename3");

System.out.println(name1);
System.out.println(subject1);
System.out.println(name2);
System.out.println(subject2);
System.out.println(name3);
System.out.println(subject3);
System.out.println(filename1);
System.out.println(filename2);
System.out.println(filename3);

}


}

 

실행 결과

D:\SaveLocation\jsp\.metadata\.plugins\org.eclipse.wst.server.core\tmp0\wtpwebapps\JSPBook\resources\images
홍길순
튤립
홍길동
펭귄
수여인
하늘
flower.jpg
pengun.jpg
sky_blue.jpg

 

 

03.Commons-FileUpload를 이용한 파일 업로드

-파일 업로드 패키지인 Commons-FileUpload는 서버의 메모리상에서 파일 처리가 가능하도록 지원함. 이 패키지는 Commons-io 패키지를 바탕으로 작성되었기 때문에 웹 브라우저에서 서버로 파일을 업로드하기 위해 오픈 라이브러리 Commons-FileUpload.jar, Commons-io.jar 파일을 다음 배포 사이트에서 직접 다운로드해서 사용함. 그리고 JSP 페이지에 page 디렉티브 태그의 import 속성을 사용하여 패키지 org.apache.commoms.fileupload.*를 설정해야 함

 

·배포 사이트: http://commons.apache.org/downloads

·다운로드 파일: commons-fileupload-1.5.bin.zip, commons-io-2.13.0-bin.zip

 

-(1)Commons-FileUpload를 이용하여 파일을 업로드하려면 먼저 Commons-FileUpload 패키지에 포함되어 있는 DiskFileUpload 객체를 생성함 (2)생성된 객체를 통해 DiskFileUpload 클래스가 제공하는 메소드를 사용하여 웹 브라우저가 전송한 multipart/form-data 유형의 요청 파라미터를 가져옴 (3)FileItem 클래스의 메소드를 사용하여 요청 파라미터가 일반 데이터인지 파일인지 분석 및 처리하여 파일을 업로드함

 

DiskFileUpload 클래스의 메소드

메소드 유형 설명
setRepositoryPath(String repositotyPath) void 업로드된 파일을 임시로 저장할 디렉터리를 설정함
setSizeMax(long sizeMax) void 최대 파일의 크기를 설정함
setSizeThreshold(int sizeThreshold) void 메모리상에 저장할 최대 크기를 설정함
parseRequest(HttpServletRequest reg) List<FileItem> multipart/form-data 유형의 요청 파라미터를 가져옴

 

FileItem 클래스의 메소드

메소드 유형 설명
isFormField() boolean 요청 파라미터가 파일이 아니라 일반 데이터인 경우 true를 반환함
getFieldName() String 요청 파라미터의 이름을 얻어옴
getString() String 기본 문자 인코딩을 사용하여 요청 파라미터의 값을 얻어 옴
getString(String encoding) String 설정한 문자 인코딩을 사용하여 요청 파라미터의 값을 얻어 옴
getName() String 업로드된 파일(경로 포함)의 이름을 얻어옴
getSize() long 업로드된 파일의 크기를 얻어옴
get() byte[] 업로드된 파일을 바이트 배열로 얻어옴
isInMemory boolean 업로드된 파일이 메모리에 저장된 상태인 경우 true를 반환하고, 임시 디렉터리에 저장된 경우 false를 반환함
delete() void 파일과 관련된 자원을 삭제함. 메모리상에 저장된 경우 할당된 메모리를 반환하고, 임시 파일로 저장된 경우 파일을 삭제함
write() void 파일과 관련된 자원을 저장함
getContentType() String 웹 브라우저가 전송하는 콘텐츠 유형을 반환하고, 정의되어 있지 않은 경우 null을 반환함

 

FileItem 클래스로 업로드 파일을 저장하는 방법

(1)write() 메소드를 사용함

(2)getInputStream() 메소드로 입력 스트림으로부터 바이트 데이터를 가져와 FileOutputStream()을 사용하여 파일에 풀력함

(3)get() 메소드로 가져온 바이트 배열을 FileOutputStream을 사용하여 파일에 출력함

-write() 메소드는 주로 로컬 디스크에 직접 업로드한 파일을 저장할 때 사용하고, getInputStream()이나 get() 메소드는 업로드한 파일에 특별한 처리를 하거나 데이터베이스와 같이 디스크가 아닌 영역에 업로드한 파일을 저장할 때 사용함

 

예제 7-3.Commons-FileUpload를 이용하여 파일 업로드하기

JSPBook/src/main/webapp/ch07/fileupload03.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>File Upload</title>
</head>
<body>
<form action="ch07_3" method="post" enctype="multipart/form-data">
<p> 파 일 : <input type="file" name="filename">
<p> <input type="submit" value="파일 올리기">
</form>
</body>
</html>

 

ch07_3_controller.java

package controller.ch07;


import java.io.File;
import java.io.IOException;
import java.util.Iterator;
import java.util.List;


import org.apache.commons.fileupload.DiskFileUpload;
import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileUploadException;


import com.oreilly.servlet.MultipartRequest;
import com.oreilly.servlet.multipart.DefaultFileRenamePolicy;


import jakarta.servlet.RequestDispatcher;
import jakarta.servlet.ServletException;
import jakarta.servlet.annotation.WebServlet;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;


@WebServlet("/ch07_3")
public class ch07_3_controller extends HttpServlet {


@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {


RequestDispatcher ds = req.getRequestDispatcher("ch07/fileupload03.jsp");
ds.forward(req, resp);
}

@Override
protected void doPost(HttpServletRequest requset, HttpServletResponse resp) throws ServletException, IOException {
String fileUploadPath = requset.getServletContext().getRealPath("resources/images"); // JSPBook 서버 주소 경로


System.out.println(fileUploadPath);


DiskFileUpload upload = new DiskFileUpload();
List items = null;
Iterator params = null;
try {
items = upload.parseRequest(requset); //Request-> List 객체 바꿈: text, img
params = items.iterator(); //이터레이터 주소주세요.
} catch (FileUploadException e) {
e.printStackTrace();
}
while (params.hasNext()) {
FileItem fileItem = (FileItem) params.next(); //next 반환: fileItem에 담기
if (!fileItem.isFormField()) { //~인지 아닌지
String fileName = fileItem.getName(); //이름 생성
fileName = fileName.substring(fileName.lastIndexOf("\\") + 1); //이름 생성
File file = new File(fileUploadPath + "/" + fileName); //파일 생성
try {
fileItem.write(file); //내용 삽입
} catch (Exception e) {
e.printStackTrace();
}


}else {
String filedName = fileItem.getFieldName(); //key
String fileName = fileItem.getString("utf-8"); //value

}
}


}


}

 

실행 결과

 

04.북마켓 도서 이미지 등록하기

-파일 업로드 처리 방법을 이용하여 도서 이미지를 등록할 수 있는 폼 페이지를 만들고 도서 이미지를 업로드하여 도서 이미지를 출력함

 

예제7-5.정적 리소스(도서 이미지 및 부트스트랩 CSS) 관리하기

BookMarket/src/main/java/dto/Book.java

1)도서 클래스에 멤버 변수 추가하기

package dto;


import java.io.Serializable;


public class Book implements Serializable{

private static final long serialVersionUID=-4274700572038677000L;

private String bookId; //도서 ID
private String name; //도서명
private int unitPrice; //가격
private String Author; //저자
private String description; //설명
private String publisher; //출판사
private String category; //분류
private long unitsInStock; //재고개수
private String releaseDate; //출판일(월/년)
private String condition; //신제품 or 구제품 or 리퍼브제품

-------------------------- 추가 -------------------------------

private String filename; //이미지 파일명

 

2)추가된 멤버 변수의 Setter/Getter() 메소드 작성하기

public Book() {
super();
}


public Book(String bookId, String name, int unitPrice) {
super();
this.bookId = bookId;
this.name = name;
this.unitPrice = unitPrice;
}


public String getBookId() {
return bookId;
}


public void setBookId(String bookId) {
this.bookId = bookId;
}


public String getName() {
return name;
}


public void setName(String name) {
this.name = name;
}


public int getUnitPrice() {
return unitPrice;
}


public void setUnitPrice(int unitPrice) {
this.unitPrice = unitPrice;
}



public String getAuthor() {
return Author;
}


public void setAuthor(String author) {
Author = author;
}


public String getDescription() {
return description;
}


public void setDescription(String description) {
this.description = description;
}


public String getPublisher() {
return publisher;
}


public void setPublisher(String publisher) {
this.publisher = publisher;
}


public String getCategory() {
return category;
}


public void setCategory(String category) {
this.category = category;
}


public long getUnitsInStock() {
return unitsInStock;
}


public void setUnitsInStock(long unitsInStock) {
this.unitsInStock = unitsInStock;
}


public String getReleaseDate() {
return releaseDate;
}


public void setReleaseDate(String releaseDate) {
this.releaseDate = releaseDate;
}


public String getCondition() {
return condition;
}


public void setCondition(String condition) {
this.condition = condition;
}


public static long getSerialversionuid() {
return serialVersionUID;
}

-------------------------- 추가 -------------------------------

public String getFilename() {
return filename;
}

public void setFilename(String filename) {
this.filename = filename;
}


}

 

3)도서 데이터 접근 클래스 수정하기(확장자(이미지)추가)

BookMarket/src/main/java/dao/BookRepository.java

package dao;


import dto.Book;
import java.util.ArrayList;


public class BookRepository {


private ArrayList<Book> listOfBooks = new ArrayList<Book>();
private static BookRepository instance = new BookRepository(); //싱글톤

public static BookRepository getInstance() {
return instance;
}


public BookRepository() {

// System.out.println("BookRepository 객체가 생성됨");

Book book1 = new Book("ISBN1234", "C# 프로그래밍", 27000);
book1.setAuthor("우재남");
book1.setDescription(
"C#을 처음 접하는 독자를 대상으로 일대일 수업처럼 자세히 설명한 책이다. 꼭 알아야 할 핵심 개념은 기본 예제로 최대한 쉽게 설명했으며, 중요한 내용은 응용 예제, 퀴즈, 셀프 스터디, 예제 모음으로 한번 더 복습할 수 있다.");
book1.setPublisher("한빛아카데미");
book1.setCategory("IT모바일");
book1.setUnitsInStock(1000);
book1.setReleaseDate("2022/10/06");
-------------------------- 추가 -------------------------------
book1.setFilename("ISBN1234.jpg");


Book book2 = new Book("ISBN1235", "자바마스터", 30000);
book2.setAuthor("송미영");
book2.setDescription(
"자바를 처음 배우는 학생을 위해 자바의 기본 개념과 실습 예제를 그림을 이용하여 쉽게 설명합니다. 자바의 이론적 개념→기본 예제→프로젝트 순으로 단계별 학습이 가능하며, 각 챕터의 프로젝트를 실습하면서 온라인 서점을 완성할 수 있도록 구성하였습니다.");
book2.setPublisher("한빛아카데미");
book2.setCategory("IT모바일");
book2.setUnitsInStock(1000);
book2.setReleaseDate("2023/01/01");
book2.setFilename("ISBN1235.jpg");


Book book3 = new Book("ISBN1236", "파이썬 프로그래밍", 30000);
book3.setAuthor("최성철");
book3.setDescription(
"파이썬으로 프로그래밍을 시작하는 입문자가 쉽게 이해할 수 있도록 기본 개념을 상세하게 설명하며, 다양한 예제를 제시합니다. 또한 프로그래밍의 기초 원리를 이해하면서 파이썬으로 데이터를 처리하는 기법도 배웁니다.");
book3.setPublisher("한빛아카데미");
book3.setCategory("IT모바일");
book3.setUnitsInStock(1000);
book3.setReleaseDate("2023/01/01");
book3.setFilename("ISBN1236.jpg");

listOfBooks.add(book1);
listOfBooks.add(book2);
listOfBooks.add(book3);


}


public ArrayList<Book> getAllBooks() {
return listOfBooks;
}

public Book getBookById(String bookId) {
Book bookById=null;

for(int i=0; i<listOfBooks.size(); i++) {
Book book=listOfBooks.get(i);
if(book!=null && book.getBookId()!=null && book.getBookId().equals(bookId)) {
bookById=book;
break;
}
}
return bookById;
}


public void addBook(Book book) { //DTO
listOfBooks.add(book);
}


}

 

4)정적 리소스 관리 폴더 만들기

-/scr/main/webapp/ 폴더에 resources 폴더를 생성하고, 여기에 이미지 파일을 관리하는 images 폴더와 부트스트랩 파일(bootstrap.css)을 관리하는 css 폴더를 생성함

-images 폴더에 이미지 파일명을 도서 아이디로 하여 등록함

-css 폴더에 부트스트랩 CSS 파일(bootstrap.min.css)을 다운로드하여 등록함

 

 

◎부트스트랩 CSS 파일 설치 방법

(1)배포 사이트(http://getbootstrap.com/)에서 bootstrap-5.3.0-dist.zip 파일을 다운로드함

(2)bootstrap-5.3.0-dist.zip 파일의 압축을 품

(3)압축을 푼 파일의 css 폴더에 있는 bootstrap.min.css 파일을 찾음

(4)웹 애플리케이션의 /src/main/webapp/resources/css/ 폴더에 bootstrap.min.css 파일을 포함함

 

5)도서 목록 페이지 수정하기

BookMarket/src/main/webapp/books.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ page import="java.util.ArrayList" %>
<%@ page import="dto.Book" %>
<%@ page import="dao.BookRepository" %>
<!-- BookRepository bookDAO = new BookRepository() -->
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<script src="https://kit.fontawesome.com/fa848000d2.js" crossorigin="anonymous"></script>
-------------------------- 추가 -------------------------------

<link rel ="stylesheet" href ="./resources/css/bootstrap.min.css" />
<title>도서 목록</title>
</head>
<body>
<div class="container py-4">
<%@ include file="menu.jsp" %>
<div class="p-5 mb-4 bg-body-tertiary rounded-3">
<div class="container-fluid py-5">
<h1 class="display-5 fw-bold">도서목록</h1>
<p class="col=md-8 fs-4">BookList</p>
</div>
</div>
<%
BookRepository dao=BookRepository.getInstance();
ArrayList<Book> listOfBooks = dao.getAllBooks();
%>

<div class="row align-items-md-stretch text-center">
<%
for(int i=0; i<listOfBooks.size(); i++){
Book book=listOfBooks.get(i);

%>
<div class="col-md-4">
<div class="h-100 p-2 round-3">
-------------------------- 추가 -------------------------------

<img src="./resources/images/<%=book.getFilename()%>" style="width: 250px; height:350px" />
<p><h5><b><%=book.getName() %></b></h5>
<p> <%=book.getAuthor() %>
<br><%=book.getPublisher() %> : <%=book.getUnitPrice() %>
<p> <%=book.getDescription() %>
<p><%=book.getUnitPrice() %>
<p> <a href="./book.jsp?id=<%=book.getBookId() %>" class="btn btn-secondary" role="button">상세 정보 &raquo;</a>
</div>
</div>
<%
}
%>
</div>
<%@ include file="footer.jsp" %>
</div>
</body>
</html>

*style에 px 안쓰면 이미지 크기 안 먹힘

 

6)도서 상세 정보 페이지 수정하기

BookMarket/src/main/webapp/book.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ page import="dto.Book" %>
<%@ page import="dao.BookRepository" %>



<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<script src="https://kit.fontawesome.com/fa848000d2.js" crossorigin="anonymous"></script>
-------------------------- 추가 -------------------------------

<link rel ="stylesheet" href ="./resources/css/bootstrap.min.css" />


<title>도서 상세 정보</title>
</head>
<body>
<div class="container py-4">
<%@ include file="menu.jsp" %>

<div class="p-5 mb-4 bg-body-tertiary rounded-3">
<div class="container-fluid py-5">
<h1 class="display-5 fw-bold">도서정보</h1>
<p class="col-md-8 fs-4">BookInfo</p>
</div>
</div>

<%
String id=request.getParameter("id");
BookRepository dao=BookRepository.getInstance();
Book book=dao.getBookById(id);
%>

<div class="row align-items-md-stretch">
-------------------------- 추가 -------------------------------

<div class="col-md-5">
<img src="./resources/images/<%=book.getFilename() %>" style="width : 70%">
</div>
<div class="col-md-12">
<h3><b><%=book.getName() %></b></h3>
<p> <%=book.getDescription() %>
<p> <b>도서코드 : </b><span class="badge text-bg-danger">
<%= book.getBookId()%></span>
<p> <b>저자</b> : <%=book.getAuthor() %>
<p> <b>출판사</b> : <%=book.getPublisher() %>
<p> <b>출판일</b> : <%=book.getReleaseDate() %>
<p> <b>분류</b> : <%=book.getCategory() %>
<p> <b>재고수</b> : <%=book.getUnitsInStock() %>
<h4><%=book.getUnitPrice() %></h4>
<p> <a href="#" class="btn btn-info">도서주문 &raquo;</a>
<a href=" ./books.jsp" class="btn btn-secondary" >도서 목록 &raquo;</a>
</div>
</div>
<jsp:include page="footer.jsp" />
</div>
</body>
</html>

 

예제 7-6.도서 이미지 업로드 하기

1)오픈 라이브러리 cos.jar 등록하기

-MultipartRequest 클래스를 이용한 파일 업로드를 위해 /src/main/webapp/WEB-INF/lib/ 폴더에 cos.jar 파일을 등록함

*cos.jar 파일은 톰캣 10버전에서 사용할 수 있도록 마이그레이션해야 함

 

2)도서 정보 등록 페이지 수정하기

BookMarket/src/main/webapp/addBook.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<script src="https://kit.fontawesome.com/fa848000d2.js" crossorigin="anonymous"></script>
-------------------------- 추가 -------------------------------

<link rel ="stylesheet" href ="./resources/css/bootstrap.min.css" />
<title>도서 등록</title>
</head>
<body>
<div class="container py-4">
<%@ include file="menu.jsp"%>


<div class="p-5 mb-4 bg-body-tertiary rounded-3">
<div class="container-fluid py-5">
<h1 class="display-5 fw-bold">도서 등록</h1>
<p class="col-md-8 fs-4">Book Addition</p>
</div>
</div>


<div class="row align-items-md-stretch">
-------------------------- 추가 -------------------------------

<form name="newBook" action="./processAddBook.jsp" class="form-horizontal" method="post" enctype="multipart/form-data">
<div class="mb-3 row">
<label class="col-sm-2">도서코드</label>
<div class="col-sm-3">
<input type="text" name="bookId" class="form-control">
</div>
</div>
<div class="mb-3 row">
<label class="col-sm-2">도서명</label>
<div class="col-sm-3">
<input type="text" name="name" class="form-control">
</div>
</div>
<div class="mb-3 row">
<label class="col-sm-2">가격</label>
<div class="col-sm-3">
<input type="text" name="unitPrice" class="form-control">
</div>
</div>
<div class="mb-3 row">
<label class="col-sm-2">저자</label>
<div class="col-sm-3">
<input type="text" name="author" class="form-control">
</div>
</div>
<div class="mb-3 row">
<label class="col-sm-2">출판사</label>
<div class="col-sm-3">
<input type="text" name="publisher" class="form-control">
</div>
</div>
<div class="mb-3 row">
<label class="col-sm-2">출판일</label>
<div class="col-sm-3">
<input type="text" name="releaseDate" class="form-control">
</div>
</div>


<div class="mb-3 row">
<label class="col-sm-2">상세정보</label>
<div class="col-sm-5">
<textarea name="description" cols="50" rows="2"
class="form-control" placeholder="100자 이상 적어주세요"></textarea>
</div>
</div>
<div class="mb-3 row">
<label class="col-sm-2">분류</label>
<div class="col-sm-3">
<input type="text" name="category" class="form-control">
</div>
</div>
<div class="mb-3 row">
<label class="col-sm-2">재고수</label>
<div class="col-sm-3">
<input type="text" name="unitsInStock" class="form-control">
</div>
</div>
<div class="mb-3 row">
<label class="col-sm-2">상태</label>
<div class="col-sm-5">
<input type="radio" name="condition" value="New"> 신규도서 <input
type="radio" name="condition" value="Old"> 중고도서 <input
type="radio" name="condition" value="EBook"> E-Book
</div>
</div>
-------------------------- 추가 -------------------------------

<div class="mb-3 row">
<label class="col-sm-2">이미지</label>
<div class="col-sm-5">
<input type="file" name="BookImage" class="form-control">
</div>
</div>
<div class="mb-3 row">
<div class="col-sm-offset-2 col-sm-10">
<input type="submit" class="btn btn-primary" value="등록">
</div>
</div>
</form>
</div>
<jsp:include page="footer.jsp" />
</div>
</body>
</html>

 

3)도서 등록 처리 페이지 수정하기

BookMarket/src/main/webapp/processAddBook.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ page import="dto.Book" %>
<%@ page import="dao.BookRepository" %>
-------------------------- 추가 -------------------------------

<%@ page import="com.oreilly.servlet.*" %>
<%@ page import="com.oreilly.servlet.multipart.*" %>
<%@ page import="java.util.*" %>


<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>


<%
request.setCharacterEncoding("UTF-8");

-------------------------- 추가 -------------------------------

String realFolder=request.getServletContext().getRealPath("resources/images");
int maxSize=5 * 1024 * 1024; //최대 업로드될 파일의 크기 5MB
String encType="utf-8"; //인코딩 유형

MultipartRequest multi=new MultipartRequest(request, realFolder, maxSize, encType, new DefaultFileRenamePolicy());




String bookId=multi.getParameter("bookId");
String name=multi.getParameter("name");
String unitPrice=multi.getParameter("unitPrice");
String author=multi.getParameter("author");
String publisher=multi.getParameter("publisher");
String releaseDate=multi.getParameter("releaseDate");
String description=multi.getParameter("description");
String category=multi.getParameter("category");
String unitsInStock=multi.getParameter("unitsInStock");
String condition=multi.getParameter("condition");
-------------------------- 추가 -------------------------------
String fileName=multi.getFilesystemName("BookImage");

System.out.println(bookId);
System.out.println(name);
System.out.println(unitPrice);
System.out.println(publisher);
System.out.println(releaseDate);
System.out.println(description);
System.out.println(category);
System.out.println(unitsInStock);
System.out.println(condition);
System.out.println(fileName);

Integer price;

if(unitPrice.isEmpty())
price=0;
else
price=Integer.valueOf(unitPrice);

long stock;

if(unitsInStock.isEmpty())
stock=0;
else
stock=Long.valueOf(unitsInStock);

BookRepository dao=BookRepository.getInstance();

Book newBook=new Book();
newBook.setBookId(bookId);
newBook.setName(name);
newBook.setUnitPrice(price);
newBook.setAuthor(author);
newBook.setPublisher(publisher);
newBook.setReleaseDate(releaseDate);
newBook.setDescription(description);
newBook.setCategory(category);
newBook.setUnitsInStock(stock);
newBook.setCondition(condition);
-------------------------- 추가 -------------------------------

newBook.setFilename(fileName);

dao.addBook(newBook);

response.sendRedirect("books.jsp");

%>


</body>
</html>

*setParameter("")를 multi.getParameter("");로 변경