수업내용/Web

[2022.11.16.수] 국내도서, 장바구니

주니어주니 2022. 11. 16. 22:50

 

 

 

1. 국내도서 리스트, 상세정보 

 

 

1)  sample_board_books 테이블,  sample_board_book_cart_items 테이블 추가 

 

  CREATE TABLE "SAMPLE_BOARD_BOOKS" 
   (	"BOOK_NO" NUMBER(6,0) PRIMARY KEY, 
	"BOOK_TITLE" VARCHAR2(255) NOT NULL, 
	"BOOK_AUTHOR" VARCHAR2(255) NOT NULL, 
	"BOOK_PUBLISHER" VARCHAR2(255) NOT NULL, 
	"BOOK_DESCRIPTION" VARCHAR2(2000), 
    	"BOOK_IMAGE" VARCHAR2(100),
	"BOOK_PRICE" NUMBER(10,0), 
	"BOOK_DISCOUNT_PRICE" NUMBER(10,0), 
	"BOOK_STOCK" NUMBER(10,0), 
	"BOOK_ON_SELL" CHAR(1) DEFAULT 'Y', 
	"BOOK_CREATED_DATE" DATE DEFAULT SYSDATE, 
	"BOOK_UPDATED_DATE" DATE DEFAULT SYSDATE
   );

 

CREATE TABLE SAMPLE_BOARD_BOOK_CART_ITEMS (
    ITEM_NO NUMBER(6) PRIMARY KEY,
    BOOK_NO NUMBER(6) REFERENCES SAMPLE_BOARD_BOOKS (BOOK_NO),
    USER_ID VARCHAR2(20) REFERENCES SAMPLE_BOARD_USERS (USER_ID),
    ITEM_AMOUNT NUMBER(3) DEFAULT 1,
    ITEM_CREATED_DATE DATE DEFAULT SYSDATE,
    ITEM_UPDATED_DATE DATE DEFAULT SYSDATE
);

 

 

 

2) Book 객체, Dao, xml 추가

 

 

- books.xml

 

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE sqlMap PUBLIC "-//iBATIS.com//DTD SQL Map 2.0//EN" 
	"http://ibatis.apache.org/dtd/sql-map-2.dtd">
 
<sqlMap namespace="books">

	<select id="getBooks" parameterClass="com.sample.util.Pagination" resultClass="com.sample.vo.Book">
		select 
			book_no					as no,
			book_title 				as title,
			book_author 			as author,
			book_publisher			as publisher,
			book_description		as description,
			book_image				as image,
			book_price				as price,
			book_discount_price		as discount,
			book_stock				as stock,
			book_on_sell			as onSell,
			book_created_date 		as createdDate,
			book_updated_date		as updatedDate
		from 
			(select row_number() over(order by book_no desc) row_numbers, 
					book_no, book_title, book_author, book_publisher, book_description, book_image,
					book_price, book_discount_price, book_stock, book_on_sell, book_created_date, book_updated_date
			 from sample_board_books)
		where
			row_numbers between #begin# and #end#
	</select>
	
	<select id="getTotalRows" resultClass="int">
		select
			count(*)
		from
			sample_board_books
	</select>
	
	<select id="getBookByNo" parameterClass="int" resultClass="com.sample.vo.Book">
		select 
			book_no					as no,
			book_title 				as title,
			book_author 			as author,
			book_publisher			as publisher,
			book_description		as description,
			book_image				as image,
			book_price				as price,
			book_discount_price		as discount,
			book_stock				as stock,
			book_on_sell			as onSell,
			book_created_date 		as createdDate,
			book_updated_date		as updatedDate
		from
			sample_board_books
		where
			book_no = #value#
	</select>
	
</sqlMap>

 

 

- bookDao

 

package com.sample.dao;

import java.util.List;

import com.sample.util.Pagination;
import com.sample.util.SqlMapper;
import com.sample.vo.Book;

public class BookDao {

	@SuppressWarnings("unchecked")
	public List<Book> getBooks(Pagination pagination){
		return (List<Book>) SqlMapper.selectList("books.getBooks", pagination);
	}
	
	public int getTotalRows() {
		return (Integer)SqlMapper.selectOne("books.getTotalRows");
	}
	
