mvcPage
WEB-INF
폴더의 shop.properties
하단에 다음의 내용을 추가/item/detail.do=kr.item.action.DetailAction
# 장바구니
/cart/write.do=kr.cart.action.WriteAction
/cart/list.do=kr.cart.action.ListAction
table.sql
하단에 다음의 내용을 추가/* 장바구니 */
CREATE TABLE zcart(
cart_num NUMBER,
item_num NUMBER NOT NULL,
order_quantity NUMBER(7) NOT NULL,
reg_date DATE NOT NULL,
mem_num NUMBER NOT NULL,
CONSTRAINT zcart_pk PRIMARY KEY (cart_num),
CONSTRAINT zcart_fk1 FOREIGN KEY (item_num) REFERENCES zitem (item_num),
CONSTRAINT zcart_fk2 FOREIGN KEY (mem_num) REFERENCES zmember (mem_num)
);
CREATE SEQUENCE zcart_seq;
DetailAction
생성package kr.item.action;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import kr.controller.Action;
import kr.item.dao.ItemDAO;
import kr.item.vo.ItemVO;
import kr.util.StringUtil;
public class DetailAction implements Action {
@Override
public String execute(HttpServletRequest request, HttpServletResponse response) throws Exception {
// 상품 번호 반환
int item_num = Integer.parseInt(request.getParameter("item_num"));
ItemDAO dao = ItemDAO.getInstance();
ItemVO item = dao.getItem(item_num);
// 줄바꿈 처리
item.setDetail(StringUtil.useBrNoHtml(item.getDetail()));
request.setAttribute("item", item);
// JSP 경로 반환
return "/WEB-INF/views/item/user_detail.jsp";
}
}
src/main/java
오른쪽 클릭하고 새 패키지 kr.cart.action
생성 후 새 클래스 WriteAction
생성package kr.cart.action;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import kr.cart.dao.CartDAO;
import kr.cart.vo.CartVO;
import kr.controller.Action;
import kr.item.dao.ItemDAO;
import kr.item.vo.ItemVO;
public class WriteAction implements Action {
@Override
public String execute(HttpServletRequest request, HttpServletResponse response) throws Exception {
HttpSession session = request.getSession();
Integer user_num = (Integer)session.getAttribute("user_num");
if(user_num==null) { // 로그인되어 있지 않은 경우
return "redirect:/member/loginForm.do";
}
// 로그인되어 있는 경우
request.setCharacterEncoding("UTF-8");
CartVO cart = new CartVO();
cart.setItem_num(Integer.parseInt(request.getParameter("item_num")));
cart.setOrder_quantity(Integer.parseInt(request.getParameter("order_quantity")));
cart.setMem_num(user_num);
CartDAO dao = CartDAO.getInstance();
CartVO cartItem = dao.getCart(cart);
if(cartItem==null) { // 같은 회원 번호, 같은 상품 번호로 등록한 정보 미존재
dao.insertCart(cart);
}
else { // 같은 회원 번호, 같은 상품 번호로 등록한 정보 존재
ItemDAO itemDao = ItemDAO.getInstance();
ItemVO item = itemDao.getItem(cartItem.getItem_num());
int order_quantity = cartItem.getOrder_quantity() + cart.getOrder_quantity(); // 기존 카트에 저장된 수량과 새로 입력한 수량 합산
if(item.getQuantity()<order_quantity) { // 상품 재고 수량보다 장바구니에 많이 담으면 오류
request.setAttribute("notice_msg", "기존에 장바구니에 담은 상품입니다. 수량을 추가하면 재고가 부족합니다.");
request.setAttribute("notice_url", request.getContextPath() + "/cart/list.do");
return "/WEB-INF/views/common/alert_singleView.jsp";
}
// 같은 회원 번호, 같은 상품 번호로 등록한 정보가 존재할 때 업데이트
cart.setOrder_quantity(order_quantity);
dao.updateCartByItem_num(cart);
}
// JSP 경로 반환
return "redirect:/cart/list.do";
}
}
ListAction
생성package kr.cart.action;
import java.util.List;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import kr.cart.dao.CartDAO;
import kr.cart.vo.CartVO;
import kr.controller.Action;
public class ListAction implements Action {
@Override
public String execute(HttpServletRequest request, HttpServletResponse response) throws Exception {
HttpSession session = request.getSession();
Integer user_num = (Integer)session.getAttribute("user_num");
if(user_num==null) { // 로그인되어 있지 않은 경우
return "redirect:/member/loginForm.do";
}
CartDAO dao = CartDAO.getInstance();
int all_total = dao.getTotalByMem_num(user_num);
List<CartVO> list = null;
if(all_total>0) {
list = dao.getListCart(user_num);
}
request.setAttribute("list", list);
request.setAttribute("all_total", all_total);
// JSP 경로 반환
return "/WEB-INF/views/cart/list.jsp";
}
}
item
폴더에 새 JSP 파일 user_detail.jsp
생성<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>상품 상세</title>
<link rel="stylesheet" href="${pageContext.request.contextPath}/css/layout.css">
<script type="text/javascript" src="${pageContext.request.contextPath}/js/jquery-3.6.0.min.js"></script>
<script type="text/javascript" src="${pageContext.request.contextPath}/js/jquery.number.min.js"></script>
<script type="text/javascript">
$(function() {
// 장바구니 상품 담기 유효성 체크
$('#item_cart').submit(function() {
if($('#order_quantity').val()=='') {
alert('수량을 입력하세요!');
$('#order_quantity').focus();
return false;
}
}); // end of submit
// 주문 수량 변경
$('#order_quantity').on('keyup mouseup', function() {
if($('#order_quantity').val()=='') {
$('#item_total_txt').text('총 주문 금액 : 0원');
return;
}
if(Number($('#item_quantity').val()) < $('#order_quantity').val()) { // Number()를 씌우지 않으면 양쪽 다 문자열로 인식해서 비교가 제대로 되지 않음
alert('수량이 부족합니다.');
$('#order_quantity').val('');
$('#item_total_txt').text('총 주문 금액 : 0원');
return;
}
let total = $('#item_price').val() * $('#order_quantity').val();
$('#item_total_txt').text('총 주문 금액 : ' + $.number(total) + '원');
}); // end of on
});
</script>
</head>
<body>
<div class="page-main">
<jsp:include page="/WEB-INF/views/common/header.jsp"/>
<h2>상품 상세</h2>
<c:if test="${item.status==1}">
<div class="result-display">
<div class="align-center">
본 상품은 판매 중지되었습니다.
<br>
<input type="button" value="상품 목록" onclick="location.href='itemList.do';">
</div>
</div>
</c:if>
<c:if test="${item.status==2}">
<h3 class="align-center">${item.name}</h3>
<div class="item-image">
<img src="${pageContext.request.contextPath}/upload/${item.photo2}" width="400">
</div>
<div class="item-detail">
<form id="item_cart" action="${pageContext.request.contextPath}/cart/write.do" method="post">
<input type="hidden" name="item_num" id="item_num" value="${item.item_num}">
<input type="hidden" name="item_price" id="item_price" value="${item.price}">
<input type="hidden" name="item_quantity" id="item_quantity" value="${item.quantity}">
<ul>
<li>
가격 : <b><fmt:formatNumber value="${item.price}"/>원</b>
</li>
<li>
재고 : <b><fmt:formatNumber value="${item.quantity}"/>개</b>
</li>
<c:if test="${item.quantity>0}">
<li>
<label for="order_quantity">구매 수량</label>
<input type="number" name="order_quantity" id="order_quantity" min="1" max="${item.quantity}" class="quantity-width">
</li>
<li>
<span id="item_total_txt">총 주문 금액 : 0원</span>
</li>
<li>
<input type="submit" value="장바구니에 담기">
</li>
</c:if>
<c:if test="${item.quantity<=0}">
<li class="align-center">
<span class="sold-out">품절</span>
</li>
</c:if>
</ul>
</form>
</div>
<hr size="1" noshade width="100%">
<p>
${item.detail}
</p>
</c:if>
</div>
</body>
</html>
common
폴더에 새 JSP 파일 alert_singleView.jsp
생성<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<script type="text/javascript">
alert('${notice_msg}');
location.href = '${notice_url}';
</script>
views
폴더의 하위 폴더로 cart
생성 후 새 JSP 파일 list.jsp
생성<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>장바구니</title>
<link rel="stylesheet" href="${pageContext.request.contextPath}/css/layout.css">
<script type="text/javascript" src="${pageContext.request.contextPath}/js/jquery-3.6.0.min.js"></script>
<script type="text/javascript">
$(function() {
// 장바구니 상품 주문 수량 변경
$('.cart-modify').on('click', function() {
let input_quantity = $(this).parent().find('input[name="order_quantity"]');
if(input_quantity.val()=='') {
alert('수량을 입력하세요!');
input_quantity.focus();
return;
}
if(input_quantity.val()<1) {
alert('상품의 최소 수량은 1입니다.');
input_quantity.val(input_quantity.attr('value'));
return;
}
// ajax 처리
$.ajax({
url:'modifyCart.do',
type:'post',
data:{
cart_num:$(this).attr('data-cartnum'),
item_num:$(this).attr('data-itemnum'),
order_quantity:input_quantity.val()
},
dataType:'json',
cache:false,
timeout:30000,
success:function(param) {
if(param.result=='logout') {
alert('로그인 후 사용하세요!');
}
else if(param.result=='noSale') {
alert('판매 중지되었습니다.');
location.href = 'list.do'; // 화면 갱신
}
else if(param.result=='noQuantity') {
alert('상품의 수량이 부족합니다.');
location.href = 'list.do'; // 화면 갱신
}
else if(param.result=='success') {
alert('담은 수량이 수정되었습니다.');
location.href='list.do'; // 화면 갱신
}
else {
alert('수정시 오류 발생!');
}
},
error:function() {
alert('네트워크 오류 발생!');
}
}); // end of ajax
}); // end of on
// 장바구니 상품 삭제
$('.cart-delete').on('click', function() {
$.ajax({
url:'deleteCart.do',
type:'post',
data:{cart_num:$(this).attr('data-cartnum')},
dataType:'json',
cache:false,
timeout:30000,
success:function(param) {
if(param.result=='logout') {
alert('로그인 후 사용하세요!');
}
else if(param.result=='success') {
alert('선택하신 상품을 삭제했습니다.');
location.href = 'list.do'; // 화면 갱신
}
else {
alert('삭제시 오류 발생!');
}
},
error:function() {
alert('네트워크 오류 발생!');
}
}); // end of ajax
}); // end of on
});
</script>
</head>
<body>
<div class="page-main">
<jsp:include page="/WEB-INF/views/common/header.jsp"/>
<h2>장바구니</h2>
<c:if test="${empty list}">
<div class="result-display">
장바구니에 담은 상품이 없습니다.
</div>
</c:if>
<c:if test="${!empty list}">
<form id="cart_order" method="post" action="${pageContext.request.contextPath}/order/orderForm.do">
<table>
<tr>
<th>상품명</th>
<th>수량</th>
<th>상품 가격</th>
<th>합계</th>
</tr>
<c:forEach var="cart" items="${list}">
<tr>
<td>
<a href="${pageContext.request.contextPath}/item/detail.do?item_num=${cart.item_num}">
<img src="${pageContext.request.contextPath}/upload/${cart.item.photo1}" width="80">
${cartitem.name}
</a>
</td>
<td class="align-center">
<c:if test="${cart.item.status==1 or cart.item.quantity<cart.order_quantity}">[판매 중지]</c:if>
<c:if test="${cart.item.status!=1 or cart.item.quantity>=cart.order_quantity}">
<input type="number" name="order_quantity" value="${cart.order_quantity}" min="1" max="99999" class="quantity-width">
<br>
<input type="button" value="변경" class="cart-modify" data-cartnum="${cart.cart_num}" data-itemnum="${cart.item_num}">
</c:if>
</td>
<td class="align-center"><fmt:formatNumber value="${cart.item.price}"/>원</td>
<td class="align-center">
<fmt:formatNumber value="${cart.sub_total}"/>원
<br>
<input type="button" value="삭제" class="cart-delete" data-cartnum="${cart.cart_num}">
</td>
</tr>
</c:forEach>
<tr>
<td colspan="3" class="align-right"><b>총 구매 금액</b></td>
<td class="align-center"><fmt:formatNumber value="${all_total}"/>원</td>
</tr>
</table>
<div class="align-center">
<input type="submit" value="구매하기">
</div>
</form>
</c:if>
</div>
</body>
</html>
common
폴더의 header.jsp
에서 <c:if test="${!empty user_num}">
태그 사이에 다음의 내용을 추가 <a href="${pageContext.request.contextPath}/cart/list.do">장바구니</a>
src/main/java
오른쪽 클릭하고 새 패키지 kr.cart.vo
생성 후 새 클래스 CartVO
생성package kr.cart.vo;
import java.sql.Date;
import kr.item.vo.ItemVO;
public class CartVO {
private int cart_num;
private int item_num;
private int order_quantity;
private Date reg_date;
private int mem_num;
private int sub_total;
private ItemVO item;
public int getCart_num() {
return cart_num;
}
public void setCart_num(int cart_num) {
this.cart_num = cart_num;
}
public int getItem_num() {
return item_num;
}
public void setItem_num(int item_num) {
this.item_num = item_num;
}
public int getOrder_quantity() {
return order_quantity;
}
public void setOrder_quantity(int order_quantity) {
this.order_quantity = order_quantity;
}
public Date getReg_date() {
return reg_date;
}
public void setReg_date(Date reg_date) {
this.reg_date = reg_date;
}
public int getMem_num() {
return mem_num;
}
public void setMem_num(int mem_num) {
this.mem_num = mem_num;
}
public int getSub_total() {
return sub_total;
}
public void setSub_total(int sub_total) {
this.sub_total = sub_total;
}
public ItemVO getItem() {
return item;
}
public void setItem(ItemVO item) {
this.item = item;
}
}
src/main/java
오른쪽 클릭하고 새 패키지 kr.cart.dao
생성 후 새 클래스 CartDAO
생성package kr.cart.dao;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.ArrayList;
import java.util.List;
import kr.cart.vo.CartVO;
import kr.item.vo.ItemVO;
import kr.util.DBUtil;
public class CartDAO {
// 싱글턴 패턴
private static CartDAO instance = new CartDAO();
public static CartDAO getInstance() {
return instance;
}
private CartDAO() {}
// 장바구니 등록
public void insertCart(CartVO cart) throws Exception {
Connection conn = null;
PreparedStatement pstmt = null;
String sql = null;
try {
// 커넥션 풀로부터 커넥션 할당
conn = DBUtil.getConnection();
// SQL문 작성
sql = "INSERT INTO zcart (cart_num, item_num, order_quantity, reg_date, mem_num) "
+ "VALUES (zcart_seq.NEXTVAL, ?, ?, SYSDATE, ?)";
// PreparedStatement 객체 생성
pstmt = conn.prepareStatement(sql);
// ?에 데이터를 바인딩
pstmt.setInt(1, cart.getItem_num());
pstmt.setInt(2, cart.getOrder_quantity());
pstmt.setInt(3, cart.getMem_num());
// SQL문 실행
pstmt.executeUpdate();
}
catch (Exception e) {
throw new Exception(e);
}
finally {
// 자원 정리
DBUtil.executeClose(null, pstmt, conn);
}
}
// 회원 번호(mem_num)별 총 구입액
public int getTotalByMem_num(int mem_num) throws Exception {
int total = 0;
Connection conn = null;
PreparedStatement pstmt = null;
ResultSet rs = null;
String sql = null;
try {
// 커넥션 풀로부터 커넥션 할당
conn = DBUtil.getConnection();
// SQL문 작성
sql = "SELECT SUM(sub_total) FROM (SELECT c.mem_num, c.order_quantity * i.price AS sub_total "
+ "FROM zcart c JOIN zitem i ON c.item_num=i.item_num) WHERE mem_num=?";
// PreparedStatement 객체 생성
pstmt = conn.prepareStatement(sql);
// ?에 데이터를 바인딩
pstmt.setInt(1, mem_num);
// SQL문을 실행해서 결과 행을 ResultSet에 담아 반환
rs = pstmt.executeQuery();
if(rs.next()) {
total = rs.getInt(1);
}
}
catch(Exception e) {
throw new Exception(e);
}
finally {
// 자원 정리
DBUtil.executeClose(rs, pstmt, conn);
}
return total;
}
// 장바구니 목록
public List<CartVO> getListCart(int mem_num) throws Exception {
List<CartVO> list = null;
Connection conn = null;
PreparedStatement pstmt = null;
ResultSet rs = null;
String sql = null;
try {
// 커넥션 풀로부터 커넥션 할당
conn = DBUtil.getConnection();
// SQL문 작성
sql = "SELECT * FROM zcart c JOIN zitem i ON c.item_num=i.item_num "
+ "WHERE c.mem_num=? ORDER BY i.item_num ASC";
// PreparedStatement 객체 생성
pstmt = conn.prepareStatement(sql);
// ?에 데이터를 바인딩
pstmt.setInt(1, mem_num);
// SQL문을 실행해서 결과 행들을 ResultSet에 담아 반환
rs = pstmt.executeQuery();
list = new ArrayList<CartVO>();
while(rs.next()) {
CartVO cart = new CartVO();
cart.setCart_num(rs.getInt("cart_num"));
cart.setItem_num(rs.getInt("item_num"));
cart.setOrder_quantity(rs.getInt("order_quantity"));
cart.setMem_num(rs.getInt("mem_num"));
ItemVO item = new ItemVO();
item.setName(rs.getString("name"));
item.setPrice(rs.getInt("price"));
item.setPhoto1(rs.getString("photo1"));
item.setQuantity(rs.getInt("quantity"));
item.setStatus(rs.getInt("status"));
// ItemVO를 CartVO에 저장
cart.setItem(item);
// sub_total 연산하기
cart.setSub_total(cart.getOrder_quantity() * item.getPrice());
list.add(cart);
}
}
catch(Exception e) {
throw new Exception(e);
}
finally {
// 자원 정리
DBUtil.executeClose(rs, pstmt, conn);
}
return list;
}
// 장바구니 상세
public CartVO getCart(CartVO cart) throws Exception {
CartVO cartSaved = null;
Connection conn = null;
PreparedStatement pstmt = null;
ResultSet rs = null;
String sql = null;
try {
// 커넥션 풀로부터 커넥션 할당
conn = DBUtil.getConnection();
// SQL문 작성
sql = "SELECT * FROM zcart WHERE item_num=? AND mem_num=?";
// PreparedStatement 객체 생성
pstmt = conn.prepareStatement(sql);
// ?에 데이터를 바인딩
pstmt.setInt(1, cart.getItem_num());
pstmt.setInt(2, cart.getMem_num());
// SQL문을 실행해서 결과 행을 ResultSet에 담아 반환
rs = pstmt.executeQuery();
if(rs.next()) {
cartSaved = new CartVO();
cartSaved.setCart_num(rs.getInt("cart_num"));
cartSaved.setItem_num(rs.getInt("item_num"));
cartSaved.setOrder_quantity(rs.getInt("order_quantity"));
}
}
catch(Exception e) {
throw new Exception(e);
}
finally {
// 자원 정리
DBUtil.executeClose(rs, pstmt, conn);
}
return cartSaved;
}
// 장바구니 수정
public void updateCart(CartVO cart) throws Exception {
Connection conn = null;
PreparedStatement pstmt = null;
String sql = null;
try {
// 커넥션 풀로부터 커넥션 할당
conn = DBUtil.getConnection();
// SQL문 작성
sql = "UPDATE zcart SET order_quantity=? WHERE cart_num=?";
// PreparedStatement 객체 생성
pstmt = conn.prepareStatement(sql);
// ?에 데이터를 바인딩
pstmt.setInt(1, cart.getOrder_quantity());
pstmt.setInt(2, cart.getCart_num());
// SQL문 실행
pstmt.executeUpdate();
}
catch(Exception e) {
throw new Exception(e);
}
finally {
// 자원 정리
DBUtil.executeClose(null, pstmt, conn);
}
}
// 장바구니 회원 번호별 수정
public void updateCartByItem_num(CartVO cart) throws Exception {
Connection conn = null;
PreparedStatement pstmt = null;
String sql = null;
try {
// 커넥션 풀로부터 커넥션 할당
conn = DBUtil.getConnection();
// SQL문 작성
sql = "UPDATE zcart SET order_quantity=? WHERE item_num=? AND mem_num=?";
// PreparedStatement 객체 생성
pstmt = conn.prepareStatement(sql);
// ?에 데이터를 바인딩
pstmt.setInt(1, cart.getOrder_quantity());
pstmt.setInt(2, cart.getItem_num());
pstmt.setInt(3, cart.getMem_num());
// SQL문 실행
pstmt.executeUpdate();
}
catch(Exception e) {
throw new Exception(e);
}
finally {
// 자원 정리
DBUtil.executeClose(null, pstmt, conn);
}
}
// 장바구니 삭제
}