Spring : session과 cookie (최근 본 상품, 장바구니)

부트캠프(END)/-Spring|2022. 9. 1. 17:15

 

쿠키와 세션을 이용해서 최근 본 상품 목록 기능과 장바구니 기능을 만들어 보자.

 

 

쿠키

자동 로그인, 최신 방문 정보 출력 등의 기능을 구현하는 데에 사용되며, 로컬에 관련 정보를 저장한다.

= 각각의 브라우저를 판별할 수 있는 정보가 포함되어 있다!

세션

HTTP 프로토콜은 클라이언트와 서버 간의 상태에 대한 보존 없이,

매번 새로운 연결을 하고 요청에 대한 응답을 서버가 전송하고 나면 모든 연결이 끊어진다.

연결이 끊어지면 클라이언트의 정보도 모두 사라진다.

→ 이런 정보를 보존하기 위해서 세션을 사용한다.

즉, 서버가 클라이언트의 정보를 갖고 있는 상태를 '세션'이라고 한다.

 

 

최근 본 상품 목록 기능 만들기

 

1. 언제나처럼 일단 VO와 DAO, Mapper를 생성한다.

 

GoodsVO.java(Class)

package doo.doo.dao;

import lombok.Getter;
import lombok.Setter;

@Getter
@Setter
public class GoodsVO {
	private int no, goods_discount, price;
	private String goods_name, goods_sub, 
		goods_price, goods_first_price, goods_delivery, goods_poster;
}

 

GoodsMapper.java (Interface)

package doo.doo.mapper;
import java.util.*;
import doo.doo.dao.*;

import org.apache.ibatis.annotations.Result;
import org.apache.ibatis.annotations.Results;
import org.apache.ibatis.annotations.Select;

public interface GoodsMapper {
  @Select("SELECT no, goods_name, goods_price, goods_poster, num " +
    "FROM (SELECT no, goods_name, goods_price, goods_poster, rownum as num " +
    "FROM (SELECT /*+ INDEX_ASC(goods_all ga_no_pk)*/ no, goods_name, goods_price, goods_poster " +
    "FROM goods_all)) " +
    "WHERE num BETWEEN #{start} AND #{end} ")
  public List < GoodsVO > goodsListData(Map map);

  //	@Results({
  //		@Result(property="name",column="goods_name"),
  //		@Result(property="sub",column="goods_sub"),
  //		@Result(property="price",column="goods_price"),
  //		@Result(property="discount",column="goods_discount"),
  //		@Result(property="first_price",column="goods_first_price"),
  //		@Result(property="delivery",column="goods_delivery"),
  //		@Result(property="poster",column="goods_poster"),
  //	})

  @Select("SELECT CEIL(COUNT(*)/12.0) FROM goods_all")
  public int goodsTotalPage();

  @Select("SELECT * FROM goods_all WHERE no=#{no}")
  public GoodsVO goodsDetailData(int no);
}

 

GoodsDAO.java(Class)

package doo.doo.dao;

import java.util.List;
import java.util.Map;

import org.apache.ibatis.annotations.Select;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;

import doo.doo.mapper.GoodsMapper;

@Repository
public class GoodsDAO {
  @Autowired
  private GoodsMapper mapper;

  public List < GoodsVO > goodsListData(Map map) {
    return mapper.goodsListData(map);
  }
  public int goodsTotalPage() {
    return mapper.goodsTotalPage();
  }
  public GoodsVO goodsDetailData(int no) {
    return mapper.goodsDetailData(no);
  }
}

 

 

 

 

2. 위에서 만든 DAO 메서드를 활용해서 Controller를 작성한다.

 

우선 상품 목록과 그 하단에 쿠키를 이용한 '최근 본 상품' 목록을 함께 띄워 보자.

 

이렇게!

 

@Controller 어노테이션으로 이 자바 파일이 컨트롤러임을 알려 주고,

@Autowired로 GoodsDAO를 싱글톤 패턴으로 호출해 둔다.

 

그리고 list.do를 호출했을 때 불러올 정보!

request에서 쿠키 정보를 받아와 최신순으로 정렬한 뒤 쿠키 리스트와 상품 목록을 Model에 담아 넘겨 준다.

 

 