	public Book getBookByNo(int no) {
		return (Book) SqlMapper.selectOne("books.getBookByNo",no);
	}
}

 

 

 

* 겹치는 SQL 방지 -> namespace 설정

 

1) ibatis-config.xml 맨 첫 줄에 네임스페이스 사용 활성화 

<!-- SQL 구문에 네임스페이스 사용을 활성화한다. -->
	<settings useStatementNamespaces="true" />

 

 

2) 겹치는 SQL이 있는 모든 xml 

<sqlMap namespace="books">
<sqlMap namespace="boards">
<sqlMap namespace="reviews">
<sqlMap namespace="users">

 

 

3) 모든 dao의 모든 메소드의 "id" 입력 부분에 

"books.getBooks"
"books.getTotalRows"
"books.getBookByNo"
"boards.getBoards"
....

 

 

 

 

3) 페이징처리 

 

 

* 아예 util에 Pagination 객체를 만들어놓기 

 

- Pagination 

 

package com.sample.util;

public class Pagination {

	private int rows;			// 한 화면에 표시되는 데이터 개수 
	private int pages;			// 한 화면에 표시되는 페이지번호 개수 
	private int currentPage;	// 요청한 페이지 번호
	private int totalRows;		// 전체 데이터 개수 
	
	/**
	 * 요청한 페이지번호, 전체 데이터 개수를 전달받아서 Pagination객체를 초기화한다.
	 * <p>한 화면에 표시되는 데이터 개수는 10개다.
	 * <p>한 화면에 표시되는 페이지번호 개수는 5개다.
	 * @param currentPage 요청한 페이지 번호
	 * @param totalRows 전체 데이터 개수
	 */
	public Pagination(int currentPage, int totalRows) {
		this(currentPage, totalRows, 10, 5);
	}
	
	/**
	 * 요청한 페이지번호, 전체 데이터 개수, 한 화면에 표시할 행의 개수를 전달받아서 Pagination객체를 초기화한다.
	 * <p>한 화면에 표시되는 페이지번호 개수는 5개다.
	 * @param currentPage 요청한 페이지 번호
	 * @param totalRows 전체 데이터 개수
	 * @param rows 한 화면에 표시되는 행의 개수 
	 */
	public Pagination(int currentPage, int totalRows, int rows) {
		this(currentPage, totalRows, rows, 5);
		
	}
	
	/**
	 * 요청한 페이지번호, 전체 데이터 개수, 한 화면에 표시할 행의 개수, 한 화면에 표시할 페이지번호 개수를 전달받아서 Pagination객체를 초기화한다.
	 * @param currentPage 요청한 페이지 번호
	 * @param totalRows 전체 데이터 개수
	 * @param rows 한 화면에 표시되는 행의 개수
	 * @param pages 한 화면에 표시되는 페이지번호 개수 
	 */
	public Pagination(int currentPage, int totalRows, int rows, int pages) {
		this.currentPage = currentPage;
		this.totalRows = totalRows;
		this.rows = rows;
		this.pages = pages;
	}
	
	/**
	 * 요청한 페이지번호의 조회 시작번호를 반환한다.
	 * @return
	 */
	public int getBegin() {
		return (currentPage - 1)*rows + 1;
	}
	
	/**
	 * 요청한 페이지번호의 조회 끝번호를 반환한다.
	 * @return
	 */
	public int getEnd() {
		return currentPage*rows;
	}
	
	/**
	 * 총 페이지 개수를 반환한다.
	 * @return
	 */
	public int getTotalPages() {
		return (int) Math.ceil((double) totalRows/rows);
	}
	
	/**
	 * 총 페이지 블록 개수를 반환한다.
	 * @return
	 */
	public int getTotalBlocks() {
		return (int) Math.ceil((double) getTotalPages()/pages);
	}
	
	/**
	 * 요청한 페이지번호가 속한 페이지 블록 번호를 반환한다. 
	 * @return
	 */
	public int getCurrentPageBlock() {
		return (int) Math.ceil((double) currentPage/pages);
	}
	
	/**
	 * 요청한 페이지번호가 속한 페이지 블록의 시작 페이지 번호를 반환한다. 
	 * @return
	 */
	public int getBeginPage() {
		return (getCurrentPageBlock() - 1)*pages + 1;
	}
	
