day11 书城项目第四阶段
第一章 添加商品进购物车
1 创建购物车模型
1.1 购物项详情类
public class CartItem {
package com.atguigu.bean;
/
包名:com.atguigu.bean
@author Chunsheng Zhang
日期2021-05-17 09:06
*/
public class CartItem {
private Integer bookId;
private String bookName;
private String imgPath;
/
商品的单价
/
private Double price;
private Integer count;
/*
购物项的金额
*/
private Double amount;
public CartItem() {<br /> }
@Override<br /> public String toString() {<br /> return "CartItem{" +<br /> "bookId=" + bookId +<br /> ", bookName='" + bookName + '\'' +<br /> ", imgPath='" + imgPath + '\'' +<br /> ", price=" + price +<br /> ", count=" + count +<br /> ", amount=" + amount +<br /> '}';<br /> }
public CartItem(Integer bookId, String bookName, String imgPath, Double price, Integer count, Double amount) {<br /> this.bookId = bookId;<br /> this.bookName = bookName;<br /> this.imgPath = imgPath;<br /> this.price = price;<br /> this.count = count;<br /> this.amount = amount;<br /> }
public Integer getBookId() {<br /> return bookId;<br /> }
public void setBookId(Integer bookId) {<br /> this.bookId = bookId;<br /> }
public String getBookName() {<br /> return bookName;<br /> }
public void setBookName(String bookName) {<br /> this.bookName = bookName;<br /> }
public String getImgPath() {<br /> return imgPath;<br /> }
public void setImgPath(String imgPath) {<br /> this.imgPath = imgPath;<br /> }
public Double getPrice() {<br /> return price;<br /> }
public void setPrice(Double price) {<br /> this.price = price;<br /> }
public Integer getCount() {<br /> return count;<br /> }
public void setCount(Integer count) {<br /> this.count = count;<br /> }
/**<br /> * 这个方法获取总价:要通过计算才能获取<br /> * @return<br /> */<br /> public Double getAmount() {<br /> return this.price*this.count;<br /> }
public void setAmount(Double amount) {<br /> this.amount = amount;<br /> }
/**<br /> * 数量+1<br /> */<br /> public void countIncrease(){<br /> this.count ++;<br /> }
/**<br /> * 数量-1<br /> */<br /> public void countDecrease(){<br /> this.count --;<br /> }<br />}
1.2 购物车类:Cart
package com.atguigu.bean;
import java.math.BigDecimal;
import java.util.HashMap;
import java.util.Map;
/
包名:com.atguigu.bean
@author Chunsheng Zhang
日期2021-05-17 09:09
*/
public class Cart {
/
存储购物车中的购物项
以购物项中的书的ID作为key,以购物项作为value
*/
private Map
/**<br /> * 将书添加进购物车<br /> * @param book<br /> */<br /> public void addBookToCart(Book book){<br /> //1. 判断购物车中是否已经有这件商品<br /> if (cartItemMap.containsKey(book.getBookId())) {<br /> //2. 如果购物车中已经有这件商品了,那么就对其数量+1<br /> itemCountIncrease(book.getBookId());<br /> }else {<br /> //3. 如果购物车中还没有这件商品,那么我们就新增一个购物项<br /> //第一次添加商品进购物车,那么数量count肯定是1,那么总价就是单价<br /> CartItem cartItem = new CartItem(book.getBookId(),book.getBookName(),book.getImgPath(),book.getPrice(),1,book.getPrice());<br /> cartItemMap.put(cartItem.getBookId(),cartItem);<br /> }<br /> }
@Override<br /> public String toString() {<br /> return "Cart{" +<br /> "cartItemMap=" + cartItemMap +<br /> '}';<br /> }
/**<br /> * 显示购物车信息,为了在Thymeleaf中便于使用OGNL表达式获取购物车的信息,<br /> * 我们的方法名要叫作getCartItemMap(),那么我们在Thymeleaf中就可以使用 .cartItemMap获取<br /> * @return<br /> */<br /> public Map<Integer,CartItem> getCartItemMap(){<br /> return cartItemMap;<br /> }
/**<br /> * 将购物车中的某个购物项的数量+1<br /> * @param bookId<br /> */<br /> public void itemCountIncrease(Integer bookId){<br /> cartItemMap.get(bookId).countIncrease();<br /> }
/**<br /> * 将购物车中的某个购物项的数量-1<br /> * @param bookId<br /> */<br /> public void itemCountDecrease(Integer bookId){<br /> CartItem cartItem = cartItemMap.get(bookId);<br /> //1.先将当前购物项的数量-1<br /> cartItem.countDecrease();<br /> //2.判断当前购物项的count是否等于0<br /> if (cartItem.getCount() == 0) {<br /> //说明要将当前购物项从购物车中移除<br /> removeCartItem(bookId);<br /> }<br /> }
/**<br /> * 从购物车中移除购物项<br /> * @param bookId<br /> */<br /> public void removeCartItem(Integer bookId){<br /> cartItemMap.remove(bookId);<br /> }
/**<br /> * 修改某个购物项的数量<br /> * @param bookId<br /> */<br /> public void updateItemCount(Integer bookId,Integer newCount){<br /> cartItemMap.get(bookId).setCount(newCount);<br /> }
/**<br /> * 获取购物车中的购物项中的商品的总数<br /> * 就是将所有购物项的count进行累加<br /> * @return<br /> */<br /> public Integer getTotalCount(){<br /> //遍历出每一个CartItem的count然后累加<br /> //方式一: 采用JDK1.8的新特性<br /> /*AtomicReference<Integer> totalCount = new AtomicReference<>(0);<br /> cartItemMap.forEach((k,cartItem) -> {<br /> totalCount.updateAndGet(v -> v + cartItem.getCount());<br /> });
return totalCount.get();*/
//方式二: 使用原生的entrySet遍历Map<br /> Integer totalCount = 0;<br /> for (Map.Entry<Integer, CartItem> cartItemEntry : cartItemMap.entrySet()) {<br /> totalCount += cartItemEntry.getValue().getCount();<br /> }<br /> return totalCount;<br /> }
/**<br /> * 获取总金额<br /> * 就是遍历出每个购物项的金额再累加<br /> * @return<br /> */<br /> public Double getTotalAmount(){<br /> //解决精度问题的核心: 就是将要进行运算的数据转成BigDecimal类型之后再计算<br /> //声明一个总金额<br /> Double totalAmount = 0.0;<br /> for (Map.Entry<Integer, CartItem> cartItemEntry : cartItemMap.entrySet()) {<br /> //cartItemEntry.getValue().getAmount()是获取每一个购物项的金额
//使用总金额加上遍历出来的购物项的金额<br /> totalAmount += cartItemEntry.getValue().getAmount();<br /> }<br /> return totalAmount;<br /> }<br />}
2. 目标
在首页点击『加入购物车』将该条图书加入『购物车』
3. 思路
首页→加入购物车→CartServlet.addCartItem()→执行添加操作→回到首页
4. 代码实现
4.1 创建CartServlet
public class CartServlet extends ModelBaseServlet {
private BookService bookService = new BookServiceImpl();
/*
添加商品进购物车
@param request
@param response
*/
public void addCartItem(HttpServletRequest request, HttpServletResponse response){
try {
//1. 获取请求参数id的值
Integer id = Integer.valueOf(request.getParameter(“id”));
//2. 调用bookService的方法根据id查询book信息
Book book = bookService.getBookById(id);
//3. 尝试从会话域中获取购物车
HttpSession session = request.getSession();
Cart cart = (Cart) session.getAttribute(“cart”);
//4. 判断之前是否已经添加过购物车了
if (cart == null) {
//说明这是第一次添加购物车
//那么就要新创建一个购物车对象
cart = new Cart();
//然后将当前book加入到这个购物车
cart.addBookToCart(book);
//然后将cart存入到session
session.setAttribute(“cart”,cart);
}else {
//说明不是第一次添加购物车
//那么就直接用之前的购物车,添加当前book就行
cart.addBookToCart(book);
}
//跳转到首页<br /> response.sendRedirect(request.getContextPath()+"/index.html");<br /> } catch (Exception e) {<br /> e.printStackTrace();<br /> }<br /> }<br />}
4.2 index.html页面
购物车数量显示:
加入购物车:
加入购物车
4.3 CSS样式
.books-list .list-content .list-item a {
display: block;
width: 80px;
height: 30px;
border: none;
line-height: 30px;
background-color: #39987c;
margin-top: 5px;
outline: none;
color: #fff;
cursor:pointer;
font-size:12px;
text-align:center;
}
如果修改完成后页面效果没有改变,可以使用Ctrl+F5强制刷新。
第二章 显示购物车页面
1目标
把购物车信息在专门的页面显示出来
2思路
首页→购物车超链接→CartServlet.showCart()→cart.html
3代码实现
3.1 购物车超链接
登录状态和未登录状态
3.2 CartServlet
/*
跳转到显示购物车列表的页面
@param request
@param response
*/
public void toCartPage(HttpServletRequest request,HttpServletResponse response) throws IOException {
processTemplate(“cart/cart”,request,response);
}
3.3 cart.html
<th>数量</th><br /> <th>单价</th><br /> <th>金额</th><br /> <th>操作</th><br /> </tr><br /> </thead><br /> <tbody th:if="${session.cart == null}"><br /> <tr><br /> <td th:colspan="6"><br /> <a href="index.html">购物车空空如也,请抓紧购物吧!!!!</a><br /> </td><br /> </tr><br /> </tbody><br /> <tbody th:if="${session.cart != null}"><br /> <tr th:each="cartItemEntry : ${session.cart.cartItemMap}"><br /> <td><br /> <img th:src="${cartItemEntry.value.imgPath}" alt="" /><br /> </td><br /> <td th:text="${cartItemEntry.value.bookName}">活着</td><br /> <td><br /> <a class="count" th:href="#">-</a><br /> <input class="count-num" type="text" th:value="${cartItemEntry.value.count}" value="1" /><br /> <input type="hidden" th:value="${cartItemEntry.value.bookId}"/><br /> <a class="count" th:href="#">+</a><br /> </td><br /> <td th:text="${cartItemEntry.value.price}">36.8</td><br /> <td th:text="${cartItemEntry.value.amount}">36.8</td><br /> <td><a th:href="#">删除</a></td><br /> </tr><br /> </tbody><br /></table><br /><div><br /> <div class="footer" th:if="${session.cart != null}"><br /> <div class="footer-left"><br /> <a href="#" class="clear-cart">清空购物车</a><br /> <a href="#">继续购物</a><br /> </div><br /> <div class="footer-right"><br /> <div>共<span th:text="${session.cart.totalCount}">3</span>件商品</div><br /> <div class="total-price">总金额<span th:text="${session.cart.totalAmount}">99.9</span>元</div><br /> <a class="pay" href="pages/cart/checkout.html">去结账</a><br /> </div><br /> </div><br /></div>
第三章 清空购物车
1 目标
当用户确定点击清空购物车,将Session域中的Cart对象移除。
2 思路
cart.html→清空购物车超链接→绑定单击响应函数→confirm()确认→确定→CartServlet.clearCart()→从Session域移除Cart对象
3 代码实现
3.1 清空购物车超链接
3.2 CartServlet.cleanCart()
/*
清空购物车
@param request
@param response
@throws IOException
/
public void cleanCart(HttpServletRequest request,HttpServletResponse response) throws IOException {
//就是移除掉session中的cart就行了
request.getSession().removeAttribute(“cart”);
//跳转到购物车展示页面
processTemplate(“cart/cart”,request,response);
}
第四章 减号
1. 目标
- 在大于1的数值基础上-1:执行-1的逻辑
- 在1的基础上-1:执行删除item的逻辑
2. 思路
减号a标签绑定单击响应函数→获取文本框中的数据:当前数量→检查数量是否等于1,如果它等于1的话,则弹出一个确认框,询问其是否想删除?如果不想删除,则阻止a标签的事件
3. 后端代码
CartServlet.countDecrease()方法
/*
购物车中某个一个购物项的数量-1
@param request
@param response
@throws IOException
/
public void countDecrease(HttpServletRequest request,HttpServletResponse response) throws IOException {
//1. 获取到要-1的书的id
Integer id = Integer.valueOf(request.getParameter(“id”));
//2. 从session中获取购物车信息
Cart cart = (Cart) request.getSession().getAttribute(“cart”);
//3. 调用购物车的-1方法
cart.itemCountDecrease(id);
//4. 跳转回到购物车页面
processTemplate(“cart/cart”,request,response);
}
4. 前端代码
HTML代码给“减号”设置访问路径以及绑定点击事件:
需要注意:只能使用onclick绑定不能使用Vue绑定(通过实践得出的)
-
js代码:
第四章 删除
1. 目标
点击删除超链接后,把对应的CartItem从Cart中删除
2. 思路
cart.html→删除超链接→CartServlet.removeCartItem()→回到cart.html
需要注意:删除之前要确认
3. 代码实现
3.1 后端代码
CartServlet.removeCartItem()
/*
删除购物项
@param request
@param response
@throws IOException
/
public void removeCartItem(HttpServletRequest request,HttpServletResponse response) throws IOException {
//1. 获取要删除的购物项的书的id
Integer id = Integer.valueOf(request.getParameter(“id”));
//2.从session中获取购物车
Cart cart = (Cart) request.getSession().getAttribute(“cart”);
//3. 调用cart的删除购物项的方法
cart.removeCartItem(id);
//4. 跳转回到购物车页面
processTemplate(“cart/cart”,request,response);
}
3.2 前端代码
HTML代码:
Vue代码:
var vue = new Vue({
“el”:”#app”,
“methods”:{
deleteCartItem(){<br /> //想办法使用JavaScript获取要删除的购物项的书名<br /> //event.target就表示获取当前事件的标签<br /> var bookName = event.target.parentElement.parentElement.getElementsByTagName("td")[1].innerText;<br /> if (!confirm("你确定要删除这个"+bookName+"吗?")) {<br /> event.preventDefault()<br /> }<br /> }<br /> }<br />});
第五章 文本框修改
1. 目标
用户在文本框输入新数据后,根据用户输入在Session中的Cart中修改CartItem中的count
2. 思路
cart.html→前端数据校验→CartServlet.updateCartItemCount()→回到cart.html
3. 代码实现
3.1 后端代码
CartServlet.updateCartItemCount()
/*
修改购物项的数量
@param request
@param response
@throws IOException
/
public void updateCartItemCount(HttpServletRequest request,HttpServletResponse response) throws IOException {
//1. 获取请求参数:id,newCount
Integer id = Integer.valueOf(request.getParameter(“id”));
Integer newCount = Integer.valueOf(request.getParameter(“newCount”));
//2. 从session中获取购物车信息
Cart cart = (Cart) request.getSession().getAttribute(“cart”);
//3. 调用cart中跟新数量的方法
cart.updateItemCount(id,newCount);
//4. 跳转到购物车页面<br /> processTemplate("cart/cart",request,response);<br />}
3.2 前端代码
HTML代码:
Vue代码:
var vue = new Vue({
“el”:”#app”,
“methods”:{
updateCartItemCount(){
//获取bookId
var bookId = event.target.nextElementSibling.value;
//获取newCount
var newCount = event.target.value;
//校验newCount的格式是否正确<br /> var reg = /^[1-9][0-9]*$/
if (reg.test(newCount)) {<br /> //发送请求携带请求参数<br /> location.href = "cart?method=updateCartItemCount&id="+bookId+"&newCount="+newCount
}else {<br /> alert("请输入正确的数量")<br /> }<br /> }<br /> }<br />});
第六章 加号
1. 目标
告诉Servlet将Session域中Cart对象里面对应的CartItem执行count+1操作
2. 思路
加号span绑定单击响应函数→获取文本框中的数据:当前数量→CartServlet.countIncrease()→回到cart.html
3. 代码实现
3.1 后端代码
CartServlet.countIncrease()
/*
购物车中某个一个购物项的数量+1
@param request
@param response
@throws IOException
/
public void countIncrease(HttpServletRequest request,HttpServletResponse response) throws IOException {
//1. 获取到要-+1的书的id
Integer id = Integer.valueOf(request.getParameter(“id”));
//2. 从session中获取购物车信息
Cart cart = (Cart) request.getSession().getAttribute(“cart”);
//3. 调用购物车的+1方法
cart.itemCountIncrease(id);
//4. 跳转回到购物车页面
processTemplate(“cart/cart”,request,response);
}
3.2 前端代码
HTML代码:
+
第七章 Double数据运算过程中精度调整
1. 问题现象
2. 解决方案
- 使用BigDecimal类型来进行Double类型数据运算
- 创建BigDecimal类型对象时将Double类型的数据转换为字符串
Cart类:
/*
获取总金额
@return
/
public Double getTotalAmount(){
//解决精度问题的核心: 就是将要进行运算的数据转成BigDecimal类型之后再计算
//声明一个总金额
BigDecimal bigDecimalTotalAmount = new BigDecimal(“0.0”);
for (Map.Entry
//cartItemEntry.getValue().getAmount()是获取每一个购物项的金额
//使用总金额加上遍历出来的购物项的金额<br /> bigDecimalTotalAmount = bigDecimalTotalAmount.add(new BigDecimal(cartItemEntry.getValue().getAmount() + ""));<br /> }<br /> return bigDecimalTotalAmount.doubleValue();<br />}<br />CartItem类:<br />/**<br /> * 这个方法获取总价:要通过计算才能获取<br /> * @return<br /> */<br />public Double getAmount() {<br /> //1. 将price和count封装成BigDecimal类型<br /> BigDecimal bigDecimalPrice = new BigDecimal(price + "");<br /> BigDecimal bigDecimalCount = new BigDecimal(count + "");
//2. 使用bigDecimal的方法进行乘法<br /> return bigDecimalCount.multiply(bigDecimalPrice).doubleValue();<br />}
图片 | 商品名称 | 删除 |
---|