본문 바로가기
[ JAVA ]/JAVA Spring

[ Spring ] 상품 목록 기능 구현

by 환이s 2023. 4. 10.

 

프로젝트 구조

 

 

오늘은 상품 관리 할 때 필요한 목록 리스트 기능을 구현해 보겠습니다.

 

프로젝트 흐름은 다음과 같습니다.

 

Product table 생성 => menu.jsp(호출페이지) => DTO => Controller => Service => DAO => View 단


Product Table

 

먼저 데이터를 담을 수 있는 테이블을 생성하고 목록 페이지에 출력될 상품 데이터를 추가합니다.

 

-- 상품테이블 생성
create table product (
product_id number,
product_name varchar2(50),
price number default 0,
description clob,
picture_url varchar2(500),
primary key(product_id)
);

insert into product values (1,'레몬',1500,'레몬에 포함된 구연산은 피로회복에 좋
습니다. 비타민 C도 풍부합니다.','lemon.jpg');
insert into product values (2,'오렌지',2000,'비타민 C가 풍부합니다. 생과일 주스
로 마시면 좋습니다.','orange.jpg');
insert into product values (3,'키위',3000,'비타민 C가 매우 풍부합니다. 다이어트
나 미용에 좋습니다.','kiwi.jpg'); 
insert into product values (4,'포도',5000,'폴리페놀을 다량 함유하고 있어 항산화
작용을 합니다.','grape.jpg');
insert into product values (5,'딸기',8000,'비타민 C나 플라보노이드를 다량 함유
하고 있습니다.','strawberry.jpg');
insert into product values (6,'귤',7000,'시네피린을 함유하고 있어 감기 예방에
좋다고 합니다.','tangerine.jpg');
select * from product;

 

테이블 생성과 데이터를 추가했다면 타입에 맞게 DTO를 생성합니다.

 


DTO

 

package com.example.spring.model.shop.dto;

import org.springframework.web.multipart.MultipartFile;

public class ProductDTO {

	private int product_id;
	private String product_name;
	private int price;
	private String description;
	private  String picture_url;
	private MultipartFile file1; // 첨부파일 

	public int getProduct_id() {
		return product_id;
	}

	public void setProduct_id(int product_id) {
		this.product_id = product_id;
	}

	public String getProduct_name() {
		return product_name;
	}

	public void setProduct_name(String product_name) {
		this.product_name = product_name;
	}

	public int getPrice() {
		return price;
	}

	public void setPrice(int price) {
		this.price = price;
	}

	public String getDescription() {
		return description;
	}

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

	public String getPicture_url() {
		return picture_url;
	}

	public void setPicture_url(String picture_url) {
		this.picture_url = picture_url;
	}

	public MultipartFile getFile1() {
		return file1;
	}

	public void setFile1(MultipartFile file1) {
		this.file1 = file1;
	}

	@Override
	public String toString() {
		return "ProductDTO [product_id=" + product_id + ", product_name=" + product_name + ", price=" + price
				+ ", description=" + description + ", picture_url=" + picture_url + ", file1=" + file1 + "]";
	}
}

 

DTO 생성을 했다면 이제 본격적으로 기능 구현에 들어가는데, 이전 포스팅에서 메뉴로 구현한 menu.jsp 페이지에 기능을 추가해서 작업하려고 합니다. 


menu.jsp

 

호출 방식은 확장자로 Controller에서 세부 url 작업을 할 수 있게 합니다.

 

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
        <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
        <c:set var="path" value="${pageContext.request.contextPath }"/>   

<div style="text-align: center;">
 	<a href="${path }">Home</a> |
	<a href="${path}/memo/list.do">메모장</a> |
	<a href="${path}/upload/uploadForm">업로드 테스트</a> | 
	<a href="${path}/shop/product/list.do">상품 목록</a> | <!-- 기능 추가 -->
	<div style="text-align: right;">
	<a href="${path}/member/login.do">로그인</a> |
	</div>
</div>
<hr>

 


Controller

 

호출받은 Controller는 중간 다리 역할을 하는데, ControllerService DI(의존 관계)를 설정해야 합니다.

@Inject 처리를 해주고, url 맵핑 처리해서 서비스단에 보냅니다.

 

package com.example.spring.controller.shop;

import javax.inject.Inject;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;

import com.example.spring.service.shop.ProductService;

@Controller
@RequestMapping("shop/product/*") // 공통 url pattern
public class ProductController {
		
	@Inject
	ProductService productService;
	
	
	@RequestMapping("list.do")
	public ModelAndView list(ModelAndView mav) {
		mav.setViewName("/shop/product_list");
		mav.addObject("list", productService.listProduct());
		return mav;
	}

 

Controller에서 사용한 ModelAndView데이터와 이동하고자 하는 View Page를 같이 저장하는 생성자 입니다. 

 

Service단에는 setViewName(String view) => 응답할 view 단 페이지와 , addObject() => view단에 전달할 값을 설정해서 리턴해줍니다.

 


Service

 

Service 단에서는 DAO와 의존 관계 설정을 해주고,

Service, DAO에서 해당 품목 상세 페이지까지 구현할 수 있게 미리 설정해 줍니다.

 

package com.example.spring.service.shop;

import java.util.List;

import com.example.spring.model.shop.dto.ProductDTO;

public interface ProductService {
	
	List<ProductDTO> listProduct();
	ProductDTO detailProduct(int product_id);
    
    }

 

package com.example.spring.service.shop;

import java.util.List;

import javax.inject.Inject;

import org.springframework.stereotype.Service;

import com.example.spring.model.shop.dao.ProductDAO;
import com.example.spring.model.shop.dto.ProductDTO;

@Service
public class ProductServiceImpl implements ProductService {
	
	@Inject // DI
	ProductDAO productDao;

	@Override
	public List<ProductDTO> listProduct() { // 상품 목록
		
		return productDao.listProduct();
	}

	@Override
	public ProductDTO detailProduct(int product_id) { //상품 상세 화면
		
		return productDao.detailProduct(product_id);
	}
  }

 

다음으로 DAO를 생성합니다.

 


DAO

 

DAO에서는 요청받은 값을 SQL에서 가져오거나 처리를 해줘야 합니다. 그렇다면 이전 포스팅에서 부터 응용했던 Mybatis를 활용하기 위해 mapper 파일에 id 값을 보내서 요청합니다.

 

package com.example.spring.model.shop.dao;

import java.util.List;

import com.example.spring.model.shop.dto.ProductDTO;

public interface ProductDAO {
	
	List<ProductDTO> listProduct(); // 상품 목록
	ProductDTO detailProduct(int product_id); // 상품 상세 화면
    }

 

 

package com.example.spring.model.shop.dao;

import java.util.List;

import javax.inject.Inject;

import org.apache.ibatis.session.SqlSession;
import org.springframework.stereotype.Repository;

import com.example.spring.model.shop.dto.ProductDTO;

@Repository
public class ProductDAOImpl implements ProductDAO {
	
	@Inject // DI
	SqlSession sqlSession;
	
	
	
	@Override
	public List<ProductDTO> listProduct() { // 상품 목록
		
		return sqlSession.selectList("product.product_list");
	}

	@Override
	public ProductDTO detailProduct(int product_id) { // 상품 상세 화면
		
		return sqlSession.selectOne("product.detail_product", product_id);
	}
    
}

 

미리 상품 상세 화면 작업을 한 이유는 데이터를 추가/수정/삭제를 하는 게 아니라 목록을 가져와서 출력만 하는 select라서 목록 페이지 코드 작업할 때 같이 했습니다. 

 

다음으로 mapper 파일에서 작업을 합니다.

 


mapper.xml

 

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">

<!-- 다른 mapper와 중복되지 않도록 네임스페이스 기재 -->
<mapper namespace="product">
	<select id="product_list" resultType="com.example.spring.model.shop.dto.ProductDTO">
	select * from product
	order by product_name 
	</select>
	<select id="detail_product" resultType="com.example.spring.model.shop.dto.ProductDTO">
	select * from product
	where product_id= #{product_id}
	</select>
</mapper>

 

다음으로 view단에 출력할 수 있게 페이지를 생성합니다.


product_list.jsp

 

목록 페이지는 간단하게 만들어주고, 상세 화면 페이지로 이동할 수 있게 작업을 해야 합니다. 그렇다면 미리 작업해 둔 코드를 Controller를 통해 가져와야 하기 때문에 확장자를 보내서 호출할 수도 있지만, 이번에는 해당 상품 id값을 보내서 호출해보려 합니다.

 

<%@ 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>
<%@ include file="../include/header.jsp" %>
</head>
<body>
<%@ include file="../include/menu.jsp" %>
<h2>상품 목록</h2>
<table border="1" style="width: 100%;">
  <tr>
    <th>상품 코드</th>
    <th>&nbsp;</th>
     <th>상품명</th>
    <th>가격</th>
  </tr>
  <c:forEach var="row" items="${list}">
  <tr>
    <td>${row.product_id }</td>
    <td><img src="${path }/images/${row.picture_url}" width="100px" height="100px"> </td>
    <!-- 상세 화면 페이지 이동 -->
    <td><a href="${path }/shop/product/detail/${row.product_id}">${row.product_name }</a></td>
    <td><fmt:formatNumber  value="${row.price }" pattern="#,###"/> </td>
  </tr>
  </c:forEach>
</table>
</body>
</html>

 

다음으로 Controller 에서 요청 처리를 해주고 Service단과 연결해 줍니다.

 


Controller

 

Service , DAO에서 미리 작업했기 때문에 의존 관계Service와 연결을 시켜주고, view 단 페이지만 생성해줍니다.

 

	@RequestMapping("detail/{product_id}")
	public ModelAndView detail(@PathVariable int product_id, ModelAndView mav) {
		mav.setViewName("/shop/product_detail");
		mav.addObject("dto", productService.detailProduct(product_id));
		return mav;
	}

product_detail

 

상세 화면 페이지에서는 간단하게 해당 상품 개수를 선택할 수 있는 기능을 추가하고, 다음 포스팅인 장바구니 기능 구현을 위한 submit 버튼까지만 구현해줍니다.

 

<%@ 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>
<%@ include file="../include/header.jsp" %>
</head>
<body>
<%@ include file="../include/menu.jsp" %>
<h2>상품 정보</h2>
<table>
<tr> 
	<td><img  src="${path }/images/${dto.picture_url}" width="300px" height="300px"> </td>
	<td align="center"> 
	<table>
			  <tr>
			  	<td>상품명</td>
			  	<td>${dto.product_name } </td>
			  </tr>
			    <tr>
			  	<td>가격</td>
			  	<td>${dto.price } </td>
			  </tr>
			  <tr>
			  	<td>&nbsp;</td>
			  	<td>${dto.description } </td>
			  </tr>
			  <tr>
			  <td colspan="2">
			  	<form name="form1" method="post" action="${path }/shop/cart/insert.do">
			  	<input type="hidden" name="product_id" value="${dto.product_id }">
			  	<select name="amount">
			  		<c:forEach begin="1" end="10" var="i" > <!-- 상품 개수 선택(1~10개) -->
			  			<option value="${i }">${i }</option>
			  		</c:forEach>
			  	</select>
			  	<input type="submit" value="장바구니에 담기">
			  	</form>
			   </td>
			  </tr>
	</table>
	</td>
</tr>
</table>
</body>
</html>

 


출력

 

< menu.jsp >

 

 

< 상품 목록 >

 


마치며

 

오늘은 상품 목록 페이지 구현을 알아봤습니다.

다음 포스팅은 이어서 장바구니 기능을 추가해 보겠습니다.

 

 

728x90