왜 request까지 받아오나? 

→ 쿠키는 내장 객체가 아니고 request로 생성해야 하기 때문! ==  request.getCookie()

매개변수로 사용할 수 있는 것
1. 사용자가 보낸 데이터형 (int, String, double..)
2. Servlet이 가지고 있는 내장 객체(request, response, session, application, pageContext...)
3. 기타 : Error, RedirectAttributes

 

그럼 아래와 같이 코드를 작성할 수 있다.

 

 

GoodsController.java (Class)

package doo.doo.web;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;

import java.util.*;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import doo.doo.dao.*;

@Controller
public class GoodsController {
  @Autowired
  private GoodsDAO dao; //멤버로 선언했으므로 GoodsController 내에서 계속 쓸 수 있다.

  @GetMapping("goods/list.do")
  public String goods_list(String page, Model model, HttpServletRequest request) {
  //page가 null로 들어올 수 있으므로 이런 경우에는 String으로 받는다.
    if (page == null)
      page = "1";
    int curPage = Integer.parseInt(page);
    int totalPage = dao.goodsTotalPage();

    Map map = new HashMap();
    int rowSize = 12;
    int start = (rowSize * curPage) - (rowSize - 1);
    int end = rowSize * curPage;
    map.put("start", start);
    map.put("end", end);
    List < GoodsVO > list = dao.goodsListData(map);

    for (GoodsVO vo: list) {
      String name = vo.getGoods_name();
      if (name.length() > 20) {
        name = name.substring(0, 20) + "..";
      }
      vo.setGoods_name(name);
    }
    //Cookie
    Cookie[] cookies = request.getCookies();
    List < GoodsVO > cList = new ArrayList < GoodsVO > ();
    if (cookies != null) {
      for (int i = cookies.length - 1; i >= 0; i--) {
        if (cookies[i].getName().startsWith("goods")) {
          String no = cookies[i].getValue();
          GoodsVO vo = dao.goodsDetailData(Integer.parseInt(no));
          cList.add(vo);
        }
      }
    }

    model.addAttribute("curPage", curPage);
    model.addAttribute("totalPage", totalPage);
    model.addAttribute("list", list);
    model.addAttribute("cList", cList);
    model.addAttribute("size", cList.size());

    return "goods/list";
  }

 

 

쿠키 저장

이제 쿠키를 저장해 보자!

쿠키와 HTML은 한 번에 둘 중 한 종류씩밖에 보낼 수 없다.

따라서, 상세페이지로 이동하기 전에 한 번 거쳐갈 페이지가 하나 더 필요하다.

 

여기서는 detail_before.do 와 detail.do로 구분하여

detail_before에서는 쿠키를 저장하고 detail.do로 redirect시켜 준다.

그리고 detail.do에서는 선택한 상품의 상세 정보를 출력하도록 세팅해 준다.

 

 

GoodsController.java (Class)

//쿠키 저장 (쿠키랑 HTML 한번에 하나씩밖에 못 보냄 == detail_before 필요함)
@GetMapping("goods/detail_before.do")
public String goods_detail_before(int no, HttpServletResponse response) {
  //쿠키의 단점 : 클라이언트(=브라우저)에 저장이 되는데, 문자열만 저장할 수 있다.
  Cookie cookie = new Cookie("goods" + no, String.valueOf(no));
  cookie.setPath("/"); //root에 저장
  cookie.setMaxAge(60 * 60 * 24); //하루동안 저장
  response.addCookie(cookie); //전송!
  return "redirect:detail.do?no=" + no;
}

//상세보기 - <a> 태그는 무조건 GET방식!!!
@GetMapping("goods/detail.do")
public String goods_detail(int no, Model model) {
  GoodsVO vo = dao.goodsDetailData(no);
  vo.setPrice(Integer.parseInt(vo.getGoods_price().replaceAll("[^0-9]", "").trim()));
  model.addAttribute("vo", vo);
  return "goods/detail";
}

 

 

쿠키 삭제

 

최근 본 상품의 각 항목 아래에 있는 삭제버튼을 누르면 해당 쿠키를 삭제하고,

쿠키 전체삭제 버튼을 누르면 상품과 관련된 모든 쿠키가 삭제되도록 해 보자.

 

 

쿠키 삭제는 단순히 MaxAge(유효기간)을 0으로 세팅해 주면 된다.

 

우리가 직접 생성한 쿠키 외에도 다른 쿠키가 브라우저에 저장되므로! 꼭 이름을 검색해서 처리한다.

 

한 개씩 삭제할 때는 반복문으로 쿠키를 저장할 때 지정한 이름으로 검색,

선택한 쿠키와 일치하는 이름이 나오면 삭제 후 break한다.

전체 삭제는.. 그냥 break없이 쭉 반복문을 끝내면 된다.

 

 

GoodsController.java (Class)

//쿠키 한개씩 삭제
@GetMapping("goods/cookie_delete.do")
public String goods_cookie_delete(int no, HttpServletRequest request, HttpServletResponse response) {
  Cookie[] cookies = request.getCookies();
  // 지금은 cookies가 null이 아님.
  for (int i = cookies.length - 1; i >= 0; i--) {
    if (cookies[i].getName().equals("goods" + no)) {
      cookies[i].setPath("/");
      cookies[i].setMaxAge(0);
      response.addCookie(cookies[i]);
      break;
    }
  }
  return "redirect:list.do";
}

//쿠키 전체삭제
@GetMapping("goods/cookie_all_delete.do")
public String goods_cookie_all_delete(HttpServletRequest request, HttpServletResponse response) {
  Cookie[] cookies = request.getCookies();
  for (int i = cookies.length - 1; i >= 0; i--) {
    if (cookies[i].getName().startsWith("goods")) {
      cookies[i].setPath("/");
      cookies[i].setMaxAge(0);
      response.addCookie(cookies[i]);
    }
  }
  return "redirect:list.do";
}

 

 

 

 

 

장바구니 기능 만들기 (결제X)

 

이제 상품을 장바구니에 담아 목록을 출력하도록 해 보자.

이번 예제에서 따로 DAO는 생성하지 않고, 세션에 장바구니 정보를 저장할 것이다.

 

 

1. 장바구니 목록을 구성할 CartVO 클래스를 생성한다.

 

CartVO.java (Class)

package doo.doo.dao;

import lombok.Getter;
import lombok.Setter;

@Getter
@Setter
public class CartVO {
	private int no, account, total;
	private String name, poster, price;
}

 

 

2. 그에 맞게 Controller를 작성한다.

 

이런 화면을 만들 것이다

 

장바구니 추가

 

상세 페이지에서 상품의 수량을 설정하고 "장바구니" 버튼을 누르면

session_insert.do 라는 주소를 호출하게 되고, POST 방식으로 장바구니에 담을 상품 데이터가 전송된다.

 

GoodsController.java (Class) *해당 기능과 관련된 코드만*

//장바구니 추가
@PostMapping("goods/session_insert.do")
public String goods_session_insert(int no, int account, HttpSession session, Model model) {
  List < CartVO > list = (List < CartVO > ) session.getAttribute("cart");
  //처음 이후에는 세션에 저장된 데이터를 불러옴 -> 맨 처음에만 메모리 할당을 하도록 한다.
  if (list == null) {
    list = new ArrayList < CartVO > ();
  }
  //name, poster, price
  GoodsVO vo = dao.goodsDetailData(no);
  CartVO cvo = new CartVO();
  cvo.setNo(no);
  cvo.setName(vo.getGoods_name());
  cvo.setPoster(vo.getGoods_poster());
  cvo.setPrice(vo.getGoods_price());
  cvo.setAccount(account);

  boolean bCheck = false;
  for (CartVO avo: list) {
    //이미 장바구니에 들어가 있는 상품을 또 담은 경우 수량만 증가시킨다
    if (avo.getNo() == cvo.getNo()) {
      int acc = avo.getAccount() + cvo.getAccount();
      avo.setAccount(acc);
      bCheck = true;
      break;
    }
  }
  //새로운 상품을 담은 경우
  if (bCheck == false) {
    list.add(cvo);
    session.setAttribute("cart", list);
  }
  //데이터 전송
  //		model.addAttribute("list",list);
  //		model.addAttribute("no",no);
  //redirect가 나올 때는 Model로 보내 주면 안된다. request가 초기화된 후 전송되니까...불가능함.
  return "redirect:cart_list.do?no=" + no;
}

 

 

 

장바구니 목록 출력 

 

세션에 저장된 장바구니 리스트를 불러와 Model에 담아서 화면에 출력해 준다.

 

GoodsController.java (Class) *해당 기능과 관련된 코드만*

//장바구니
@GetMapping("goods/cart_list.do")
public String goods_cart_list(int no, HttpSession session, Model model) {
  //세션 속에 저장된 장바구니 리스트를 불러 와야 함
  List < CartVO > list = (List < CartVO > ) session.getAttribute("cart");
  //데이터 전송
  model.addAttribute("no", no);
  model.addAttribute("list", list);
  return "goods/cart_list";
}

 

 

 

장바구니 삭제

 

쿠키 삭제할 때와 비슷한 로직으로 작동한다!

세션에 저장된 장바구니 리스트를 가져와 그 리스트에서 삭제해 준다.

 

GoodsController.java (Class) *해당 기능과 관련된 코드만*

@GetMapping("goods/cart_cancel.do")
public String cart_cancel(int no, HttpSession session) {
  List < CartVO > list = (List < CartVO > ) session.getAttribute("cart");
  for (int i = 0; i < list.size(); i++) {
    CartVO vo = list.get(i);
    if (vo.getNo() == no) {
      list.remove(i);
    }
  }
  return "redirect:cart_list.do?no=" + no;
}

@GetMapping("goods/cart_total_delete.do")
public String cart_total_delete(int no, HttpSession session) {
  session.removeAttribute("cart"); //cart정보만 삭제
  return "redirect:cart_list.do?no=" + no;
}

 

 

더보기
package doo.doo.web;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;

import java.util.*;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import doo.doo.dao.*;

@Controller
public class GoodsController {
  @Autowired
  private GoodsDAO dao; //멤버로 선언했으므로 GoodsController 내에서 계속 쓸 수 있다.

