kh day 083
이번주 공지사항
가. Servlet/JSP : 오늘 Servlet 종료, 곧바로 JSP 기본/고급 완료예정 (수요일까지)
나. 스프링의 선행요소 기술 학습:
-DB처리를 위한 MyBatis SQL Mapper Framework 완료예정
- 배치처리를 위한 Quartz Job Scheduler Framework 완료예정
다. 스프링 MVC 프레임워크 시작 :
- spring-core, spring-context, spring-webmvc, spring-jdbc, spring-tx, spring-websocket
동시에 Final Project에 박차를 가해주시기 자랍니다.
가. UX/UI 스토리보드 작성
나. 관계형 데이터 모델링 => 3NF까지 완료된 테이블 생성 => Dummy 데이터 생성
---
*파일 업로드
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>FileUpload 실습</title>
</head>
<body>
<h1>/resources/uploadForm.html</h1>
<hr>
<!-- 파일업로드 태그가 포함된 Form은, 반드시 enctype 속성의 값으로 아래와 같이 지정해야함 (표준) -->
<form action="/Upload" method="post" enctype="multipart/form-data">
1. 작성자 : <input type="text" name="writer"><br><br>
2. 업로드 파일 : <input type="file" name="uploadFile" multiple>
<br><br>
<input type="submit" value="업로드">
</form>
</body>
</html>
uploadForm.html
@Log4j2
@NoArgsConstructor
@MultipartConfig(
location="C:/temp/upload",
maxFileSize=1 * 1024 * 1024 * 2, // 최대 파일 크기 : 2MB
maxRequestSize=1 * 1024 * 1024 * 2) // 한 요청당 최대크기 : 2MB
@WebServlet("/Upload")
public class UploadServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
@Override
protected void service(HttpServletRequest req, HttpServletResponse res)
throws ServletException, IOException {
log.trace("service(req, res) invoked.");
// 응답 메시지 생성 및 전송
req.setCharacterEncoding("utf8");
res.setContentType("text/html; charset=utf8");
@Cleanup
PrintWriter out = res.getWriter();
// multiple 속성이 있는 <input type=file multiple> 태그로 업로드 된 복수의 파일을 저장하는 로직
Collection<Part> parts = req.getParts();
// parts.forEach( p -> log.info(p) );
parts.forEach( p -> log.info( p.getName() ) );
// 멀티파트를 구성하는 각 Part의 이름이란? => 각 파트를 구성하는 전송 파라미터의 이름
// Part uploadFilePart = req.getPart("uploadFile");
// log.info("uploadFile : {}", uploadFilePart);
// 각 파트의 구성 헤더 정보에 접근해보자
Iterator<Part> iter = parts.iterator();
while(iter.hasNext()) { // 그 다음 요소가 있느냐?
Part part = iter.next(); // 있다면 그 다음 요소를 달라!
// 이 Part에 포함된
log.info("========================================");
log.info("\t+ 1. part.getName : {}", part.getName()); // 전송 파라미터 이름 (=파트이름)
log.info("\t+ 2. part.getContentType : {}", part.getContentType()); // Content-Type 헤더의 값
log.info("\t+ 3. part.getSize : {}", part.getSize()); // Body의 Content Length
log.info("\t+ 4. part.getSubmittedFileName : {}", part.getSubmittedFileName()); // 파일의 원본 파일명
log.info("\t+ 5. part.getHeaderNames : {}", part.getHeaderNames()); // 헤더명의 목록
// 첨부파일만 포함하고 있는 Part를 필터링해서 첨부파일 저장
if( part.getSubmittedFileName() != null ) {
// part.write(part.getSubmittedFileName()); // 원본파일명으로 지정된 폴더에 저장
// 근데 실제 서비스에선 이렇게 하면 원본파일명이 겹치는 사용자가 있기 때문에 문제가 생김
try {
String uuid = UUIDGenerator.generateUniqueKeysWithUUIDAndMessageDigest();
part.write(uuid); // 파일명 임시파일처럼 저장
part.delete(); // 다운로드시 사용된 임시파일 삭제
// 응답으로 각 파일의 다운로드 링크 생성
String encodedFilename = URLEncoder.encode(part.getSubmittedFileName(), "utf8");
String link = String.format("<a href='/FileDown?file_name=%s&uuid=%s'> 파일 다운로드 </a><br>", encodedFilename, uuid);
out.println(link);
} catch (Exception e) {;;}
} // if
} //while
out.flush();
}// service
} // end class
UploadServlet.java
---
*파일 다운로드
@Log4j2
@NoArgsConstructor
@WebServlet("/FileDown")
public class FileDownServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
@Override
protected void service(HttpServletRequest req, HttpServletResponse res)
throws ServletException, IOException {
log.trace("service(req, res) invoked.");
req.setCharacterEncoding("utf8");
// step1. 다운로드에 필요한 전송 파라미터 획득
String file_name = req.getParameter("file_name");
String uuid = req.getParameter("uuid");
log.info("\t+ 1. file_name : {}", file_name); // 원본파일명
log.info("\t+ 2. uuid : {}", uuid); // 저장파일명
// step2. 저장파일명을 이용해서, 파일데이터를 응답메시지의 Body에 Write.
String path = "C:/temp/upload/" + uuid; // 저장파일에 대한 절대경로
@Cleanup
FileInputStream fis = new FileInputStream(path);
// step3. 다운로드할 대상 파일의 Mime Type 획득
ServletContext sc = req.getServletContext();
String mimeType = sc.getMimeType(file_name);
if (mimeType == null) {
mimeType = "application/octet-stream";
} // if
// step4. 응답문서의 Content Type 헤더의 값을 Mime Type으로 지정 (***)
res.setContentType(mimeType);
// step5. 응답문서의 헤더영역에 아래의 새로운 헤더 추가 (***)
// Content-Disposition : attachment; filename=원본파일명
// 주의할 점 : 원본파일명은 ASCII (ISO-8859-1) 문자집합으로 인코딩해서 넣어야 함.
String encodedFN = new String(file_name.getBytes("utf8"), "ISO-8859-1");
res.setHeader("Content-Disposition", "attachment; filename=" + encodedFN );
// step6. 저장파일명(uuid)을 이용하여, 파일데이터를 읽어 응답메시지 body에 write & send
byte [] bagagi = new byte[100]; // 바가지 준비
int readBytes = 0; // 실제 한번 바가지로 읽어낸 바이트 수를 저장
// 응답메시지의 body에 바이트 기반 출력스트림을 획득
@Cleanup
ServletOutputStream sos = res.getOutputStream();
while ((readBytes = fis.read(bagagi)) != -1) { // -1 : EOF (End Of File)
sos.write(bagagi, 0, readBytes);
} // while
sos.flush();
}// service
} // end class
FileDownServlet.java
---
이제 JSP 들어갑니다
*
Servlet : Buisness Logic 수행 및 데이터 생산
JSP : 응답화면 만드는 것 (HTML 문서 생산)
<JSP 기본>
1. JSP == Servlet (JSP가 Servlet으로 변환됨)
2. JSP 기본태그 (JSP Scripting Tags)
(HTML 문서의 원하는 위치에 Model 데이터를 injection하기 위해서)
3. JSP 내장객체
4. JSP 액션태그
<JSP 고급>
5. EL (Expression Language)
6. JSTL (JSP Standard Tag Libraries)
---
JSP 개요
JSP은 서블릿과 마찬가지로 동적인 웹 어플리케이션을 개발할 때 사용 가능한 웹 컴포넌트이다. 다음은 JSP 웹 컴포넌트의 특징을 정리한 것이다.
- 태그(tag)기반의 웹 컴포넌트로서 jsp 확장자를 갖는다.
- 클라이언트의 요청에 의해서 동적으로 실행된다. 따라서 다양한 클라이언트 요구사항을 처리할 수 있다.
- 클라이언트는 브라우저를 이용한 URL 지정을 통해서 JSP에 요청이 가능하다. 요청방법은 HTML 파일 요청방식과 동일하다.
- JSP의 응답결과는 HTML 형식으로 서비스된다. JSP의 대부분의 구성요소가 HTML과 같은 태그로 되어있기 때문에 서블릿과 비교해서 손쉽게 HTML 화면을 구성할 수 있다.
- JSP는 자동으로 서블릿으로 변환되어 실행된다. 따라서 JSP가 서블릿이라고 해도 틀린 말이 아니다.
- MVC 패턴의 View 역할로서 JSP가 사용된다.
상위에 언급된 JSP의 특징을 반드시 숙지하고 간단한 JSP을 직접 작성하여 실행함으로써 JSP 생성 방법 및 동작 아키텍쳐를 이해해보기로 한다.
'국비학원' 카테고리의 다른 글
[국비지원] KH 정보교육원 85일차 (0) | 2022.07.28 |
---|---|
[국비지원] KH 정보교육원 84일차 (0) | 2022.07.27 |
[국비지원] KH 정보교육원 81일차 (0) | 2022.07.22 |
[국비지원] KH 정보교육원 80일차 (0) | 2022.07.21 |
[국비지원] KH 정보교육원 79일차 (0) | 2022.07.20 |