	/**
	 * 요청한 페이지번호가 속한 페이지 블록의 끝 페이지 번호를 반환한다. 
	 * @return
	 */
	public int getEndPage() {
		return getCurrentPageBlock() == getTotalBlocks() ? getTotalPages() : getCurrentPageBlock()*pages;
	}
	
	/**
	 * 첫 페이지인지 여부를 반환한다.
	 * @return 첫 페이지이면 true 반환
	 */
	public boolean isFirst() {
		return currentPage <= 1;
	}
	
	/**
	 * 끝 페이지인지 여부를 반환한다.
	 * @return 끝 페이지이면 true 반환
	 */
	public boolean isLast() {
		return currentPage >= getTotalPages();
	}
	
	/**
	 * 이전 페이지 번호를 반환한다. 
	 * @return
	 */
	public int getPrevPage() {
		return currentPage - 1;
	}
	
	/**
	 * 다음 페이지 번호를 반환한다.
	 * @return
	 */
	public int getNextPage() {
		return currentPage + 1;
	}
}

 

 

- book / list.jsp 에서 페이징 처리 

 

<%@page import="com.sample.util.Pagination"%>
<%@page import="com.sample.vo.Book"%>
<%@page import="java.util.List"%>
<%@page import="com.sample.dao.BookDao"%>
<%@page import="java.util.HashMap"%>
<%@page import="java.util.Map"%>
<%@page import="com.sample.util.StringUtils"%>
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.2.2/dist/css/bootstrap.min.css" rel="stylesheet">
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.2.2/dist/js/bootstrap.bundle.min.js"></script>
<title>익명 게시판</title>
<style type="text/css">
	img.img-thumbnail {width: 53px; height: 68px;}
</style>
</head>
<body>
<jsp:include page="../common/header.jsp">
	<jsp:param name="menu" value="book"/>
</jsp:include>


<div class="container my-3">
	<h1 class="mb-3 fs-4 border p-2 bg-light">도서 리스트</h1>
	<p>도서 목록을 확인하세요.</p>
	
	<%
		// 요청파라미터에서 요청한 페이지번호를 조회한다. 
		int currentPage = StringUtils.stringToInt(request.getParameter("page"), 1);
	
		// BookDao 객체 생성
		BookDao bookDao = new BookDao();
		// 총 데이터 개수 조회 
		int totalRows = bookDao.getTotalRows();
		
		// 페이징처리에 필요한 정보를 제공하는 Pagination객체 생성 (한 페이지에 5행, 5페이지씩 표시)
		Pagination pagination = new Pagination(currentPage, totalRows, 5, 5);
		
		// 요청한 페이지 범위에 해당하는 책목록을 조회한다. 
		List<Book> bookList = bookDao.getBooks(pagination);
	%>
	
	<table class="table">
		<colgroup>
			<col width="10%">
			<col width="*">
			<col width="12%">
			<col width="15%">
			<col width="10%">
			<col width="10%">
		</colgroup>
		<thead>
			<tr>
				<th></th>
				<th>제목</th>
				<th>저자</th>
				<th>출판사</th>
				<th>가격</th>
				<th>재고수량</th>
			</tr>
		</thead>
		<tbody>
	<% 
		if(bookList.isEmpty()){
	%>
			<tr>
				<td colspan="6" class="text-center">등록된 도서가 없습니다.</td>
			</tr>
	<%
		} else { 
			for(Book book : bookList){
	%>
	
			<tr class="align-middle">
				<td><img src="../resources/images/<%=book.getImage() %>" class="img-thumbnail"></td>
				<td><a href="detail.jsp?no=<%=book.getNo() %>" class="text-decoration-none"><%=book.getTitle() %></a></td>
				<td><%=book.getAuthor() %></td>
				<td><%=book.getPublisher() %></td>
				<td><%=book.getPrice() %> 원</td>
				<td><%=book.getStock() %> 권</td>
			</tr>	
	<% 
			}
		}
	%>
		</tbody>
	</table>
	
	<%
      if (totalRows >= 0) { 
   %>
   <div aria-label="navigation">
      <ul class="pagination justify-content-center">
         <li class="page-item">
            <a class="page-link <%=pagination.isFirst() ? "disabled" : "" %>" href="list.jsp?page=<%=pagination.getPrevPage()%>">이전</a>
         </li>
   <%
      for (int number = pagination.getBeginPage(); number <= pagination.getEndPage(); number++) {
   %>
         <li class="page-item"><a class="page-link <%=currentPage == number ? "active" : "" %>" href="list.jsp?page=<%=number %>"><%=number %></a></li>
   <%
      }
   %>
         <li class="page-item">
            <a class="page-link <%=pagination.isLast() ? "disabled" : "" %>" href="list.jsp?page=<%=pagination.getNextPage() %>">다음</a>
         </li>
      </ul>
   </div>
   <%
      }
   %>