  @GetMapping("goods/list.do")
  public String goods_list(String page, Model model, HttpServletRequest request) {
    /*null로 들어올 수 있으므로 이런 경우에는 String으로 받는다.
    왜 request까지 받아오나? 쿠키는 내장 객체가 아니고 request로 생성해야 하기 때문임. -> request.getCookie()
    매개변수로 사용할 수 있는 것
    	1. 사용자가 보낸 데이터형 (int, String, double..)
    	2. Servlet이 가지고 있는 내장 객체(request, response, session, application, pageContext...)
    	3. 기타 : Error, RedirectAttributes
    */
    if (page == null)
      page = "1";
    int curPage = Integer.parseInt(page);
    int totalPage = dao.goodsTotalPage();

    Map map = new HashMap();
    int rowSize = 12;
    int start = (rowSize * curPage) - (rowSize - 1);
    int end = rowSize * curPage;
    map.put("start", start);
    map.put("end", end);
    List < GoodsVO > list = dao.goodsListData(map);

    for (GoodsVO vo: list) {
      String name = vo.getGoods_name();
      if (name.length() > 20) {
        name = name.substring(0, 20) + "..";
      }
      vo.setGoods_name(name);
    }
    //Cookie
    Cookie[] cookies = request.getCookies();
    List < GoodsVO > cList = new ArrayList < GoodsVO > ();
    if (cookies != null) {
      for (int i = cookies.length - 1; i >= 0; i--) {
        if (cookies[i].getName().startsWith("goods")) {
          String no = cookies[i].getValue();
          GoodsVO vo = dao.goodsDetailData(Integer.parseInt(no));
          cList.add(vo);
        }
      }
    }

    model.addAttribute("curPage", curPage);
    model.addAttribute("totalPage", totalPage);
    model.addAttribute("list", list);
    model.addAttribute("cList", cList);
    model.addAttribute("size", cList.size());

    return "goods/list";
  }

