[ JAVA ]/JAVA Spring

[ Spring ] 장바구니 기능 구현

환이s 2023. 4. 11. 13:34
728x90


프로젝트 구조 

 

 

이전 포스팅에서 상품 목록 페이지를 구현했습니다.

오늘은 장바구니 기능을 구현해 보겠습니다.

 


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에서는 기능이 하나씩 추가될 때마다 각 요청에 맞게 구현을 하는데, ServiceDI를 맺고 연결해 줍니다.

 

각 기능 코드는 다음과 같습니다.

 

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를 활용하기 때문에 생소하신 분들은 아래 포스팅을 참고해 보세요!)

 

 

[ JSP ] Mybatis 개념 및 설정

오늘은 SQL을 좀 더 쉽게 접근하게 해 주고 코드도 간결하게 만들어주는 Mybatis에 대해서 포스팅해 보겠습니다. ■ Mybatis란? Mybatis는 개발자가 지정한 SQL, 저장 프로시저를 지원하는 프레임워크(Jav

drg2524.tistory.com

 

 

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>&nbsp;</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 >

 

 


마치며

 

오늘은 간단한 장바구니 기능 구현을 해보았습니다.

다음 포스팅에서 뵙겠습니다.

 

728x90