</div>
</body>
</html>

 

 

 

 

 

4) 도서상세

 

- book / detail.jsp 

 

* book / list.jsp 의 책 제목으로부터 요청받은 no를 조회

-> 책 번호에 해당하는 책 조회 

 

 

<%@page import="com.sample.vo.Book"%>
<%@page import="com.sample.dao.BookDao"%>
<%@page import="com.sample.vo.User"%>
<%@page import="com.sample.vo.Review"%>
<%@page import="com.sample.dao.ReviewDao"%>
<%@page import="java.util.List"%>
<%@page import="com.sample.vo.Board"%>
<%@page import="com.sample.dao.BoardDao"%>
<%@page import="com.sample.util.StringUtils"%>
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.9.1/font/bootstrap-icons.css">
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.2.2/dist/css/bootstrap.min.css" rel="stylesheet">
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.2.2/dist/js/bootstrap.bundle.min.js"></script>
<title>익명 게시판</title>
<style>
	textarea {
		resize: none;
	}
</style>
</head>
<body>
<jsp:include page="../common/header.jsp">
	<jsp:param name="menu" value="book"/>
</jsp:include>
<div class="container my-3">
	<h1 class="mb-3 fs-4 border p-2 bg-light">도서 상세정보</h1>
	
	<%
		int bookNo = StringUtils.stringToInt(request.getParameter("no"));
		
		BookDao bookDao = new BookDao();
		Book book = bookDao.getBookByNo(bookNo);
	%>
	
	<p>도서 상세정보를 확인하세요</p>
	<div class="row mb-3 p-2">
		<div class="col-4">
			<img src="../resources/images/<%=book.getImage() %>" class="img-thumbnail"/>
		</div>
		<div class="offset-1 col-7">
			<table class="table">
				<colgroup>
					<col width="15%">
					<col width="35%">
					<col width="15%">
					<col width="35%">
				</colgroup>
				<tbody>
					<tr>
						<th>도서번호</th>
						<td><%=book.getNo() %></td>
						<th>등록일</th>
						<td><%=StringUtils.dateToText(book.getCreatedDate()) %></td>
					</tr>
					<tr>
						<th>제목</th>
						<td colspan="3"><%=book.getTitle() %></td>
					</tr>
					<tr>
						<th>저자</th>
						<td><%=book.getAuthor() %></td>
						<th>출판사</th>
						<td><%=book.getPublisher() %></td>
					</tr>
					<tr>
						<th>할인가격</th>
						<td><strong class="text-danger"><%=StringUtils.numberToText(book.getDiscount()) %></strong> 원</td>
						<th>가격</th>
						<td><strong><%=StringUtils.numberToText(book.getPrice()) %></strong> 원</td>
					</tr>
					<tr>
						<th>재고수량</th>
						<td><%=book.getStock() %> 권</td>
						<th>판매여부</th>
						<td><%="Y".equals(book.getOnSell()) ? "판매중" : "재고없음" %></td>
					</tr>
					<tr>
						<th>소개</th>
						<td colspan="3"><%=book.getDescription() %></td>
					</tr>
				</tbody>
			</table>
			<div class="d-grid gap-2">
				<!-- 
					현재 URL : http://localhost/web-board/book/detail.jsp?no=10021
					
					요청 URL : http://localhost/web-board/cart/addItem.jsp?bookNo=10021
					요청 URL : http://localhost/web-board/order/orderform.jsp?bookNo=10021
					
					기준 URL : http://localhost/web-board/book/
					
					상대경로 : ../cart/addItem.jsp?bookNo=100121
					상대경로 : ../order/orderform.jsp?bookNo=100121
				 -->
				<a href="../cart/addItem.jsp?bookNo=<%=book.getNo() %>" class="btn btn-outline-dark fw-bold" type="button">장바구니</a>
				<a href="../order/orderform.jsp?bookNo=<%=book.getNo() %>" class="btn btn-outline-primary fw-bold" type="button">바로구매</a>
			</div>
		</div>
	</div>
	<hr />
	<div class="mb-3">
		<!-- 
			현재 URL : http://localhost/web-board/book/detail.jsp?no=10021
			요청 URL : http://localhost/web-board/book/list.jsp
			
			기준 URL : http://localhost/web-board/book/
			상대 경로 : list.jsp
		 -->
		<a href="list.jsp" class="btn btn-outline-primary float-end">목록</a>
	</div>
