尚硅谷JavaWeb笔记——书城项目(第七阶段:购物车模块添加)

第七阶段-加入购物车

构建思路

加入购物车模块的功能实现说明

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ij4Svnt2-1614147662152)(/Users/gaojunsong/Library/Application Support/typora-user-images/Java学习/JAVAWeb/image-20210220100620550.png)]

商品类与购物车类的构建与测试

由上述讨论可知,在这里将购物车信息保存在session域中。这是因为每个购物车对应唯一一个用户,且在服务器中,用户信息也是保存在Session中,因此有一个session域对应唯一一个用户,也因此对应一个购物车。

进一步,根据上述的的数据库表,可以可知每一个购物车项中应当包含:商品名称、商品数量、商品单价、商品金额以及总价格。因此购物车类只需要包含上述五种成员变量即可,对应代码如下:

public class CartItem {
    private Integer id;
    private String name;
    private Integer count;
    private BigDecimal price;
    private BigDecimal totalPrice;

    public CartItem() {
    }

    public CartItem(Integer id, String name, Integer count, BigDecimal price, BigDecimal totalPrice) {
        this.id = id;
        this.name = name;
        this.count = count;
        this.price = price;
        this.totalPrice = totalPrice;
    }
  // getset方法
}

因此购物车就是包含了各种CartItem集合类,同时提供一些可以获取一些统计性的据(商品总数+商品总价)方法。此外,由于在购物车中,可能会经常出现循环遍历比较判断操作,故这里考虑使用map来作为存取数据的数据结构,其中key是商品的id,value是对应的商品项,并且用链接的HashMap来实现,对应集合类代码如下,

private Map<Integer, CartItem> items = new LinkedHashMap<>();

有了集合类,就需要定义针对该集合类的操作方法

加入购物车

**需求:在主页点击了”加入购物车按钮“**添加某个商品项目后,除了请求servlet将数据保存至session外,还需要返回添加对应商品的页面,同时需要在主页中显示”成功添加xxx商品“以及当前商品的数量。

需求分析:当点击添加购物车后,应当携带着当前被点击商品项的信息(以id作为标识符)去访问CartServlet程序,在Servlet程序中,需要将该商品信息添加至Cart类的items中(如果当前存在Cart类,就直接调用添加,否则就新建)。同时需要在index.jsp中的session域中再保存一个lastAddItem用于回显最近一次被添加到商品,Cart类中对应代码如下:

/*
 *	输入:一个带添加到商品项
 */
public void addItem(CartItem cartItem) {
  // 先查看购物车中是否已经添加过此商品,如果已添加,则数量累加,总金额更新,
  // 如果没有添加过,直接放到集合中即可
  CartItem item = items.get(cartItem.getId());

  if (item == null) {
    // 之前没添加过此商品
    items.put(cartItem.getId(), cartItem);
  }else {
    // 数量 累加
    item.setCount(item.getCount() + 1);
    // 更新总金额
    item.setTotalPrice(item.getPrice().multiply(new BigDecimal(item.getCount())));
  }
}

CartServlet程序中加入购物车模块代码如下

protected void addItem(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
  // 1.获取并处理用户输入的数据
  String id = request.getParameter("id");
  int id = WebUtils.parseInt(id, 0);

  // 2.从数据库中查询该id对应的信息,同利用该信息构造一个新的cartItem项
  Book book = bookService.queryById(id);
  CartItem cartItem = new CartItem(book.getId(), book.getName(), 1, book.getPrice(), book.getPrice());

  // 3.判断当前session中是否有cart,如果有则直接获取,否则新建并将其装入sessiong域中
  Cart cart = (Cart) request.getSession().getAttribute("cart");
  if(cart == null){
    cart = new Cart;
    request.getSession().setAttribute("cart", cart);
  }

  // 4.将step2中创建的item项装入购物车
  cart.addItem(cartItem);

  // 5.地址将最后一次添加的商品项放入session域
  request.getSession().setAttribute("lastName",cartItem.getName());

  // 6.响应重定向至原先商品所在的地址页面
  String referer = request.getHeader("Referer") //得到之前的地址
    response.sendRedireciton(referer);
}

⚠️ 回跳地址不能写死为主页,应当写成返回上一个地址

index.jsp中需要将最近一次添加入购物车的商品项回显至点击页面,同时给购物车按钮绑定单击事件

<div class="book_add">
  <button bookId="${book.id}" class="addToCart">加入购物车</button>
</div>

因此也需要添加如下内容(这里用了jQuery对象):

<c:if test="${not empty sessionScope.cart}">
  <%--购物车非空的输出--%>
  <span id="cartTotalCount">您的购物车中有${sessionScope.cart.totalCount}件商品</span>
  <div>
    您刚刚将<span style="color: red" id="cartLastName">${sessionScope.lastName}</span>加入到了购物车中
  </div>
</c:if>

<script type="text/javascript">
  $(function () {
    //给加入购物车按钮绑定单击时间
    $("button.addToCart").click(function() {
      /**
             * 在事件响应的function函数 中,有一个this对象,这个this对象,是当前正在响应事件的dom对象
             * @type {jQuery}
             */
      var bookId = $(this).attr("bookId");
      location.href = "http://localhost:8080/07_book/cartServlet?action=addItem&id=" + bookId;
    })
  })
</script>

