案例26-购物车
1 案例效果
2 案例分析
3 代码实现
1 CartItem对象
package www.test.domain; public class CartItem { private Product product; private int buyNum; private double subtotal; public Product getProduct() { return product; } public void setProduct(Product product) { this.product = product; } public int getBuyNum() { return buyNum; } public void setBuyNum(int buyNum) { this.buyNum = buyNum; } public double getSubtotal() { return subtotal; } public void setSubtotal(double subtotal) { this.subtotal = subtotal; } }
2 Cart对象
package www.test.domain; import java.util.HashMap; import java.util.Map; public class Cart { //该购物车中存储的n个购物项 private Map<String,CartItem> cartItems = new HashMap<String,CartItem>(); //商品的总计 private double total; public Map<String, CartItem> getCartItems() { return cartItems; } public void setCartItems(Map<String, CartItem> cartItems) { this.cartItems = cartItems; } public double getTotal() { return total; } public void setTotal(double total) { this.total = total; } }
3 ProductServlet对象
package www.test.web.servlet; import java.io.IOException; import java.sql.SQLException; import java.util.ArrayList; import java.util.Arrays; import java.util.LinkedList; import java.util.List; import java.util.Map; import javax.servlet.ServletException; import javax.servlet.http.Cookie; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; import com.google.gson.Gson; import redis.clients.jedis.Jedis; import www.test.domain.Cart; import www.test.domain.CartItem; import www.test.domain.Category; import www.test.domain.Product; import www.test.service.ProductService; import www.test.utils.JedisPoolUtils; import www.test.vo.PageBean; public class ProductServlet extends BaseServlet { /*public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //获得请求的哪个方法method String methodName = request.getParameter("method"); //防止非空,将productListByCid放在前面,这样就能避免 if("productListByCid".equals(methodName)){ productListByCid(request,response); }else if("categoryList".equals(methodName)){ categoryList(request,response); }else if("index".equals(methodName)){ index(request,response); }else if("productInfo".equals(methodName)){ productInfo(request,response); } } public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); }*/ // 模块中的方法是通过方法名进行区分的 // 1 显示商品类别的功能 public void categoryList(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { ProductService service = new ProductService(); // 先从缓存中查询categoryList 如果有直接使用 没有在从数据库中查询 存到缓存中 // 1、获得jedis对象 连接redis数据库 Jedis jedis = JedisPoolUtils.getJedis(); String categoryListJson = jedis.get("categoryListJson"); // 2、判断categoryListJson是否为空 if (categoryListJson == null) { System.out.println("缓存没有数据 查询数据库"); // 准备分类数据 List<Category> categoryList = null; try { categoryList = service.findAllCategory(); } catch (SQLException e) { e.printStackTrace(); } // 使用转换工具将categoryList转换成json格式 Gson gson = new Gson(); categoryListJson = gson.toJson(categoryList); // 将从数据库中获得的categoryListJson存储到缓存中 jedis.set("categoryListJson", categoryListJson); } // 将转换后的json格式字符串写出 // 写出前先解决乱码问题 response.setContentType("text/html;charset=UTF-8"); response.getWriter().write(categoryListJson); } // 2 显示首页的功能 public void index(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { ProductService service = new ProductService(); // 获取热门商品-----List<Product> List<Product> hotProductList = null; try { hotProductList = service.findHotProductList(); } catch (SQLException e) { e.printStackTrace(); } // 获取最新商品-----List<Product> List<Product> newProductList = null; try { newProductList = service.findNewProductList(); } catch (SQLException e) { e.printStackTrace(); } // 准备分类数据 /* * List<Category> categoryList =null; try { categoryList = * service.findAllCategory(); } catch (SQLException e) { * * e.printStackTrace(); } request.setAttribute("categoryList", * categoryList); */ // 将获取的数据存入request域 request.setAttribute("hotProductList", hotProductList); request.setAttribute("newProductList", newProductList); // 转发 request.getRequestDispatcher("/index.jsp").forward(request, response); } // 3 显示商品的详细信息的功能 public void productInfo(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // 获取cid和当前页 String cid = request.getParameter("cid"); String currentPage = request.getParameter("currentPage"); // 获取pid String pid = request.getParameter("pid"); // 传递给service层并调取service层的方法 ProductService service = new ProductService(); Product product = null; try { product = service.findProductByPid(pid); } catch (SQLException e) { e.printStackTrace(); } // 存储到request域中 request.setAttribute("product", product); request.setAttribute("cid", cid); request.setAttribute("currentPage", currentPage); // 获取客户端携带的cookie----获得名字是pids的cookie String pids = pid; Cookie[] cookies = request.getCookies(); if (cookies != null) { for (Cookie cookie : cookies) { if ("pids".equals(cookie.getName())) { pids = cookie.getValue(); // 1-3-2 本次访问的商品的pid是8----->8-1-3-2 // 1-3-2 本次访问的商品的pid是3----->3-1-2 // 1-3-2 本次访问的商品的pid是1----->2-1-3 // 将pids拆成一个数组 String[] split = pids.split("-");// {3,1,2} // 数组转换成集合 List<String> asList = Arrays.asList(split);// [3,1,2] LinkedList<String> list = new LinkedList<String>(asList); // [3,1,2] // 判断集合中是否存在当前的pid /* * if(list.contains(pid)){ //包含当前查看的商品的pid //先删掉然后放在头上 * list.remove(pid); list.addFirst(pid); }else{ * //不包含当前查看的商品的pid 直接将该pid放在头上 list.addFirst(pid); } */ // 上面代码的优化 // 不管包不包含都需要放到头上 if (list.contains(pid)) { // 包含当前查看的商品的pid list.remove(pid); } list.addFirst(pid); // 将[3,1,2]转成3-1-2字符串 StringBuffer sb = new StringBuffer(); for (int i = 0; i < list.size() && i < 7; ++i) { sb.append(list.get(i)); sb.append("-"); // 3-1-2- } // 去掉3-1-2-后面的- // substring包含头不包含尾 pids = sb.substring(0, sb.length() - 1); } } } // 创建cookie回写 Cookie cookie_pids = new Cookie("pids", pids); cookie_pids.setMaxAge(60 * 60); // 单位为秒 设置cookie的存储事件一个小时 // 设置cookie的携带路径 cookie_pids.setPath(request.getContextPath()); // 将cookie_pids写回去 response.addCookie(cookie_pids); // 转发 request.getRequestDispatcher("/product_info.jsp").forward(request, response); } // 4 根据商品的类别获得商品的列表 public void productListByCid(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //获取cid String cid = request.getParameter("cid"); String currentPageStr = request.getParameter("currentPage"); if(currentPageStr == null){ currentPageStr = "1"; } int currentPage = Integer.parseInt(currentPageStr); int currentCount =12; //根据cid查询商品 ProductService service = new ProductService(); PageBean<Product> pageBean = service.findProductListByCid(cid,currentPage,currentCount); request.setAttribute("pageBean", pageBean); request.setAttribute("cid", cid); //定义一个集合记录历史商品信息的集合 List<Product> historyProductList = new ArrayList<Product>(); //获取客户端携带的名字叫pids的cookie Cookie[] cookies = request.getCookies(); if(cookies!=null){ for (Cookie cookie : cookies) { if("pids".equals(cookie.getName())){ String pids = cookie.getValue(); //3-1-2 String[] split = pids.split("-"); for(String pid:split){ Product product =null; try { product = service.findProductByPid(pid); historyProductList.add(product); } catch (SQLException e) { e.printStackTrace(); } } } } } //将历史记录的集合放到域中 request.setAttribute("historyProductList", historyProductList); //转发 request.getRequestDispatcher("/product_list.jsp").forward(request, response); } // 5 将商品添加到购物车 addProductToCart public void addProductToCart(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { ProductService service = new ProductService(); HttpSession session = request.getSession(); //获得要放到购物车的商品的pid String pid = request.getParameter("pid"); //获得该商品的购买数量 int buyNum = Integer.parseInt(request.getParameter("buyNum")) ; //获得product对象 Product product = null; try { product = service.findProductByPid(pid); } catch (SQLException e) { e.printStackTrace(); } //计算小计 double subtotal = product.getShop_price()*buyNum; //封装cartItem CartItem item = new CartItem(); item.setProduct(product); item.setBuyNum(buyNum); item.setSubtotal(subtotal); //获得购物车---判断是否在session中已经存在购物车 Cart cart = (Cart) session.getAttribute("cart"); if(cart==null){ cart = new Cart(); } // 将购物项放到车中----key是pid //先判断购物车中是否已经包含此购物项目------判断key是否已经存在 //如果购物车已经存在该商品-----将现在买的数量与原有的数进行相加操作 Map<String, CartItem> cartItems = cart.getCartItems(); double newsubtotal = 0.0; if(cartItems.containsKey(pid)){ //取出原有的商品的数量 CartItem cartItem = cartItems.get(pid); int oldBuyNum = cartItem.getBuyNum(); //修改后的数量 int newBuyNum = oldBuyNum + buyNum; cartItem.setBuyNum(newBuyNum); //修改小计 //原来该商品的小计 double oldsubtotal = cartItem.getSubtotal(); //新买的该商品的小计 newsubtotal = buyNum*product.getShop_price(); cartItem.setSubtotal(newsubtotal+oldsubtotal); //修改之后重新存入 cart.setCartItems(cartItems); }else{ //如果购物车中没有该商品 cart.getCartItems().put(product.getPid(), item); newsubtotal = buyNum*product.getShop_price(); } //计算总计 double total = cart.getTotal()+newsubtotal; cart.setTotal(total); // 将车再次放入session session.setAttribute("cart", cart); //转发 直接跳转到购物车页面 转发的话,每次刷新金额都不变化不可以 //request.getRequestDispatcher("/cart.jsp").forward(request, response); response.sendRedirect(request.getContextPath()+"/cart.jsp"); } }
4 product_info.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <!DOCTYPE html> <html> <head> <meta name="viewport" content="width=device-width, initial-scale=1"> <title>会员登录</title> <link rel="stylesheet" href="css/bootstrap.min.css" type="text/css" /> <script src="js/jquery-1.11.3.min.js" type="text/javascript"></script> <script src="js/bootstrap.min.js" type="text/javascript"></script> <!-- 引入自定义css文件 style.css --> <link rel="stylesheet" href="css/style.css" type="text/css" /> <style> body { margin-top: 20px; margin: 0 auto; } .carousel-inner .item img { width: 100%; height: 300px; } </style> <script type="text/javascript"> function addCart() { //获得购买商品的数量 var buyNum = $("#buyNum").val(); location.href="${pageContext.request.contextPath }/product?method=addProductToCart&pid=${product.pid}&buyNum="+buyNum; } </script> </head> <body> <!-- 引入header.jsp --> <jsp:include page="/header.jsp"></jsp:include> <div class="container"> <div class="row"> <div style="border: 1px solid #e4e4e4; width: 930px; margin-bottom: 10px; margin: 0 auto; padding: 10px; margin-bottom: 10px;"> <a href="./index.htm">首页 ></a> <a href="./蔬菜分类.htm">蔬菜 ></a> <a>无公害蔬菜</a> </div> <div style="margin: 0 auto; width: 950px;"> <div class="col-md-6"> <img style="opacity: 1; width: 400px; height: 350px;" title="" class="medium" src="${pageContext.request.contextPath }/${product.pimage}"> </div> <div class="col-md-6"> <div> <strong>${product.pname }</strong> </div> <div style="border-bottom: 1px dotted #dddddd; width: 350px; margin: 10px 0 10px 0;"> <div>编号:${product.pid }</div> </div> <div style="margin: 10px 0 10px 0;"> 亿家价: <strong style="color: #ef0101;">¥:${product.shop_price }元/份</strong> 参 考 价: <del>¥${product.market_price }元/份</del> </div> <div style="margin: 10px 0 10px 0;"> 促销: <a target="_blank" title="限时抢购 (2014-07-30 ~ 2015-01-01)" style="background-color: #f07373;">限时抢购</a> </div> <div style="padding: 10px; border: 1px solid #e7dbb1; width: 330px; margin: 15px 0 10px 0;; background-color: #fffee6;"> <div style="margin: 5px 0 10px 0;">白色</div> <div style="border-bottom: 1px solid #faeac7; margin-top: 20px; padding-left: 10px;"> 购买数量: <input id="buyNum" name="buyNum" value="1"maxlength="4" size="10" type="text"> </div> <div style="margin: 20px 0 10px 0;; text-align: center;"> <a href="javascript:void(0);" onclick="addCart()"> <input style="background: url('./images/product.gif') no-repeat scroll 0 -600px rgba(0, 0, 0, 0); height: 36px; width: 127px;" value="加入购物车" type="button"> </a> 收藏商品 </div> </div> <a href="${pageContext.request.contextPath }/product?method=productListByCid&cid=${cid }¤tPage=${currentPage}">返回商品列表</a> </div> </div> <div class="clear"></div> <div style="width: 950px; margin: 0 auto;"> <div style="background-color: #d3d3d3; width: 930px; padding: 10px 10px; margin: 10px 0 10px 0;"> <strong>商品介绍</strong> </div> <div> <img src="${pageContext.request.contextPath }/${product.pimage}"> </div> <div style="background-color: #d3d3d3; width: 930px; padding: 10px 10px; margin: 10px 0 10px 0;"> <strong>商品参数</strong> </div> <div style="margin-top: 10px; width: 900px;"> <table class="table table-bordered"> <tbody> <tr class="active"> <th colspan="2">基本参数</th> </tr> <tr> <th width="10%">级别</th> <td width="30%">标准</td> </tr> <tr> <th width="10%">标重</th> <td>500</td> </tr> <tr> <th width="10%">浮动</th> <td>200</td> </tr> </tbody> </table> </div> <div style="background-color: #d3d3d3; width: 900px;"> <table class="table table-bordered"> <tbody> <tr class="active"> <th><strong>商品评论</strong></th> </tr> <tr class="warning"> <th>暂无商品评论信息 <a>[发表商品评论]</a></th> </tr> </tbody> </table> </div> <div style="background-color: #d3d3d3; width: 900px;"> <table class="table table-bordered"> <tbody> <tr class="active"> <th><strong>商品咨询</strong></th> </tr> <tr class="warning"> <th>暂无商品咨询信息 <a>[发表商品咨询]</a></th> </tr> </tbody> </table> </div> </div> </div> </div> <!-- 引入footer.jsp --> <jsp:include page="/footer.jsp"></jsp:include> </body> </html>
5 cart.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%> <!DOCTYPE html> <html> <head> <meta name="viewport" content="width=device-width, initial-scale=1"> <title>黑马商城购物车</title> <link rel="stylesheet" href="css/bootstrap.min.css" type="text/css" /> <script src="js/jquery-1.11.3.min.js" type="text/javascript"></script> <script src="js/bootstrap.min.js" type="text/javascript"></script> <!-- 引入自定义css文件 style.css --> <link rel="stylesheet" href="css/style.css" type="text/css" /> <style> body { margin-top: 20px; margin: 0 auto; } .carousel-inner .item img { width: 100%; height: 300px; } font { color: #3164af; font-size: 18px; font-weight: normal; padding: 0 10px; } </style> </head> <body> <!-- 引入header.jsp --> <jsp:include page="/header.jsp"></jsp:include> <div class="container"> <div class="row"> <div style="margin: 0 auto; margin-top: 10px; width: 950px;"> <strong style="font-size: 16px; margin: 5px 0;">订单详情</strong> <table class="table table-bordered"> <tbody> <tr class="warning"> <th>图片</th> <th>商品</th> <th>价格</th> <th>数量</th> <th>小计</th> <th>操作</th> </tr> <c:forEach items="${cart.cartItems }" var="entry"> <tr class="active"> <td width="60" width="40%"><input type="hidden" name="id" value="22"> <img src="${pageContext.request.contextPath }/${entry.value.product.pimage}" width="70" height="60"></td> <!--${cart.cartItems }获得是Map<String,CartItem> entry.value获得是CartItem entry.value.product获得product --> <td width="30%"><a target="_blank"> ${entry.value.product.pname}</a></td> <td width="20%">¥${entry.value.product.shop_price}</td> <td width="10%"> ${entry.value.buyNum } </td> <td width="15%"><span class="subtotal">¥${entry.value.subtotal }</span></td> <td><a href="javascript:;" class="delete">删除</a></td> </tr> </c:forEach> </tbody> </table> </div> </div> <div style="margin-right: 130px;"> <div style="text-align: right;"> <em style="color: #ff6600;"> 登录后确认是否享有优惠 </em> 赠送积分: <em style="color: #ff6600;">${cart.total }</em> 商品金额: <strong style="color: #ff6600;">¥${cart.total }元</strong> </div> <div style="text-align: right; margin-top: 10px; margin-bottom: 10px;"> <a href="order_info.htm" id="clear" class="clear">清空购物车</a> <a href="order_info.htm"> <input type="submit" width="100" value="提交订单" name="submit" border="0" style="background: url('./images/register.gif') no-repeat scroll 0 0 rgba(0, 0, 0, 0); height: 35px; width: 100px; color: white;"> </a> </div> </div> </div> <!-- 引入footer.jsp --> <jsp:include page="/footer.jsp"></jsp:include> </body> </html>