목표
products.jsp와 product.jsp에 해당 사진이 보여지도록하고
addProduct.jsp에서 사진을 저장하도록 한다
ProductVO추가 (filename 저장 프로퍼티 생성)
package kr.or.ddit.vo;
// 자바 빈 클래스
/* 자바빈 규약
1. 프로퍼티
2. 기본생성자
3. getter/setter메서드
*/
/**
* @author PC-13
*
*/
public class ProductVO {
// 프로퍼티 = 멤버변수(필드)
private String productId;
private String pname;
private long unitPrice;
private String description;
private String manufacturer;
private String category;
private long unitsInStock;
private String condition;
private String filename;
// 기본 생성자
public ProductVO() {
}
// 생성자(상품아이디, 상품명, 상품가격)
public ProductVO(String productId, String pname, long unitPrice) {
this.productId = productId;
this.pname = pname;
this.unitPrice = unitPrice;
}
// getter / setter 메서드
public String getProductId() {
return productId;
}
public void setProductId(String productId) {
this.productId = productId;
}
public String getPname() {
return pname;
}
public void setPname(String pname) {
this.pname = pname;
}
public long getUnitPrice() {
return unitPrice;
}
public void setUnitPrice(long unitPrice) {
this.unitPrice = unitPrice;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public String getManufacturer() {
return manufacturer;
}
public void setManufacturer(String manufacturer) {
this.manufacturer = manufacturer;
}
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 getCondition() {
return condition;
}
public void setCondition(String condition) {
this.condition = condition;
}
public String getFilename() {
return filename;
}
public void setFilename(String filename) {
this.filename = filename;
}
@Override
public String toString() {
return "ProductVO [productId=" + productId + ", pname=" + pname + ", unitPrice=" + unitPrice + ", description="
+ description + ", manufacturer=" + manufacturer + ", category=" + category + ", unitsInStock="
+ unitsInStock + ", condition=" + condition + "]";
}
}
Dao 수정
(기존 파일 사진 추가)
package kr.or.ddit.dao;
import java.util.ArrayList;
import java.util.List;
import kr.or.ddit.vo.ProductVO;
public class ProductRepository {
// 싱글톤 객체
private static ProductRepository dao;
public static ProductRepository getInstance() {
if(dao==null) dao = new ProductRepository();
return dao;
}
private List<ProductVO> listOfProducts = new ArrayList<ProductVO>();
// 기본 생성자 3개의 상품 정보를 설정
private ProductRepository() {
ProductVO phone = new ProductVO("P1234", "iPhone 15s", 1250000);
phone.setDescription("iPhone 15 · A16 Bionic 칩 5코어 GPU 탑재 · 첨단 듀얼 카메라 시스템. 48MP 메인 카메라 2배 망원 지원 울트라 와이드 카메라 · 최대 26시간 동영상 재생 ");
phone.setCategory("Smart Phone");
phone.setManufacturer("Apple");
phone.setUnitsInStock(1000);
phone.setCondition("New");
phone.setFilename("P1234.jpg");
ProductVO notebook = new ProductVO("P1235", "LG Gram", 2000000);
notebook.setDescription("최대 22시간의 배터리 성능이 선사하는 궁극의 프로급 휴대성");
notebook.setCategory("NoteBook");
notebook.setManufacturer("LG");
notebook.setUnitsInStock(1000);
notebook.setCondition("Old");
notebook.setFilename("P1235.jpg");
ProductVO tablet = new ProductVO("P1236", "갤럭시 탭 S9 Ultra", 1700000);
tablet.setDescription("디스플레이 369.9 mm 다이나믹 아몰레드 2X · 내구성 IP68 · 프로세서 스냅드래곤8 2세대");
tablet.setCategory("Tablet");
tablet.setManufacturer("Samsung");
tablet.setUnitsInStock(1000);
tablet.setCondition("Refurbished");
tablet.setFilename("P1236.jpg");
listOfProducts.add(phone);
listOfProducts.add(notebook);
listOfProducts.add(tablet);
}
// ProductVO 객체 타입의 변수 listOfProducts에 저장된 모든 상품 목록을 가져옴
public List<ProductVO> getAllProducts(){
return listOfProducts;
}
// 상품 상세 보기
// listOfProducts 변수에 저장된 3개 (이상)의 상품 목록 중
// 선택한 상품의 아이디와 일치하는 상품 정보를 가져옴
public ProductVO getProductById(String productId) {
for(ProductVO vo : listOfProducts) {
String id = vo.getProductId();
if(id.equals(productId)) {
return vo;
}
}
return null;
};
// 상품 등록(무엇을 어디에 추가)
public void addProduct(ProductVO vo) {
listOfProducts.add(vo);
};
}
Products.jsp 수정
사진 추가
<%@page import="kr.or.ddit.vo.ProductVO"%>
<%@page import="java.util.List"%>
<%@page import="kr.or.ddit.dao.ProductRepository"%>
<%@ page language="java" contentType="text/html; charset=UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
<!DOCTYPE html>
<html>
<head>
<title>상품 목록</title>
<link rel="stylesheet" href="/css/bootstrap.min.css">
<script src="/js/jquery-3.6.0.js"></script>
<script>
$(function(){
$(document).on('click','.col-md-4',function(){
let id = $(this).attr("name");
location.href="/product.jsp?pid="+id;
})
})
</script>
</head>
<body>
<!-- header -->
<!--
디렉티브 태그 속성 속성의 값 -->
<%@ include file="menu.jsp" %>
<% // 스크립틀릿
// 클래스 객체 클래스 메서드(호출)
ProductRepository dao = ProductRepository.getInstance();
// 객체타입 변수 객체 메서드(호출)
List<ProductVO> list = dao.getAllProducts();
%>
<!-- 상품 목록 시작 -->
<div class="jumbotron">
<div class="container">
<h1 class="display-3">Product List</h1>
</div>
</div>
<div class="container">
<div class="row" align="center">
<c:set var="list" value="<%=list %>"/>
<!-- 상품 반복 부분 시작 -->
<!-- 객체 타입 변수 list에 저장된 상품 목록 개수만큼 실행하는 JSTL 반복문 -->
<c:forEach var="vo" items="${list}">
<div class="col-md-4" name="${vo.productId}">
<!-- EL 표현문 -->
<h3>${vo.pname}</h3>
<img src="/images/${vo.filename}" style='width:200px;' />
<p>${vo.description}</p>
<p><fmt:formatNumber value="${vo.unitPrice}" type="number" pattern="#,###" />원</p>
<p>
<a href="product.jsp?pid=${vo.productId}" class="btn btn-secondary" role="button">상세정보 »</a>
</p>
</div>
</c:forEach>
<!-- 상품 반복 부분 끝 -->
</div>
<hr />
<div class="form-group row">
<div class="col-sm-offset-2 col-sm-10">
<a href="/addProduct.jsp" class="btn btn-primary" role="button">등록</a>
</div>
</div>
</div>
<!-- 상품 목록 끝 -->
<!-- footer -->
<%@ include file="footer.jsp" %>
</body>
</html>
Product.jsp 수정
사진 추가
<%@page import="kr.or.ddit.vo.ProductVO"%>
<%@page import="java.util.List"%>
<%@page import="kr.or.ddit.dao.ProductRepository"%>
<%@ page language="java" contentType="text/html; charset=UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
<!DOCTYPE html>
<html>
<head>
<title>상품 목록</title>
<link rel="stylesheet" href="/css/bootstrap.min.css">
</head>
<body>
<!-- header -->
<!--
디렉티브 태그 속성 속성의 값 -->
<%@ include file="menu.jsp" %>
<!-- 상품 목록 시작 -->
<div class="jumbotron">
<div class="container">
<h1 class="display-3">상품 상세</h1>
</div>
</div>
<div class="container">
<%
String pid = request.getParameter("pid");
ProductRepository dao = ProductRepository.getInstance();
ProductVO vo = dao.getProductById(pid);
%>
<c:set var="vo" value="<%=vo %>"/>
<div class="row">
<div class="col-md-6"> <!-- style = " width : 50%; "-->
<span class="badge badge-danger">${vo.condition}</span>
<h3>
${vo.pname}</h3>
<img src="/images/${vo.filename}" style='width:200px;' />
<p>${vo.description}</p>
<p>
<b>상품 코드 : </b>
${vo.productId}
</p>
<p>
<b>제조사 : </b>
${vo.manufacturer}
</p>
<p>
<b>분류 : </b>
${vo.category}
</p>
<p>
<b>재고 수 : </b>
${vo.unitsInStock}
</p>
<h4>
<fmt:formatNumber value="${vo.unitPrice}" type="number" pattern="#,###" />원
</h4>
<p>
<a href="/products.jsp" class="btn btn-secondary" role="button">상품 목록 »</a>
</p>
</div>
</div>
</div>
<!-- 상품 목록 끝 -->
<!-- footer -->
<%@ include file="footer.jsp" %>
</body>
</html>
addProduct.jsp
파일 input추가와 form에 enctype="multipart/form-data"추가
<%@page import="kr.or.ddit.vo.ProductVO"%>
<%@page import="java.util.List"%>
<%@page import="kr.or.ddit.dao.ProductRepository"%>
<%@ page language="java" contentType="text/html; charset=UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt"%>
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href="/css/bootstrap.min.css">
<script src="/js/jquery.min.js"></script>
<title>상품 목록</title>
<script>
$(function(){
$('input:file').on('input',handleImg);
})
// e 이벤트 객체
function handleImg(e){
let files = e.target.files; // 파일에 접근
let fileArr = Array.prototype.slice.call(files); // 붙어있는 파일을 배열로 정렬
$.each(fileArr, function(){
// 이미지 여부 체크
if(!this.type.match("image.*")){
console.log("이미지가 아닙니다")
return;
}
// 이미지
let reader = new FileReader();
// e : reader가 이미지 객체를 읽는 이벤트
reader.onload = function(e){
let img_html = "<img src='"+e.target.result+"' style='width:200px;' />";
// 요소.append : 누적, 요소.html : 새로고침,
// 요소.innerHTML : JavaScript에서 새로고침
$('#pImg').html(img_html);
}
reader.readAsDataURL(this);
});
}
</script>
</head>
<body>
<!-- header -->
<!--
디렉티브 태그 속성 속성의 값 -->
<%@ include file="menu.jsp"%>
<!-- 상품 목록 시작 -->
<div class="jumbotron">
<div class="container">
<h1 class="display-3">상품 등록</h1>
</div>
</div>
<div class="container">
<form action="processAddProduct.jsp" method="post" enctype="multipart/form-data" class="form-horizontal" name="newProduct">
<div class="form-group row">
<label class="col-sm-2">상품 코드</label>
<div class="col-sm-3">
<input type="text" name="productId">
</div>
</div>
<div class="form-group row">
<label class="col-sm-2">상품명</label>
<div class="col-sm-3">
<input type="text" name="pname">
</div>
</div>
<div class="form-group row">
<label class="col-sm-2">가격</label>
<div class="col-sm-3">
<input type="text" name="unitPrice">
</div>
</div>
<div class="form-group row">
<label class="col-sm-2">상세정보</label>
<div class="col-sm-5">
<textarea rows="2" cols="23" name="description">
</textarea>
</div>
</div>
<div class="form-group row">
<label class="col-sm-2">제조사</label>
<div class="col-sm-3">
<input type="text" name="manufacturer">
</div>
</div>
<div class="form-group row">
<label class="col-sm-2">카테고리</label>
<div class="col-sm-3">
<input type="text" name="category">
</div>
</div>
<div class="form-group row">
<label class="col-sm-2">재고수</label>
<div class="col-sm-3">
<input type="text" name="unitsInStock">
</div>
</div>
<div class="form-group row">
<label class="col-sm-2">상태</label>
<div class="col-sm-5">
<input type="radio" id="new" name="condition" value="New">
<label for="new">신규 제품</label>
<input type="radio" id="old" name="condition" value="Old">
<label for="old">중고 제품</label>
<input type="radio" id="Refurbished" name="condition" value="Refurbished">
<label for="Refurbished">재생 제품</label>
</div>
</div>
<div class="form-group row">
<label class="col-sm-2">이미지</label>
<div class="col-sm-3">
<input type="file" name="filename">
<span id="pImg"></span>
</div>
</div>
<div class="form-group row">
<div class="col-sm-offset-2 col-sm-10">
<input class="btn btn-primary" type="submit" value="등록" />
</div>
</div>
<hr />
</form>
</div>
<!-- 상품 목록 끝 -->
<!-- footer -->
<%@ include file="footer.jsp"%>
</body>
</html>
processAddProduct.jsp 수정
파일여부를 확인해 파일일 때는 저장하고 vo객체에 이름 값 저장하고
파일이 아닐때는 값을 각각의 vo값에 저장하여 insert작업을 수행한다
<%@page import="org.apache.commons.fileupload.DiskFileUpload"%>
<%@page import="java.io.File"%>
<%@page import="java.util.UUID"%>
<%@page import="org.apache.commons.fileupload.FileItem"%>
<%@page import="java.util.Iterator"%>
<%@page import="java.util.List"%>
<%@page import="kr.or.ddit.dao.ProductRepository"%>
<%@page import="kr.or.ddit.vo.ProductVO"%>
<%@page import="java.util.Enumeration"%>
<%@ page language="java" contentType="text/html; charset=UTF-8"%>
<%
request.setCharacterEncoding("utf-8");
//윈도우 경로 : 역슬러시 두 개
// 해당 경로는 가져오는 과정이 있기 때문에 redirect로 페이지를 이동했을 때 해당 이미지가 바로 표시되지 않는다 cash폴더를 이용해야 빠르게 접근이 가능하다
// String path = "D:\\A_TeachingMaterial\\06_JSP\\workspace\\JSPBook\\WebContent\\images";
// 캐시파일로 저장할 경우 바로 이미지가 나옴 org.eclipse.wst.server.core\\tmp0\\wtpwebapps 의 경로로 들어갈 것
String path = "D:\\A_TeachingMaterial\\06_JSP\\workspace\\.metadata\\.plugins\\org.eclipse.wst.server.core\\tmp0\\wtpwebapps\\JSPBook\\images";
//commons-fileupload.jar 안에 해당 클래스가 있음
DiskFileUpload upload = new DiskFileUpload();
// 업로드 할 파일 크기의 최대 크기
upload.setSizeMax(5000000); //5Mbyte
// 메모리에 저장할 최대 크기
upload.setSizeThreshold(5*4096); // 5 * 1024 * 1024
// 업로드할 파일을 임시로 저장할 경로(폴더가 없으면 자동으로 폴더가 생성됨 mkdir()으로 생성하지 않아도됨)
upload.setRepositoryPath(path);
// 요청 파라미터 : {filename=파일객체}
// parse : 구문분석(오류체크), 의미분석, 변환
List items = upload.parseRequest(request);
// 요청 파라미터 들을 Iterator(열거) 클래스로 변환
Iterator params = items.iterator();
ProductVO vo = new ProductVO();
// 요청 파라미터가 없어질 때 까지 반복
while(params.hasNext()){
// FileItem : 일반데이터(text, radio, checkbox)
// 파일(file)
FileItem item = (FileItem) params.next();
//isFormField() > true > 일반데이터
if(!item.isFormField()){// 파일(input type="file")
// 요청 파라미터 : {filename=파일객체} => item
String fileFieldName = item.getFieldName(); // filename
String fileName = item.getName(); // 업로드 될 파일 명(경로 포함)
fileName = fileName.substring(fileName.lastIndexOf("\\")+1); // 경로 삭제
// 이미지파일이라면 MIME TYPE : image/jpg
String contentType = item.getContentType();
long fileSize = item.getSize(); //파일의 크기
// 파일이 이미 있으면 already exists: 오류 발생
//파일명 중복 방지 시작
UUID uuid = UUID.randomUUID();
fileName = uuid.toString() + "_" +fileName;
// c:\\upload\\사진.jpg로 복사
File file = new File(path, fileName);
// 복사 실행
item.write(file);
vo.setFilename(fileName);
} else{
String key = item.getFieldName();
String value = item.getString("UTF-8"); // 한글 처리
// if문으로 비교해서 넣기..
if(key.equals("productId")){
vo.setProductId(value);
} else if(key.equals("pname")){
vo.setPname(value);
} else if(key.equals("unitPrice")){
vo.setUnitPrice(Long.parseLong(value));
} else if(key.equals("description")){
vo.setDescription(value);
} else if(key.equals("manufacturer")){
vo.setManufacturer(value);
} else if(key.equals("category")){
vo.setCategory(value);
} else if(key.equals("unitsInStock")){
vo.setUnitsInStock(Integer.parseInt(value));
} else if(key.equals("condition")){
vo.setCondition(value);
}
}
}
ProductRepository dao = ProductRepository.getInstance();
// 새로운 상품 등록
dao.addProduct(vo);
// 목록이동 (redirect : url)
response.sendRedirect("/products.jsp");
%>
'JAVA > JSP' 카테고리의 다른 글
[JSP] 구현5 - 유효성 검사, 다국어(fmt) (0) | 2024.07.09 |
---|---|
[JSP] Validation(유효성 검사), 정규 표현식 (0) | 2024.07.08 |
[JSP] 파일 업로드 (0) | 2024.07.04 |
[JSP] 구현 3 - 상품 추가 (0) | 2024.07.03 |
[JSP] form 태그 (0) | 2024.07.02 |