  //쿠키 저장 (쿠키랑 HTML 한번에 하나씩밖에 못 보냄 == detail_before 필요함)
  @GetMapping("goods/detail_before.do")
  public String goods_detail_before(int no, HttpServletResponse response) {
    //쿠키의 단점 : 클라이언트(=브라우저)에 저장이 되는데, 문자열만 저장할 수 있다.
    Cookie cookie = new Cookie("goods" + no, String.valueOf(no));
    cookie.setPath("/"); //root에 저장
    cookie.setMaxAge(60 * 60 * 24); //하루동안 저장
    response.addCookie(cookie); //전송!
    return "redirect:detail.do?no=" + no;
  }

  //상세보기 - <a> 태그는 무조건 GET방식!!!
  @GetMapping("goods/detail.do")
  public String goods_detail(int no, Model model) {
    GoodsVO vo = dao.goodsDetailData(no);
    vo.setPrice(Integer.parseInt(vo.getGoods_price().replaceAll("[^0-9]", "").trim()));
    model.addAttribute("vo", vo);
    return "goods/detail";
  }

  //쿠키 한개씩 삭제
  @GetMapping("goods/cookie_delete.do")
  public String goods_cookie_delete(int no, HttpServletRequest request, HttpServletResponse response) {
    Cookie[] cookies = request.getCookies();
    // 지금은 cookies가 null이 아님.
    for (int i = cookies.length - 1; i >= 0; i--) {
      if (cookies[i].getName().equals("goods" + no)) {
        cookies[i].setPath("/");
        cookies[i].setMaxAge(0);
        response.addCookie(cookies[i]);
        break;
      }
    }
    return "redirect:list.do";
  }