</div>
</body>
</html>

 

 

* 주소표기법

 

  • 절대경로
    • 경로가 "/"로 시작하는 경로 
    • url 주소에서 "http://localhost" 다음부터의 전체 경로를 작성하는 것 
    • 절대경로는 현재 페이지의 URL 주소와 상관없이 요청 URL의 주소를 작성하는 것 
      * 모든 페이지에 공통으로 포함되는 내비바의 주소는 절대경로로 지정한다. 
    • 요청 URL : http://localhost/web-board/home.jsp
                        <a href="/web-board/home.jsp">홈</a> 
    • 요청 URL : http://localhost/web-board/book/list.jsp
                        <a href="/web-board/book/list.jsp">국내도서</a>

 

  • 상대경로 
    • 경로가 "/"로 시작하지 않는 경로
    • 상대경로는 현재 페이지의 URL 주소를 기준으로 요청 URL의 주소를 작성하는 것 

    • 현재 페이지의 URL : http://localhost/web-board/home.jsp
    • 요청 URL : http://localhost/web-board/about.jsp
      * 절대경로 : <a href="/web-board/about.jsp">소개</a>
      * 상대경로 : <a href="about.jsp">소개</a>

    • 맨 마지막 / 까지가 기준

      현재 URL : http://localhost/web-board/home.jsp
      요청 URL : http://localhost/web-board/about.jsp

      기준 :  http://localhost/web-board/   +    "about.jsp"
      <a href="about.jsp">

    • 현재 URL :  http://localhost/web-board/home.jsp
      요청 URL :  http://localhost/web-board/board/list.js

      기준 :  http://localhost/web-board/   +   "board/list.jsp"
      <a href="board/list.jsp">

    • 현재 URL :  http://localhost/web-board/board/list.jsp
      요청 URL :  http://localhost/web-board/board/detail.jsp?no=100

      기준 :  http://localhost/web-board/   +   "detail.jsp?no=100"
      <a href="detail.jsp?no=100">

    • 현재 URL :  http://localhost/web-board/board/list.jsp
      요청 URL :  http://localhost/web-board/home.jsp

      기준 :  http://localhost/web-board/board/   +   "../home.jsp"
            => http://localhost/web-board/   +   "home.jsp"
      <a href="../home.jsp">

 

 

 

 

 

 

2. 장바구니 담기

 

 

1)  장바구니 (CartItem) 객체, carts.xml, CartItemDao 생성

 

- CartItem

 

package com.sample.vo;

import java.util.Date;

public class CartItem {

	private int no;
	private int bookNo;
	private String userId;
	private int amount; 
	private Date createdDate; 
	private Date updatedDate;
	
	public CartItem() {}
	public CartItem(int bookNo, String userId) {
		this.bookNo = bookNo;
		this.userId = userId;
	}
	
	public int getNo() {
		return no;
	}
	public void setNo(int no) {
		this.no = no;
	}
	public int getBookNo() {
		return bookNo;
	}
	public void setBookNo(int bookNo) {
		this.bookNo = bookNo;
	}
	public String getUserid() {
		return userId;
	}
	public void setUserid(String userid) {
		this.userId = userid;
	}
	public int getAmount() {
		return amount;
	}
	public void setAmount(int amount) {
		this.amount = amount;
	}
	public Date getCreatedDate() {
		return createdDate;
	}
	public void setCreatedDate(Date createdDate) {
		this.createdDate = createdDate;
	}
	public Date getUpdatedDate() {
		return updatedDate;
	}
	public void setUpdatedDate(Date updatedDate) {
		this.updatedDate = updatedDate;
	}
}

 

