프로젝트 구조
오늘은 상품 관리 할 때 필요한 목록 리스트 기능을 구현해 보겠습니다.
프로젝트 흐름은 다음과 같습니다.
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는 중간 다리 역할을 하는데, Controller는 Service와 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> </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> </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 >
< 상품 목록 >
마치며
오늘은 상품 목록 페이지 구현을 알아봤습니다.
다음 포스팅은 이어서 장바구니 기능을 추가해 보겠습니다.
'[ JAVA ] > JAVA Spring' 카테고리의 다른 글
[ Spring ] 관리자 페이지 목록 구현 (0) | 2023.04.12 |
---|---|
[ Spring ] 장바구니 기능 구현 (0) | 2023.04.11 |
[ Spring ] 파일 업로드 테스트 구현 (0) | 2023.04.07 |
[ Spring ] 메모장 만들기(STS) (0) | 2023.04.06 |
[ Spring ] Spring 용어 키워드 간단 정리 (0) | 2023.01.06 |