  //쿠키 전체삭제
  @GetMapping("goods/cookie_all_delete.do")
  public String goods_cookie_all_delete(HttpServletRequest request, HttpServletResponse response) {
    Cookie[] cookies = request.getCookies();
    for (int i = cookies.length - 1; i >= 0; i--) {
      if (cookies[i].getName().startsWith("goods")) {
        cookies[i].setPath("/");
        cookies[i].setMaxAge(0);
        response.addCookie(cookies[i]);
      }
    }
    return "redirect:list.do";
  }

  //장바구니
  @GetMapping("goods/cart_list.do")
  public String goods_cart_list(int no, HttpSession session, Model model) {
    //세션 속에 저장된 장바구니 리스트를 불러 와야 함
    List < CartVO > list = (List < CartVO > ) session.getAttribute("cart");
    //		if(list==null) {
    //			list = new ArrayList<CartVO>();
    //		}
    //데이터 전송
    model.addAttribute("no", no);
    model.addAttribute("list", list);
    return "goods/cart_list";
  }

  //장바구니 추가
  @PostMapping("goods/session_insert.do")
  public String goods_session_insert(int no, int account, HttpSession session, Model model) {
    List < CartVO > list = (List < CartVO > ) session.getAttribute("cart");
    //처음 이후에는 세션에 저장된 데이터를 불러옴 -> 맨 처음에만 메모리 할당을 하도록 한다.
    if (list == null) {
      list = new ArrayList < CartVO > ();
    }
    //name, poster, price
    GoodsVO vo = dao.goodsDetailData(no);
    CartVO cvo = new CartVO();
    cvo.setNo(no);
    cvo.setName(vo.getGoods_name());
    cvo.setPoster(vo.getGoods_poster());
    cvo.setPrice(vo.getGoods_price());
    cvo.setAccount(account);

    boolean bCheck = false;
    for (CartVO avo: list) {
      //이미 장바구니에 들어가 있는 상품을 또 담은 경우 수량만 증가시킨다
      if (avo.getNo() == cvo.getNo()) {
        int acc = avo.getAccount() + cvo.getAccount();
        avo.setAccount(acc);
        bCheck = true;
        break;
      }
    }
    //새로운 상품을 담은 경우
    if (bCheck == false) {
      list.add(cvo);
      session.setAttribute("cart", list);
    }
    //데이터 전송
    //		model.addAttribute("list",list);
    //		model.addAttribute("no",no);
    //redirect가 나올 때는 Model로 보내 주면 안된다. request가 초기화된 후 전송되니까...불가능함.
    return "redirect:cart_list.do?no=" + no;
  }

  @GetMapping("goods/cart_cancel.do")
  public String cart_cancel(int no, HttpSession session) {
    List < CartVO > list = (List < CartVO > ) session.getAttribute("cart");
    for (int i = 0; i < list.size(); i++) {
      CartVO vo = list.get(i);
      if (vo.getNo() == no) {
        list.remove(i);
      }
    }
    return "redirect:cart_list.do?no=" + no;
  }