- carts.xml

 

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE sqlMap PUBLIC "-//iBATIS.com//DTD SQL Map 2.0//EN" 
	"http://ibatis.apache.org/dtd/sql-map-2.dtd">
 
<sqlMap namespace="carts">

	<insert id="insertCartItem" parameterClass="com.sample.vo.CartItem">
		insert into sample_board_book_cart_items
			(item_no, book_no, user_id)
		values
			(sample_carts_seq.nextval, #bookNo#, #userId#)
	</insert>
	
	<select id="getCartItemsByUserId" parameterClass="string" resultClass="com.sample.dto.CartItemDto">
		select
		    A.item_no as itemNo,
		    A.book_no as bookNo,
		    A.user_id as userId,
		    B.book_title as title,
		    B.book_image as image,
		    A.item_amount as amount,
		    B.book_price as price,
		    B.book_discount_price as discountPrice,
		    A.item_created_date as createdDate,
		    A.item_updated_date as updatedDate
		from 
		    sample_board_book_cart_items A, sample_board_books B
		where 
		    A.book_no = B.book_no
		    and A.user_id = #value#
	</select>
	
	
</sqlMap>

 

- CartItemDao

 

package com.sample.dao;

import java.util.List;

import com.sample.dto.CartItemDto;
import com.sample.util.SqlMapper;
import com.sample.vo.CartItem;

public class CartItemDao {
	
	public void insertCartItem(CartItem cartItem) {
		SqlMapper.insert("carts.insertCartItem", cartItem);
	}
	
	@SuppressWarnings("unchecked")
	public List<CartItemDto> getCartItemsByUserId(String userId){
		return (List<CartItemDto>) SqlMapper.selectList("carts.getCartItemsByUserId", userId);
	}
}

 

 

 

 

2) 장바구니에 담기 

 

 

 

- addItem.jstp

 

* 로그인한 사용자만 장바구니 담기 가능 

장바구니에 담을 책정보 + 사용자아이디 필요

 

 

<%@page import="com.sample.dao.CartItemDao"%>
<%@page import="com.sample.vo.CartItem"%>
<%@page import="com.sample.util.StringUtils"%>
<%@page import="com.sample.vo.User"%>
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%
	// 장바구니 아이템정보를 저장하기 위해서 책번호(요청 파라미터에서 획득),
	// 사용자아이디(세션에 저장된 사용자정보에서 획득)가 필요함 
	
	// HttpSession 객체에 "loginedUser"라는 이름으로 저장된 사용자 정보를 조회한다. (user/login.jsp에서 저장해둔 것)
	User user = (User) session.getAttribute("loginedUser");
	if(user == null){
		/*
			현재 URL : http://localhost/web-board/cart/addItem.jsp?no=10021
			요청 URL : http://localhost/web-board/user/loginform.jsp?error=deny
			
			기준 URL : http://localhost/web-board/cart/
			상대경로 : ../user/loginform.jsp?error=deny
		*/
		response.sendRedirect("../user/loginform.jsp?errer=deny");
		return;
	}
	
	// 요청파라미터에서 책번호 조회
	int bookNo = StringUtils.stringToInt(request.getParameter("bookNo"));
	// 사용자 아이디 조회 
	String userId = user.getId(); 
	
	// CartItem 객체를 생성하고, 책번호와 사용자아이디를 저장한다. (생성자)
	CartItem cartItem = new CartItem(bookNo, userId);
	
	// CartItemDao 객체를 생성하고, addCartItem(CartItem cartItem) 메소드를 실행해서 장바구니 아이템을 저장시킨다. 
	CartItemDao cartItemDao = new CartItemDao();
	cartItemDao.insertCartItem(cartItem);
	
	// 재요청 URL을 응답으로 보낸다.
	/*
		현재 URL : cart/addItem.jsp
		요청 URL : cart/list.jsp
		
		기준 URL : cart/
		상대경로 : list.jsp
	*/
	response.sendRedirect("list.jsp");
%>

 

 

 

 

 

3) 장바구니 리스트 조회하기

 

 

- 장바구니 리스트에는 

