프로젝트 구조
이전 포스팅에서 상품 목록 페이지를 구현했습니다.
오늘은 장바구니 기능을 구현해 보겠습니다.
Cart Table 생성
장바구니 데이터를 담기 위한 테이블을 생성합니다.
--장바구니 테이블
create table cart (
cart_id number not null primary key,
userid varchar2(50) not null,
product_id number not null,
amount number default 0
);
테이블을 생성하고 꼭 커밋을 해주고 다음 작업으로 넘어갑니다.
DTO
테이블 생성할 때 각 칼럼 이름을 그대로 DTO에 가져와서 각 타입에 맞게 생성해 줍니다.
추가로 장바구니 테이블과 member, product 테이블과 연결을 시켜줘야 하기 때문에 필요한 키 생성해 주고 금액 계산도 할 수 있는 객체도 생성해 줍니다.
package com.example.spring.model.shop.dto;
public class CartDTO {
private int cart_id; // cart
private String userid; // cart
private String name; // member 테이블
private int product_id; // cart
private String product_name; // product 테이블
private int price; // product
private int money; // 상품 금액(계산 용도로서 테이블에는 없음)
private int amount; //cart
public int getCart_id() {
return cart_id;
}
public void setCart_id(int cart_id) {
this.cart_id = cart_id;
}
public String getUserid() {
return userid;
}
public void setUserid(String userid) {
this.userid = userid;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
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 int getMoney() {
return money;
}
public void setMoney(int money) {
this.money = money;
}
public int getAmount() {
return amount;
}
public void setAmount(int amount) {
this.amount = amount;
}
@Override
public String toString() {
return "CartDTO [cart_id=" + cart_id + ", userid=" + userid + ", name=" + name + ", product_id=" + product_id
+ ", product_name=" + product_name + ", price=" + price + ", money=" + money + ", amount=" + amount
+ "]";
}
}
menu.jsp
메뉴 페이지에 장바구니 기능을 추가하는데, 해당 페이지는 로그인 상태에서 표출될 수 있게 해 줍니다.
<%@ 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> |
<c:if test="${sessionScope.userid != null }">
<a href="${path}/shop/cart/list.do">장바구니</a> | <!-- 기능 추가 -->
</c:if>
<div style="text-align: right;">
<c:choose>
<c:when test="${sessionScope.userid == null }">
<!-- 로그인하지 않은 상태 -->
<a href="${path}/member/login.do">로그인</a> |
<a href="${path}/admin/login.do">관리자 로그인</a> |
</c:when>
<c:otherwise>
<!-- 로그인한 상태 -->
${sessionScope.name }님이 로그인중입니다.
<a href="${path}/member/logout.do">로그아웃</a> |
</c:otherwise>
</c:choose>
</div>
</div>
<hr>
다음으로 Controller 에서 요청을 받아서 작업합니다.
Controller
Controller에서는 기능이 하나씩 추가될 때마다 각 요청에 맞게 구현을 하는데, Service와 DI를 맺고 연결해 줍니다.
각 기능 코드는 다음과 같습니다.
package com.example.spring.controller.shop;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.inject.Inject;
import javax.servlet.http.HttpSession;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.servlet.ModelAndView;
import com.example.spring.model.shop.dto.CartDTO;
import com.example.spring.service.shop.CartService;
@Controller
@RequestMapping("shop/cart/*") // 공통 url
public class CartController {
@Inject
CartService cartService;
@RequestMapping("insert.do") // 세부 url
public String insert(HttpSession session , @ModelAttribute CartDTO dto) {
//세션에 userid 변수가 존재하는지 확인
String userid = (String)session.getAttribute("userid");
if(userid == null) { // 로그인 하지 않은 상태
return "redirect:/member/login.do"; // 로그인 페이지로
}
// 장바구니에 insert 처리 후 장바구니 목록으로 이동
dto.setUserid(userid);
cartService.insert(dto);
return "redirect:/shop/cart/list.do";
}
@RequestMapping("list.do")
public ModelAndView list(HttpSession session, ModelAndView mav) {
Map<String, Object> map = new HashMap<>();
//세션 변수 확인
String userid = (String)session.getAttribute("userid");
if(userid != null) { // 로그인 한 경우
List<CartDTO> list = cartService.listCart(userid);
//장바구니 합계 계산
int sumMoney = cartService.sumMoney(userid);
//배송료 계산
int fee = sumMoney >= 30000 ? 0 : 2500;
// 합계 3만원이상이면 배송료 0원
map.put("sumMoney", sumMoney);
//장바구니 합계금액
map.put("fee", fee);
// 배송료
map.put("sum", sumMoney + fee);
// 총 합계금액
map.put("list", list);
//맵에 자료 추가
map.put("count", list.size());
// 개수
mav.setViewName("shop/cart_list");
//포워딩
mav.addObject("map", map);
// 전달할 데이터
return mav;
}else { // 로그인하지 않은 경우 userid <-null
return new ModelAndView("member/login", "", null);
}
}
@RequestMapping("delete.do")
public String delete(@RequestParam int cart_id, HttpSession session) {
if(session.getAttribute("userid") != null)
cartService.delete(cart_id);
return "redirect:/shop/cart/list.do";
}
@RequestMapping("deleteAll.do")
public String deleteAll(HttpSession session) {
//세션 변수 조회
String userid=(String)session.getAttribute("userid");
if(userid != null) {
//장바구니를 비우고
cartService.deleteAll(userid);
}
//장바구니 목록으로 이동
return "redirect:/shop/cart/list.do";
}
@RequestMapping("update.do")
public String update(@RequestParam int[] amount, @RequestParam int[] cart_id, HttpSession session) {
String userid=(String)session.getAttribute("userid");
if(userid != null) {
//hidden으로 넘어오는 cart_id는 배열값으로 넘어온다.
for(int i=0; i<cart_id.length; i++) {
if(amount[i] ==0) { //수량이 0이면 레코드 삭제
cartService.delete(cart_id[i]);
}else { // 0이 아니면 수정
CartDTO dto = new CartDTO();
dto.setUserid(userid);
dto.setCart_id(cart_id[i]);
dto.setAmount(amount[i]);
cartService.modifyCart(dto);
}
}
}
return "redirect:/shop/cart/list.do";
}
}
Service
Service에서는 DAO와 연결을 시켜주고, 각 기능 타입에 맞춰서 매개변수를 보내줍니다.
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.CartDAO;
import com.example.spring.model.shop.dto.CartDTO;
@Service
public class CartServiceImpl implements CartService {
@Inject
CartDAO cartDao;
@Override
public List<CartDTO> cartMoeny() {
return null;
}
@Override
public void insert(CartDTO dto) {
cartDao.insert(dto);
}
@Override
public List<CartDTO> listCart(String userid) {
return cartDao.listCart(userid);
}
@Override
public void delete(int cart_id) {
cartDao.delete(cart_id);
}
@Override
public void deleteAll(String userid) {
cartDao.deleteAll(userid);
}
@Override
public int sumMoney(String userid) {
return cartDao.sumMoney(userid);
}
@Override
public void modifyCart(CartDTO dto) {
cartDao.modifyCart(dto);
}
}
DAO
DAO에서는 각 기능 타입별로 mapper 파일로 요청을 보냅니다.
(해당 작업은 mybatis를 활용하기 때문에 생소하신 분들은 아래 포스팅을 참고해 보세요!)
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.CartDTO;
@Repository
public class CartDAOImpl implements CartDAO {
@Inject
SqlSession sqlsession;
@Override
public List<CartDTO> cartMoeny() {
return null;
}
@Override
public void insert(CartDTO dto) {
sqlsession.insert("cart.insert", dto);
}
@Override
public List<CartDTO> listCart(String userid) {
return sqlsession.selectList("cart.listCart", userid);
}
@Override
public void delete(int cart_id) {
sqlsession.delete("cart.delete", cart_id);
}
@Override
public void deleteAll(String userid) {
sqlsession.delete("cart.deleteAll", userid);
}
@Override
public int sumMoney(String userid) {
return sqlsession.selectOne("cart.sumMoney", userid);
}
@Override
public void modifyCart(CartDTO dto) {
sqlsession.update("cart.modifyCart", dto);
}
}
mapper.xml
mapper 파일에서는 SQL문을 작성하는 페이지입니다.
원하는 데이터를 View단에서 정할 수 있게 함수 처리를 해줍니다.
<?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="cart">
<select id="listCart" resultType="com.example.spring.model.shop.dto.CartDTO">
select cart_id, m.userid, name, p.product_id, product_name,amount,price,
price*amount money
from member m, cart c, product p
where m.userid=c.userid and p.product_id=c.product_id and m.userid=#{userid}
</select>
<insert id="insert">
insert into cart(cart_id,userid,product_id,amount) values
(cart_seq.nextval,#{userid},#{product_id},#{amount})
</insert>
<select id="sumMoney" resultType="int">
select nvl(sum(price*amount), 0) money
from product p , cart c
where p.product_id=c.product_id and userid=#{userid}
</select>
<!-- 장바구니 개별 상품 삭제 -->
<delete id="delete">
delete from cart
where cart_id = #{cart_id}
</delete>
<!-- 장바구니 비우기 -->
<delete id="deleteAll">
delete from cart
where userid=#{userid}
</delete>
<!-- 장바구니 수정 -->
<update id="modifyCart">
update cart
set amount = #{amount}
where cart_id =#{cart_id}
</update>
</mapper>
cart_list.jsp
마지막으로 View단 페이지를 만들어서 화면에 표출합니다.
<%@ 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" %>
<script type="text/javascript">
$(function() {
$("#btnList").click(function() {
/*장바구니 목록으로 이동 */
location.href ="${path}/shop/product/list.do";
});
$("#btnDelete").click(function() {
if(confirm("장바구니를 비우시겠습니까?")){
location.href="${path}/shop/cart/deleteAll.do";
}
});
});
</script>
</head>
<body>
<%@ include file="../include/menu.jsp" %>
<h2>장바구니</h2>
<c:choose>
<c:when test="${map.count == 0 }">
장바구니가 비었습니다.
</c:when>
<c:otherwise>
<form name=form1 method="post" action="${path }/shop/cart/update.do">
<table border="1" style="width:100%;">
<tr >
<th>상품명</th>
<th>단가</th>
<th>수량</th>
<th>금액</th>
<th> </th>
</tr>
<c:forEach var="row" items="${map.list}">
<tr>
<td>${row.product_name }</td>
<td>${row.price }</td>
<td><input type="number" name="amount" value="${row.amount}">
<input type="hidden" name="cart_id" value="${row.cart_id }">
</td>
<td>${row.money }</td>
<td>
<c:if test="${ sessionScope.userid != null}">
<a href="${path }/shop/cart/delete.do?cart_id=${row.cart_id}">삭제</a>
</c:if>
</td>
</tr>
</c:forEach>
<tr>
<td colspan="5" align="center">
장바구니 금액 합계 : ${map.sumMoney } <br>
배송료 : ${map.fee } <br>
총 합계 : ${map.sum }
</td>
</tr>
</table>
<button id="btnUpdate">수정</button>
<button type="button" id="btnDelete">장바구니 비우기</button>
</form>
</c:otherwise>
</c:choose>
<button type="button" id="btnList">상품목록</button>
</body>
</html>
출력
< Login >
< Product_Page >
< Product_Detail >
< Cart >
배송비는 30000원 기준으로 0원, 2500원이 추가됩니다.
< Delete >
마치며
오늘은 간단한 장바구니 기능 구현을 해보았습니다.
다음 포스팅에서 뵙겠습니다.
'[ JAVA ] > JAVA Spring' 카테고리의 다른 글
[ Spring ] 상품 등록/목록 페이지 구현 (0) | 2023.04.13 |
---|---|
[ Spring ] 관리자 페이지 목록 구현 (0) | 2023.04.12 |
[ Spring ] 상품 목록 기능 구현 (0) | 2023.04.10 |
[ Spring ] 파일 업로드 테스트 구현 (0) | 2023.04.07 |
[ Spring ] 메모장 만들기(STS) (0) | 2023.04.06 |