페이지에 처음 들어가면 보여줄 페이지 welcome.jsp
를 작성한다.
<!-- webapp/resources/css 폴더 내에 파일 저장 -->
<link rel="stylesheet" href="./resources/css/bootstrap.min.css">
<!-- menu -->
<nav class="navbar navbar-expand navbar-dark bg-dark">
<div class="container">
<div class="navbar-header">
<a href="./welcome.jsp" class="navbar-brand">
Home
</a>
</div>
</div>
</nav>
<!-- jumbotron -->
<%! String greeting = "Welcome to Web Shopping Mall";
String tagline = "Welcome to Web Market!";
%>
<div class="jumbotron">
<div class="container">
<h1 class="display-3">
<%= greeting %>
</h1>
</div>
</div>
<!-- main -->
<main role="main">
<div class="container">
<div class="text-center">
<h3>
<%= tagline %>
</h3>
</div>
</div>
</main>
main
의 <h3>
아래 부분에 코드를 추가한다.
<%
Date day = new Date();
String am_pm;
int hour = day.getHours();
int min = day.getMinutes();
int sec = day.getSeconds();
// 오전, 오후 표시하기
if(hour/12 == 0) {
am_pm = "AM";
} else {
am_pm = "PM";
if(hour%12 != 0) {hour = hour - 12;}
}
String CT = hour+":"+min+":"+sec+" "+am_pm;
%>
<p>현재 접속 시각 <%= CT %></p>
현재 접속 시각 11:54:45 AM
<!-- footer -->
<footer class="container">
<p>© WebMarket</p>
</footer>
페이지에서 공통으로 사용할 부분을 모듈화한다.
menu
, footer
는 다른 페이지에 공통으로 사용하므로 따로 jsp파일로 분류해 모듈화
원래 페이지에서 <body>
안에 들어가는 내용만 따로 빼줌
<nav class="navbar navbar-expand navbar-dark bg-dark">
<div class="container">
<div class="navbar-header">
<a href="./welcome.jsp" class="navbar-brand">
Home
</a>
</div>
</div>
</nav>
<footer class="container">
<p>© WebMarket</p>
</footer>
Product
객체 하나가 상품 하나의 정보를 담게 됨 (도메인 객체)
package dto;
import java.io.Serializable;
public class Product implements Serializable {
private static final long serialVersionUID = -4274700572038677000L;
private String productId; // 상품 아이디
private String pname; // 상품명
private Integer unitPrice; // 가격
private String description; // 설명
private String manufacturer; // 제조사
private String category; // 분류
private long unitsInStock; // 재고 수
private String condition; // 신상품 or 중고품 or 재생품
// 생성자
public Product() {
super();
}
public Product(String productId, String pname, Integer 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 Integer getUnitPrice() {
return unitPrice;
}
public void setUnitPrice(Integer 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;
}
}
상품 전체를 관리하기 위해 ProductRepository
클래스 작성하기
ProductRepository
에는 Product
객체를 모아 놓은 ArrayList
객체가 있고,
다양한 메서드를 호출해 해당 List와 관련된 기능을 수행함
ProductRepository
생성자에서 Product
객체를 생성하므로 상품이 미리 추가된 상태로 객체가 생성됨
package dao;
import java.util.ArrayList;
import dto.Product;
public class ProductRepository {
// Product 객체를 저장할 ArrayList 생성
private ArrayList<Product> listOfProducts = new ArrayList<Product>();
public ProductRepository() {
// repository 객체 생성할 때 상품을 미리 추가하기
Product phone = new Product("P1234", "iPhone 6s", 800000);
phone.setDescription("4.7-inch, 1334X750 Renina GD display, 8-megapixel iSight Camera");
phone.setCategory("Smart Phone");
phone.setManufacturer("Apple");
phone.setUnitsInStock(1000);
phone.setCondition("New");
Product notebook = new Product("P1235", "LG PC 그램", 1500000);
notebook.setDescription("13.3-inch, IPS LED display, 5rd Generation Intel Core processors");
notebook.setCategory("Notebook");
notebook.setManufacturer("LG");
notebook.setUnitsInStock(1000);
notebook.setCondition("Refurbished");
Product tablet = new Product("P1236", "Galaxy Tab S", 900000);
tablet.setDescription("121.8*125.6*6.6mm, Super AMOLED display, Octa-Core processors");
tablet.setCategory("Tablet");
tablet.setManufacturer("Samsung");
tablet.setUnitsInStock(1000);
tablet.setCondition("Old");
listOfProducts.add(phone);
listOfProducts.add(notebook);
listOfProducts.add(tablet);
}
// 상품 목록을 가져오는 메서드
public ArrayList<Product> getAllProducts() {
return listOfProducts;
}
}
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ page import="java.util.ArrayList" %>
<%@ page import="dto.Product" %>
<!-- 상품 목록에 접근하기 위해 자바빈즈 객체 생성 -->
<jsp:useBean id="productDAO" class="dao.ProductRepository" scope="session" />
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>상품 목록</title>
<link rel="stylesheet" href="./resources/css/bootstrap.min.css">
</head>
<body>
<!-- menu -->
<jsp:include page="menu.jsp" />
<!-- jumbotron -->
<div class="jumbotron">
<div class="container">
<h1 class="display-3">상품 목록</h1>
</div>
</div>
<%
// ArrayList 주소 가져와 변수에 대입
ArrayList<Product> listOfProducts = productDAO.getAllProducts();
%>
<div class="container">
<div class="row" align="center">
<%
// for문으로 상품 목록 하나씩 출력
for(int i=0; i < listOfProducts.size(); i++) {
// product 하나씩 가져오기
Product product = listOfProducts.get(i);
%>
<div class="col-md-4">
<h3><%= product.getPname() %></h3>
<p><%= product.getDescription() %></p>
<p><%= product.getUnitPrice() %>원</p>
</div>
<%
}
%>
</div>
<hr>
</div>
<!-- footer -->
<jsp:include page="footer.jsp" />
</body>
</html>
상품별로 틀은 같고 내용만 다르게 상세 페이지를 만들기 위해서는 상품끼리 서로 구별이 가능해야 한다. 이를 위해 Product
객체의 속성 중 productId
를 사용하고, 상품 아이디에 따라 같은 템플릿에서 데이터 값만 다르게 출력되도록 페이지를 작성한다.
ProductRepository
클래스 안에 아래 메서드 추가
// 상품 아이디로 상품 찾기
public Product getProductById(String productId) {
// 반환할 Product 객체를 담을 변수
Product productById = null;
// list 상품 하나씩 for문으로 검사하기
for(int i=0; i < listOfProducts.size(); i++) {
Product product = listOfProducts.get(i);
if (product != null && product.getProductId() != null
&& product.getProductId().equals(productId)) {
// i번째 Product 객체가 존재하고
// 그 객체의 상품 아이디가 존재하고
// 상품 아이디가 파라미터로 받은 아이디와 일치하면
productById = product;
break;
// 변수에 해당 객체 대입하고 반복 종료하기
}
}
return productById;
}
상품 목록 페이지 products.jsp
페이지 상품 정보 아래에 코드 추가
<div class="col-md-4 p-4">
<h3><%= product.getPname() %></h3>
<p><%= product.getDescription() %></p>
<p><%= product.getUnitPrice() %>원</p>
<!-- 상품 아이디를 id 변수에 담아 파라미터로 전달 -->
<p><a href="./product.jsp?id=<%= product.getProductId() %>"
class="btn btn-secondary" role="button">상세 정보 »</a></p>
</div>
상세 페이지로 넘어올 때 url의 쿼리 스트링(? 뒤의 문자)으로 상품 아이디를 전달받아 getProductById()
메서드로 상품을 특정하고, 그 상품의 정보를 출력
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ page import="dto.Product" %>
<!-- 상품 목록에 접근하기 위해 자바빈즈 객체 생성 -->
<jsp:useBean id="productDAO" class="dao.ProductRepository" scope="session" />
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>상품 상세 정보</title>
<link rel="stylesheet" href="./resources/css/bootstrap.min.css">
<body>
<!-- menu -->
<jsp:include page="menu.jsp" />
<!-- jumbotron -->
<div class="jumbotron">
<div class="container">
<h1 class="display-3">상품 정보</h1>
</div>
</div>
<%
// 파라미터로 받은 상품 아이디로 상품 찾기
String id = request.getParameter("id");
Product product = productDAO.getProductById(id);
%>
<div class="container">
<div class="row">
<div class="col-md-6">
<h3><%= product.getPname() %></h3>
<p><%= product.getDescription() %></p>
<p>
<strong>상품 코드 : </strong>
<span class="badge badge-danger"><%= product.getProductId() %></span>
</p>
<p>
<strong>제조사 : </strong>
<%= product.getManufacturer() %>
</p>
<p>
<strong>분류 : </strong>
<%= product.getCategory() %>
</p>
<p>
<strong>재고 수 : </strong>
<%= product.getUnitsInStock() %>
</p>
<h4><%= product.getUnitPrice() %> 원</h4>
<p>
<a href="#" class="btn btn-info">상품 주문 »</a>
<a href="./products.jsp" class="btn btn-secondary">상품 목록 »</a>
</p>
</div>
</div>
<hr>
</div>
<!-- footer -->
<jsp:include page="footer.jsp" />
</body>
</html>
폼에 입력한 데이터는 processAddProduct.jsp
로 전달
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>상품 등록</title>
<link rel="stylesheet" href="./resources/css/bootstrap.min.css">
</head>
<body>
<!-- menu -->
<jsp:include page="menu.jsp" />
<!-- jumbotron -->
<div class="jumbotron">
<div class="container">
<h1 class="display-3">상품 등록</h1>
</div>
</div>
<div class="container">
<form name="newProduct" action="./processAddProduct.jsp" class="form-horizontal" method="post">
<div class="form-group row">
<label class="col-sm-2">상품 코드</label>
<div class="col-sm-3">
<input type="text" name="productId" class="form-control">
</div>
</div>
<div class="form-group row">
<label class="col-sm-2">상품명</label>
<div class="col-sm-3">
<input type="text" name="name" class="form-control">
</div>
</div>
<div class="form-group row">
<label class="col-sm-2">가격</label>
<div class="col-sm-3">
<input type="text" name="unitPrice" class="form-control">
</div>
</div>
<div class="form-group row">
<label class="col-sm-2">상세 정보</label>
<div class="col-sm-5">
<textarea name="description" cols="50" rows="2" class="form-control"></textarea>
</div>
</div>
<div class="form-group row">
<label class="col-sm-2">제조사</label>
<div class="col-sm-3">
<input type="text" name="manufacturer" class="form-control">
</div>
</div>
<div class="form-group row">
<label class="col-sm-2">분류</label>
<div class="col-sm-3">
<select name="category" class="custom-select">
<option value="Smart Phone">Smart Phone</option>
<option value="Notebook">Notebook</option>
<option value="Tablet">Tablet</option>
<option value="Others">Others</option>
</select>
</div>
</div>
<div class="form-group row">
<label class="col-sm-2">재고 수</label>
<div class="col-sm-3">
<input type="text" name="unitsInStock" class="form-control">
</div>
</div>
<div class="form-group 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="Refurbished"> 재생 제품
</div>
</div>
<div class="form-group row">
<div class="col-sm-offset-2 col-sm-10">
<input type="submit" class="btn btn-primary" value="등록">
</div>
</div>
</form>
<hr>
</div>
<!-- footer -->
<jsp:include page="footer.jsp" />
</body>
</html>
ProductRepository
클래스 안에 메서드 추가
또한 이 클래스의 인스턴스를 싱글턴 패턴으로 사용하도록 코드를 수정함
// 상품 목록에 상품을 추가하는 메서드
public void addProduct(Product product) {
listOfProducts.add(product);
}
// 자기 자신의 static 객체 생성
private static ProductRepository instance = new ProductRepository();
// 자신의 static 객체를 반환하는 static 메서드
public static ProductRepository getInstance() {
return instance;
}
request.getParameter()
로 가져와Product
객체를 새로 생성해 setter 메서드
로 값을 저장하고ProductRepository
의 addProduct()
로 ArrayList
에 생성한 객체를 추가<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ page import="dto.Product" %>
<%@ page import="dao.ProductRepository" %>
<%
// 전달받은 파라미터 인코딩 방식 설정
request.setCharacterEncoding("UTF-8");
// 전달받은 파라미터 담기
String productId = request.getParameter("productId");
String name = request.getParameter("name");
String unitPrice = request.getParameter("unitPrice");
String description = request.getParameter("description");
String manufacturer = request.getParameter("manufacturer");
String category = request.getParameter("category");
String unitsInStock = request.getParameter("unitsInStock");
String condition = request.getParameter("condition");
// Product 객체에 set하기 위해 일부 값은 형변환 필요
Integer price;
if(unitPrice.isEmpty()) {
// 가격 입력값이 비어있으면 0으로 설정
price = 0;
} else {
// 가격 입력값(String)을 Integer 타입으로 변환
price = Integer.valueOf(unitPrice);
}
long stock;
if(unitsInStock.isEmpty()) {
stock = 0;
} else {
stock = Long.valueOf(unitsInStock);
}
// ProductRepository static 객체 가져오기
ProductRepository dao = ProductRepository.getInstance();
// 새로운 Product 객체를 만들어 입력받은 값 set
Product newProduct = new Product();
newProduct.setProductId(productId);
newProduct.setPname(name);
newProduct.setUnitPrice(price);
newProduct.setDescription(description);
newProduct.setManufacturer(manufacturer);
newProduct.setCategory(category);
newProduct.setUnitsInStock(stock);
newProduct.setCondition(condition);
// 상품 목록(ArrayList)에 Product 객체 추가하는 메서드 호출
dao.addProduct(newProduct);
// 상품 목록 페이지로 이동
response.sendRedirect("products.jsp");
%>
파일명 : products.jsp, product.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ page import="dto.Product" %>
// 자바빈즈 객체 생성 대신 static 객체 사용을 위해 해당 클래스 import
<%@ page import="dao.ProductRepository" %>
...
파일명 : product.jsp
<%
String id = request.getParameter("id");
// 싱글턴 패턴으로 ProductRepository 객체 참조
ProductRepository dao = ProductRepository.getInstance();
Product product = dao.getProductById(id);
%>
public class Product implements Serializable {
...
private String filename; // 이미지 파일명을 담음 (ex. image.jpg)
public String getFilename() {
return filename;
}
public void setFilename(String filename) {
this.filename = filename;
}
...
}
ProductRepository
생성자에서 미리 생성되는 Product
객체의 filename
을 set
public class ProductRepository {
...
private ProductRepository() {
...
phone.setFilename("p1234.jpg");
notebook.setFilename("p1235.jpg");
tablet.setFilename("p1236.jpg");
...
}
...
}
상품 목록 페이지 products.jsp
코드 추가
<div class="col-md-4 p-4">
<!-- 코드 추가 -->
<img src="./resources/images/<%= product.getFilename() %>" style="width:100%;">
...
</div>
상품 상세 페이지 product.jsp
코드 추가
<div class="row">
<!-- 코드 추가 -->
<div class="col-md-5">
<img src="./resources/images/<%= product.getFilename() %>" style="width:100%;">
</div>
...
</div>
상품 등록 페이지 addProduct.jsp
에서
form
의 속성을 enctype="multipart/form-data"
, post="method"
으로 설정하고 파일을 첨부하는 input
추가
파일명 : addProduct.jsp
<form name="newProduct" action="./processAddProduct.jsp"
class="form-horizontal" method="post" enctype="multipart/form-data">
...
<div class="form-group row">
<label class="col-sm-2">이미지</label>
<div class="col-sm-5">
<input type="file" name="productImage" class="form-control">
</div>
</div>
...
</form>
...
processAddProduct.jsp
코드를 다음과 같이 수정
MultipartRequest
객체를 사용해 파일 처리 🔗참고
파일명 : processAddProduct.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ page import="com.oreilly.servlet.*" %>
<%@ page import="com.oreilly.servlet.multipart.*" %>
<%@ page import="java.util.*" %>
<%@ page import="dto.Product" %>
<%@ page import="dao.ProductRepository" %>
<%
// 전달받은 파라미터 인코딩 방식 설정
request.setCharacterEncoding("UTF-8");
// 파일을 전달받기 위한 작업
// 이미지 경로 지정
String path = "./resources/images";
String savedir = request.getServletContext().getRealPath(path);
// 최대 파일 크기, 인코딩 유형
int maxSize = 5*1024*1024;
String encType = "utf-8";
// getServletContext() : 서버가 실행되고 있는 경로 얻기
// 전달값 접근을 위한 MultipartRequest 객체 생성
MultipartRequest multi = new MultipartRequest(request, savedir, maxSize, encType);
// new DefaultFileRenamePolicy()을 파라미터로 추가하면 덮어쓰지 않음
// 전달받은 파라미터 담기
String productId = multi.getParameter("productId");
String name = multi.getParameter("name");
String unitPrice = multi.getParameter("unitPrice");
String description = multi.getParameter("description");
String manufacturer = multi.getParameter("manufacturer");
String category = multi.getParameter("category");
String unitsInStock = multi.getParameter("unitsInStock");
String condition = multi.getParameter("condition");
// Product 객체에 set하기 위해 일부 값은 형변환 필요
Integer price;
if(unitPrice.isEmpty()) {
// 가격 입력값이 비어있으면 0으로 설정
price = 0;
} else {
// 가격 입력값(String)을 Integer 타입으로 변환
price = Integer.valueOf(unitPrice);
}
long stock;
if(unitsInStock.isEmpty()) {
stock = 0;
} else {
stock = Long.valueOf(unitsInStock);
}
// 이미지 파일 이름 가져오기
String productImage = multi.getFilesystemName("productImage");
// ProductRepository static 객체 가져오기
ProductRepository dao = ProductRepository.getInstance();
// 새로운 Product 객체를 만들어 입력받은 값 set
Product newProduct = new Product();
newProduct.setProductId(productId);
newProduct.setPname(name);
newProduct.setUnitPrice(price);
newProduct.setDescription(description);
newProduct.setManufacturer(manufacturer);
newProduct.setCategory(category);
newProduct.setUnitsInStock(stock);
newProduct.setCondition(condition);
newProduct.setFilename(productImage);
// 상품 목록(ArrayList)에 Product 객체 추가하는 메서드 호출
dao.addProduct(newProduct);
// 상품 목록 페이지로 이동
response.sendRedirect("products.jsp");
%>