장바구니 상품 번호 (cart_items), 책 번호(cart_items), 사용자 아이디 (cart_items), 책 제목 (books), 이미지 (books), 수량 (cart_items), 가격 (books), 할인가격 (books), 등록 날짜(cart_items), 수정 날짜(cart_items)가 필요

 

- cart_items와 books 테이블 조인하기 위해 새로운 CartItemDto 객체 생성

 

 

- cart / list.jsp (장바구니 리스트)  요청 -> 장바구니 리스트 조회

 

* carts.xml 에서 사용자 아이디로 장바구니 리스트 조회하는 SQL -> 테이블 조인

  cartItemDao 에서 사용자 아이디로 장바구니 리스트 조회하는 메소드

 

* 요청객체에서 책번호만 전달 

* 사용자아이디는 세션 객체에서 획득

 

 

<%@page import="com.sample.util.StringUtils"%>
<%@page import="com.sample.dto.CartItemDto"%>
<%@page import="java.util.List"%>
<%@page import="com.sample.dao.CartItemDao"%>
<%@page import="com.sample.vo.User"%>
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%
	// 인증된 사용자 정보를 조회하고, 없으면 로그인폼 재요청, 있으면 -> 사용자아이디로 장바구니 목록 조회 가능 
	User user = (User) session.getAttribute("loginedUser");
	if (user == null) {
		response.sendRedirect("../user/loginform.jsp?error=deny");
		return;
	}
%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.2.2/dist/css/bootstrap.min.css" rel="stylesheet">
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.2.2/dist/js/bootstrap.bundle.min.js"></script>
<title>익명 게시판</title>
<style type="text/css">
	img.img-thumbnail {width: 53px; height: 68px;}
</style>
</head>
<body>
<jsp:include page="../common/header.jsp">
	<jsp:param name="menu" value="cart"/>
</jsp:include>
<div class="container my-3">
	<h1 class="mb-3 fs-4 border p-2 bg-light">장바구니 리스트</h1>
	
	<%
		// CartItemDao 객체를 생성하고, getCartItemsByUserId(String userId) 메소드를 실행해서 장바구니 아이템 목록을 조회한다. 
		CartItemDao cartItemDao = new CartItemDao();
		List<CartItemDto> dtoList = cartItemDao.getCartItemsByUserId(user.getId());
	%>
	<p>장바구니 목록을 확인하세요.</p>
	<table class="table">
		<colgroup>
			<col width="5%">
			<col width="10%">
			<col width="*">
			<col width="10%">
			<col width="15%">
			<col width="15%">
			<col width="10%">
		</colgroup>
		<thead>
			<tr>
				<th><input type="checkbox"></th>
				<th></th>
				<th>제목</th>
				<th>수량</th>
				<th>가격</th>
				<th>구매가격</th>
				<th></th>
			</tr>
		</thead>
		<tbody>
		<%
			if (dtoList.isEmpty()) {	
		%>
				<tr>
					<td colspan="7" class="text-center">장바구니에 저장된 도서정보가 없습니다.</td>
				</tr>
		<%
			} else {
				for (CartItemDto dto : dtoList) {
		%>
			<tr class="align-middle">
				<td><input type="checkbox" name="itemNo" value="<%=dto.getItemNo() %>" /></td>
				<td><img src="../resources/images/<%=dto.getImage() %>" class="img-thumbnail"></td>
				<td><a href="../book/detail.jsp?no=<%=dto.getBookNo() %>" class="text-decoration-none"><%=dto.getTitle() %></a></td>
				<td><%=dto.getAmount() %> 권</td>
				<td>
					<strong class="text-danger"><%=StringUtils.numberToText(dto.getDiscountPrice()) %> 원</strong> 
					<small>(<%=StringUtils.numberToText(dto.getPrice()) %> 원)</small>
				</td>
				<td><strong class="text-danger"><%=StringUtils.numberToText(dto.getAmount()*dto.getDiscountPrice()) %> 원</strong></td>
				<td>
					<a href="deleteItem.jsp?itemNo=<%=dto.getItemNo() %>" class="btn btn-secondary btn-sm">삭제</a>
					<a href="" class="btn btn-primary btn-sm">구매</a>
				</td>
			</tr>
		<% 
				}
			}
		%>
		</tbody>
	</table>
</div>
</body>
</html>