效果图:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-7Qyv9rGD-1614147662154)(/Users/gaojunsong/Library/Application Support/typora-user-images/Java学习/JAVAWeb/image-20210221105409411.png)]

显示购物车

需求:单独一个页面用于显示已经加入购物车中的商品项,要包含商品名称、数量、单价、金额以及删除,清空等操作。且数量可以再购物车中进行修改。

因此单独定义一个cart.jsp页面,用于显示购物车中的商品,代码如下

如果当前数据为空--%>
<c:if test="${empty sessionScope.cart.items}">
  <td colspan="5"><a href="index.jsp">空!!!!!继续购物!!</a></td>
</c:if>

<%--			如果购物车非空—— 遍历输出        --%>
<c:if test="${not empty sessionScope.cart.items}">
  <c:forEach items="${sessionScope.cart.items}" var="entry">
    <tr>
      <td>${entry.value.name}</td>
      <td>
        <input class="updateCount" bookId="${entry.value.id}" type="text" value="${entry.value.count}">
      </td>
      <td>${entry.value.price}</td>
      <td>${entry.value.totalPrice}</td>
      <td><a class="deleteItem" href="cartServlet?action=deleteItem&id=${entry.value.id}">删除</a></td>
    </tr>
  </c:forEach>
</c:if>

⚠️ 对于动态生成的不止一个的标签(例如第16行的a标签),如果使用id选择器的话,由于id选择的唯一性,只有第一个id能被访问的。在这里就是只有第一个删除按钮有效。故对于动态生成的标签,应当构造class属性,并用class属性选择器来选择并绑定事件。但如果是唯一性的标签,则可以用id选择器进行绑定,例如后面提到的清空购物车。

效果图:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-z7bzRq9r-1614147662156)(/Users/gaojunsong/Library/Application Support/typora-user-images/Java学习/JAVAWeb/image-20210221111646945.png)]

删除与清空购物车

需求:在cart.jsp页面删除购物车或者清空购物车时,会有页面提示询问是否删除对应的项目。

需求分析:在cart类中删除某一项对应着items.remove(id),清空则对应着items.clear()。在servlet程序中对于删除,只需要传递id信息即可,对于清空,什么都不需要传递。对应的cart类中的方法如下:

/**
     * 删除商品项
     */   
public void deleteItem(Integer id) {
  items.remove(id);
}

/**
     * 清空购物车
     */
public void clear() {
  items.clear();
}

对应的servlet程序如下

/*
*	删除某个购物车项
*/
protected void deleteItem(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
  // 1.获取商品编号
  int id = WebUtils.parseInt(request.getParameter("id"), 0);
  // 2.从session域中获取购物车对象
  Cart cart = (Cart) request.getSession().getAttribute("cart");
  if (cart != null) {
    // 删除 对应id的 商品项
    cart.deleteItem(id);
    // 重定向回原来购物车展示页面
    String referer = request.getHeader("Referer");//得到之前的地址
    response.sendRedirect(referer);
  }
}

/*
*	清空购物车
*/
protected void clear(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
  // 1 获取购物车对象
  Cart cart = (Cart) request.getSession().getAttribute("cart");
  if (cart != null) {
    // 清空购物车
    cart.clear();
    // 重定向回原来购物车展示页面
    String referer = request.getHeader("Referer");//得到之前的地址
    response.sendRedirect(referer);
  }
}

在jsp页面中也要绑定对应的单击事件

$(function () {
  //给 删除 绑定单事件
  $(".deleteItem").click(function () {
    return confirm("确定删除" + $(this).parent().parent().find("td:first").text() + "吗?");
  });
  
  //给 清空购物车 绑定单击事件
  $("#clearCart").click(function () {
    return confirm("确定清空购物车?");
  });
})

说明这里的clearCart可以用id选择器,但deleteItem只能用class选择器。

修改购物车数据

修改购物车数据主要是在如下的输入框中进行

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-NJTIs6R3-1614147662157)(/Users/gaojunsong/Library/Application Support/typora-user-images/Java学习/JAVAWeb/image-20210221113722428.png)]

上述的输入框中需要在cart.jsp中增加一个用户数据框,默认值时当前记录在session中的商品数目

<td>
  <input class="updateCount" bookId="${entry.value.id}" type="text" value="${entry.value.count}">
</td>

对该标签绑定change事件——一律转换为dom对象

//给 输入框 change内容改变事件(省去了blur的判断)
$(".updateCount").change(function () {
  //获取商品名称
  var name = $(this).parent().parent().find("td:first").text();
  var id = $(this).attr("bookId");
  //获取商品数量
  var count = this.value;
  if (confirm("确定修改购物车中 " + name + " 的数量为:" + count + "吗?") ) {
    //发起请求。给服务器保存修改
    location.href = "http://localhost:8080/07_book/cartServlet?action=updateCount&id=" + id + "&count=" + count;
  }else {
    // defaultValue属性是表单项Dom对象的属性。它表示默认的value属性值。
    this.value = this.defaultValue;
  }
});

其他技能

累加测试

在测试cart时,添加修改应做复制粘贴,对增-删-改依次作复制粘贴累加测试,这样能最大程度上避免后面测试出现打错造成测试失败的问题。

chrome中debug

在chrome中,可以进入source中查看源码并添加断点,通过输入console.log(12314),来测试是哪一部分的代码除了问题

  • 1
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值