[JSP] 웹 쇼핑몰 페이지 만들기 (1)

yeju·2023년 6월 21일
0

연습

목록 보기
4/7
post-thumbnail

📝 Step 1. 시작 페이지 만들기

페이지에 처음 들어가면 보여줄 페이지 welcome.jsp 를 작성한다.

CSS 적용을 위해 부트스트랩 v4.0.0 적용

<!-- webapp/resources/css 폴더 내에 파일 저장 -->
<link rel="stylesheet" href="./resources/css/bootstrap.min.css">

1) menu

<!-- 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>

2) jumbotron

<!-- 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>

3) main

<!-- 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>&copy; WebMarket</p>
</footer>

📝 Step 2. 페이지 모듈화하기

페이지에서 공통으로 사용할 부분을 모듈화한다.

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.jsp

<footer class="container">
	<p>&copy; WebMarket</p>
</footer>

2. welcome.jsp 에서 모듈화한 부분 include 코드로 교체


📝 Step 3. 상품 목록 페이지 만들기

1. 상품 클래스 작성하기

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;
	}
}

2. 상품 데이터 접근 클래스 작성하기

상품 전체를 관리하기 위해 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;
	}
}

3. 상품 목록을 출력할 페이지 products.jsp 작성

<%@ 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>

📝 Step 4. 상품 상세 페이지 만들기

상품별로 틀은 같고 내용만 다르게 상세 페이지를 만들기 위해서는 상품끼리 서로 구별이 가능해야 한다. 이를 위해 Product 객체의 속성 중 productId 를 사용하고, 상품 아이디에 따라 같은 템플릿에서 데이터 값만 다르게 출력되도록 페이지를 작성한다.

1. 상품 id로 상품을 찾는 메서드 만들기

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;
}

2. 상품 목록 페이지에 상세 정보 버튼 추가하기


상품 목록 페이지 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">상세 정보 &raquo;</a></p>
</div>

3. 상품 상세 페이지 product.jsp 만들기

상세 페이지로 넘어올 때 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">상품 주문 &raquo;</a>
    				<a href="./products.jsp" class="btn btn-secondary">상품 목록 &raquo;</a>
    			</p>
    		</div>
    	</div>
    	<hr>
    </div>
    
    <!-- footer -->
    <jsp:include page="footer.jsp" />
</body>
</html>

📝 Step 5. 상품 등록 페이지 만들기

1. 새 상품 정보를 입력받을 페이지 addProduct.jsp 작성

폼에 입력한 데이터는 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>

2. 새로운 상품을 목록에 추가하는 메서드 만들기

ProductRepository 클래스 안에 메서드 추가
또한 이 클래스의 인스턴스를 싱글턴 패턴으로 사용하도록 코드를 수정함

// 상품 목록에 상품을 추가하는 메서드
public void addProduct(Product product) {
	listOfProducts.add(product);
}

// 자기 자신의 static 객체 생성
private static ProductRepository instance = new ProductRepository();
// 자신의 static 객체를 반환하는 static 메서드
public static ProductRepository getInstance() {
	return instance;
}

3. 새 상품 정보를 처리할 페이지 processAddProduct.jsp 작성

  1. 전달받은 값을 request.getParameter() 로 가져와
  2. Product 객체를 새로 생성해 setter 메서드 로 값을 저장하고
  3. ProductRepositoryaddProduct()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");
%>

4. 상품 목록 페이지, 상세 페이지 ProductRepository 객체 참조 방식을 싱글턴 패턴으로 수정

파일명 : 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);
%>

📝 Step 6. 상품 이미지 등록하기 (파일 업로드)

1. 상품 클래스에 이미지 정보를 담을 멤버 변수 추가

public class Product implements Serializable {
	
    ...
    
    private String filename; // 이미지 파일명을 담음 (ex. image.jpg)
    public String getFilename() {
		return filename;
	}
	public void setFilename(String filename) {
		this.filename = filename;
	}
    
    ...
    
}

2. 상품 데이터 접근 클래스에 이미지 정보 추가

ProductRepository 생성자에서 미리 생성되는 Product 객체의 filename 을 set

public class ProductRepository {
	
    ...
    
    private ProductRepository() {
        ...
        phone.setFilename("p1234.jpg");
        notebook.setFilename("p1235.jpg");
        tablet.setFilename("p1236.jpg");
        ...
    }
    
    ...
    
}

3. 상품 목록 페이지, 상세 페이지에 이미지 추가


상품 목록 페이지 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>

4. 상품 등록 페이지에 파일 업로드 기능 추가


상품 등록 페이지 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");
%>
profile
🌱

0개의 댓글