  @GetMapping("goods/cart_total_delete.do")
  public String cart_total_delete(int no, HttpSession session) {
    session.removeAttribute("cart"); //cart정보만 삭제
    return "redirect:cart_list.do?no=" + no;
  }
}
더보기

list.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.4.1/css/bootstrap.min.css">
<style type="text/css">
.container{
  margin-top: 50px;
}
.row{
  margin : 0px auto;
  width : 100%;
}
</style>
<link rel="stylesheet" href="//code.jquery.com/ui/1.13.2/themes/base/jquery-ui.css">
<script src="https://code.jquery.com/jquery.js"></script>
<script src="https://code.jquery.com/ui/1.13.2/jquery-ui.js"></script>
<script>
  $( function() {
    $('#cookieView').on("click",function(){
      $('#dialog').dialog({
        title:'쿠키 전체보기',
        width:960,
        height:600,
        modal:true, //얘가 떠있을 땐 다른 창은 제어가 안되도록 하는것
        autoOpen:false //클릭했을때 열려야하니까
      }).dialog("open");
    })
  });
</script>
</head>
<body>
  <div class="container">
    <div class="row">
      <c:forEach var="vo" items="${list }">
        <div class="col-md-4">
            <div class="thumbnail">
              <a href="detail_before.do?no=${vo.no }">
                <img src="${vo.goods_poster }" style="width:100%">
                <div class="caption">
                  <p>${vo.goods_name }</p>
                  <p>${vo.goods_price }</p>
                </div>
              </a>
            </div>
          </div>
      </c:forEach>
    </div>
    <div style="height:20px"></div>
    <div class="row">
      <div class="text-center">
        <a href="list.do?page=${curPage>1?curPage-1:curPage }" class="btn btn-sm btn-danger">이전</a>
        ${curPage } page / ${totalPage } pages
        <a href="list.do?page=${curPage<totalPage?curPage+1:curPage }" class="btn btn-sm btn-danger">다음</a>
      </div>
    </div>
    <div style="height:50px"></div>
    <div class="row">
      <h3>최근 본 상품</h3>
      <a href="cookie_all_delete.do" class="btn btn-xs btn-danger">쿠키전체삭제</a>
      <span class="btn btn-xs btn-danger" id="cookieView">쿠키전체보기</span>
      <hr>
      <c:if test="${size<1 }">
        <span style="color:orange">방문 기록이 없습니다.</span>  
      </c:if>
      <c:if test="${size>0 }">
        <c:forEach var="c" items="${cList }" varStatus="s">
        <c:if test="${s.index<6 }">
          <div class="col-md-2">
              <div class="thumbnail">
                <a href="detail_before.do?no=${c.no }">
                  <img src="${c.goods_poster }" style="width:100%">
                  <div class="caption text-center">
                  <p><a href="cookie_delete.do?no=${c.no }" class="btn btn-xs btn-danger">삭제</a></p>
                  </div>
                </a>
                </div>
            </div>
          </c:if>
        </c:forEach>
      </c:if>
    </div>
    <div style="height:50px"></div>
  </div>
  </head>
  <div id="dialog" title="Basic dialog" style="display:none">
    <c:if test="${size<1 }">
        <span style="color:orange">방문 기록이 없습니다.</span>  
      </c:if>
      <c:if test="${size>0 }">
        <c:forEach var="c" items="${cList }" varStatus="s">
          <div class="col-md-2">
              <div class="thumbnail">
                <a href="detail_before.do?no=${c.no }">
                  <img src="${c.goods_poster }" style="width:100px;height:100px;">
                </a>
                </div>
            </div>
        </c:forEach>
      </c:if>
  </div>
</body>
</html>

dialog는 jQuery의 라이브러리이다! 쿠키전체보기 버튼을 눌렀을 때 이렇게 띄워 줌↓

 

detail.jsp

<%@ 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>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.4.1/css/bootstrap.min.css">
<style type="text/css">
.container{
  margin-top: 50px;
}
.row{
  margin : 0px auto;
  width : 800px;
}
</style>
<script type="text/javascript" src="http://code.jquery.com/jquery.js"></script>
<script type="text/javascript">
$(function(){
  $('#account').change(function(){
    let count = $(this).val();
    let price = $(this).attr("data-price");
    let totalPrice = count*price;
    console.log(totalPrice);
    
    $('#total').text(totalPrice);
    $('#goods_account').val(count);
  })
})
</script>
</head>
<body>
  <div class="container">
    <div class="row">
      <table class="table">
        <tr>
          <td width=30% class="text-center" rowspan="6">
            <img src="${vo.goods_poster }" style="width:100%">
          </td>
          <td width=70%>
            <h3>${vo.goods_name }</h3>
          </td>
        </tr>
        <tr>
          <td width=30%>${vo.goods_sub }</td>
        </tr>
        <tr>
          <td width=30%><span style="color:orange">${vo.goods_discount }%&nbsp;${vo.goods_price }</span></td>
        </tr>
        <tr>
          <td width=30%>첫구매할인가&nbsp;<span style="color:green">${vo.goods_first_price }</span></td>
        </tr>
        <tr>
          <td width=30%>배송:${vo.goods_delivery }</td>
        </tr>
        <tr>
          <td width=30%>
            수량:<input type=number id="account" max="10" min="1" data-price="${vo.price }">:<span style="color:blue;" id="total">${vo.price }</span>원
          </td>
        </tr>
        <tr>
          <td colspan="2" class="text-right">
          <form method="post" action="session_insert.do">
            <input type="hidden" name="no" id="goods_no" value="${vo.no }">
            <input type="hidden" name="account" id="goods_account">
            <button class="btn btn-sm btn-primary">장바구니</button>
            <a href="cart_list.do?no=${vo.no }" class="btn btn-sm btn-primary">장바구니 보기</a>
            <a href="list.do" class="btn btn-sm btn-primary">목록</a>
          </form>
          </td>
        </tr>
      </table>
    </div>
  </div>
</body>
</html>

ajax로 수량에 따라 금액을 자동계산해서 옆에 출력하도록 세팅했다.

 

cart_list.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.4.1/css/bootstrap.min.css">
<style type="text/css">
.container{
  margin-top: 50px;
}
.row{
  margin : 0px auto;
  width : 1200px;
}
</style>
</head>
<body>
  <div class="container">
    <div class="row">
      <h3>나의 장바구니</h3>
      <c:if test="${sessionScope.cart==null }">
        <table class="table">
          <tr>
            <td class="text-center">
              <h3>장바구니가 비었습니다.</h3>
            </td>
          </tr>
        </table>
      </c:if>
      <c:if test="${sessionScope.cart!=null }">
        <table class="table">
          <tr class="success">
            <th class="text-center">번호</th>
            <th class="text-center"></th>
            <th class="text-center">상품명</th>
            <th class="text-center">가격</th>
            <th class="text-center">수량</th>
            <th class="text-center">비고</th>
          </tr>
          <c:forEach var="vo" items="${list }">
            <tr>
              <td class="text-center">${vo.no }</td>
              <td class="text-center">
                <img src="${vo.poster }" style="width:30px;height:30px;"></td>
              <td>${vo.name }</td>
              <td class="text-center">${vo.price }</td>
              <td class="text-center">${vo.account }</td>
              <td class="text-center">
                <a href="#" class="btn btn-sm btn-success">구매</a>
                <a href="cart_cancel.do?no=${vo.no }" class="btn btn-sm btn-danger">삭제</a>
              </td>
            </tr>
          </c:forEach>
          <tr>
            <td colspan="6" class="text-right">
              <a href="cart_total_delete.do?no=${no }" class="btn btn-sm btn-danger">장바구니 전체삭제</a>
              <a href="detail.do?no=${no }" class="btn btn-sm btn-danger">상품으로 돌아가기</a>
            </td>
          </tr>
        </table>
      </c:if>
    </div>
  </div>
</body>
</html>

'부트캠프(END) > -Spring' 카테고리의 다른 글

채팅 기능 만들기  (0) 2022.09.15
Spring CURD 게시판(소스코드만 정리)  (0) 2022.08.31
Spring Web 기초  (0) 2022.08.29

댓글()