Thymeleaf在服务器端渲染的过程中将购物车总数量计算得到,通过表达式设置写入JavaScript代码,作为Vue对象的初始值。然后由Vue对象通过v-show判断是否显示数量标签。
###### 2.2.3 创建Vue对象
var vue = new Vue({
"el": "#app",
"data": {
"totalCount": [[${(session.cart == null)?"0":session.cart.totalCount}]]
}
});
##### 2.3 图书列表div绑定Vue对象
###### 2.3.1 绑定单击响应函数
给加入购物车按钮绑定单击响应函数
加入购物车Vue代码:
var vue = new Vue({
"el":"#app",
"data": {
"totalCount": [[${(session.cart == null)?"0":session.cart.totalCount}]]
},
"methods":{
addCartItem(bookId){
//发送异步请求
axios({
"method":"post",
"url":"protected/cart",
"params":{
"method":"addCartItem",
"id":bookId
}
}).then(response=>{
if (response.data.flag) {
this.totalCount = response.data.resultData
//弹框
layer.msg("加入购物车成功")
}else {
if(response.data.message == "unlogin"){
//表示用户未登录
layer.msg("请先登录再添加购物车")
//延时一秒
setTimeout(function () {
//跳转到登录页面
location.href = "user?method=toLoginPage"
},1000)
}else {
//添加失败
layer.msg(response.data.message)
}
}
})
}
}
});
##### 2.4 后端代码
CartServlet
/**
* 添加商品进购物车
* @param request
* @param response
*/
public void addCartItem(HttpServletRequest request, HttpServletResponse response) {
CommonResult commonResult = null;
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(BookStoreConstants.CARTSESSIONKEY);
//4. 判断之前是否已经添加过购物车了
if (cart == null) {
//说明这是第一次添加购物车
//那么就要新创建一个购物车对象
cart = new Cart();
//然后将当前book加入到这个购物车
cart.addBookToCart(book);
//然后将cart存入到session
session.setAttribute(BookStoreConstants.CARTSESSIONKEY, cart);
} else {
//说明不是第一次添加购物车
//那么就直接用之前的购物车,添加当前book就行
cart.addBookToCart(book);
}
//添加购物车成功
//获取购物车中的商品数量cart.getTotalCount()
commonResult = CommonResult.ok().setResultData(cart.getTotalCount());
} catch (Exception e) {
e.printStackTrace();
//添加购物车失败
commonResult = CommonResult.error().setMessage("添加购物车失败");
}
JsonUtils.writeResult(response, commonResult);
}
修改LoginFilter代码,因为添加购物车要经过Filter过滤器,判断未登录的话需要跳转到登录页面,而异步请求中是无法由服务器发起重定向跳转的
package com.atguigu.filter;
import com.atguigu.bean.CommonResult;
import com.atguigu.bean.User;
import com.atguigu.constant.BookStoreConstants;
import com.atguigu.utils.JsonUtils;
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
/**
* @author Chunsheng Zhang
* 日期2021-05-18 14:20
*/
public class LoginFilter implements Filter {
@Override
public void destroy() {
}
@Override
public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
//1. 判断当前是否已登录
HttpServletRequest request = (HttpServletRequest) req;
HttpServletResponse response = (HttpServletResponse) resp;
HttpSession session = request.getSession();
User loginUser = (User) session.getAttribute(BookStoreConstants.USERSESSIONKEY);
if (loginUser == null) {
//响应数据给客户端,告诉客户端未登录
CommonResult commonResult = CommonResult.error().setMessage("unlogin");
JsonUtils.writeResult(response,commonResult);
return;
}
//3. 如果已登录,则放行
chain.doFilter(req, resp);
}
@Override
public void init(FilterConfig config) throws ServletException {
}
}
### 功能三 显示购物车数据
#### 1、思路
![](https://cdn.nlark.com/yuque/0/2021/png/25621085/1639803067034-3193cf0e-b0e9-44e6-9f0c-3280d3a3efc2.png#)
#### 2. 代码实现
##### 2.1 CartServlet增加getCartJSON()方法
###### 2.1.1 Cart模型的局限性
![](https://cdn.nlark.com/yuque/0/2021/png/25621085/1639803067411-ba68ee16-061f-4fe6-ba97-7d92fac55020.png#)
目前的Cart对象转换为JSON后,没有totalCount、totalAmount这样的属性,Map结构也不如LIst遍历方便。
###### 2.1.2 调整方式
把前端页面需要的属性,存入Map中即可。
###### 2.1.3 方法代码
/**
* 获取购物车的json数据
* @param request
* @param response
*/
public void getCartJSON(HttpServletRequest request,HttpServletResponse response) {
Map
responseMap = null;
CommonResult commonResult = null;
try {
//1. 获取购物车信息
HttpSession session = request.getSession();
Cart cart = (Cart) session.getAttribute(BookStoreConstants.CARTSESSIONKEY);
//2. 我们要响应给客户端的是{"totalCount":总条数,"totalAmount":总金额,"cartItemList":购物项的集合}
responseMap = new HashMap<>();
responseMap.put("totalCount", cart.getTotalCount());
responseMap.put("totalAmount", cart.getTotalAmount());
//获取购物项列表
Collection cartItemCollection = cart.getCartItemMap().values();
List cartItemList = new ArrayList<>(cartItemCollection);
responseMap.put("cartItemList", cartItemList);
//查询成功
commonResult = CommonResult.ok().setResultData(responseMap);
} catch (Exception e) {
e.printStackTrace();
commonResult = CommonResult.error().setMessage("查询购物车信息失败");
}
//3. 将responseMap转成json并且响应给客户端
JsonUtils.writeResult(response, commonResult);
}
##### 2.2 前端代码
###### 2.2.1 去除Thymeleaf痕迹
将cart.html页面中,由Thymeleaf渲染数据的部分去掉。
###### 2.2.2 在mounted生命周期环境发Ajax请求
记得加入axios库和vue库:
var vue = new Vue({
“el”:”#app”,
“data”:{
“cart”:{
“totalCount”:0,
“totalAmount”:0,
“carItemList”:[]
}
},
“methods”:{
//查询购物车信息
getCart(){
//发送异步请求
axios({
“method”:”post”,
“url”:”protected/cart?method=getCartJSON”
}).then(response => {
if (response.data.flag) {
this.cart = response.data.resultData
}else {
//查询购物车失败
layer.msg(response.data.message)
}
})
}
},
//钩子函数
created(){
//调用方法查询购物车信息
this.getCart()
}
});
2.2.4 完成Vue页面渲染
<th>数量</th><br /> <th>单价</th><br /> <th>金额</th><br /> <th>操作</th><br /> </tr><br /> </thead><br /> <tbody v-if="cart.totalCount == 0"><br /> <tr><br /> <td th:colspan="6"><br /> <a href="index.html">购物车空空如也,请抓紧购物吧!!!!</a><br /> </td><br /> </tr><br /> </tbody><br /> <tbody v-if="cart.totalCount > 0"><br /> <tr v-for="(cartItem,index) in cart.cartItemList"><br /> <td><br /> <img :src="cartItem.imgPath" alt="" /><br /> </td><br /> <td v-text="cartItem.bookName">活着</td><br /> <td><br /> <a class="count" href="javascript:;">-</a><br /> <input class="count-num" type="text" v-model="cartItem.count" /><br /> <a class="count" href="javascript:;">+</a><br /> </td><br /> <td v-text="cartItem.price">36.8</td><br /> <td v-text="cartItem.amount">36.8</td><br /> <td><a href="javascript:;">删除</a></td><br /> </tr><br /> </tbody><br /> </table><br /> <div><br /> <div class="footer" v-if="cart.totalCount > 0"><br /> <div class="footer-left"><br /> <a href="protected/cart?method=cleanCart" @click="cleanCart" class="clear-cart">清空购物车</a><br /> <a href="#">继续购物</a><br /> </div><br /> <div class="footer-right"><br /> <div>共<span v-text="cart.totalCount">3</span>件商品</div><br /> <div class="total-price">总金额<span v-text="cart.totalAmount">99.9</span>元</div><br /> <a class="pay" href="protected/orderClient?method=checkout">去结账</a><br /> </div><br /> </div><br /> </div><br /> </div><br /></div><br />
功能四(扩展功能) 点击+号将购物项数量加一
HTML和Vue代码
+
cartItemCountIncrease(id,index){
//其实就是往服务器发送一个异步请求进行+1
axios({
“method”:”post”,
“url”:”protected/cart”,
“params”:{
“method”:”countIncrease”,
“id”:id
}
}).then(response => {
if (response.data.flag) {
this.cart.cartItemList[index].count ++
//重新设置页面totalCount和totalAmount<br /> this.cart.totalCount = response.data.resultData.totalCount<br /> this.cart.totalAmount = response.data.resultData.totalAmount<br /> }<br /> })<br />}<br />
CartServlet的代码
/*
购物车中某个一个购物项的数量+1
@param request
@param response
@throws IOException
/
public void countIncrease(HttpServletRequest request,HttpServletResponse response) throws IOException {
CommonResult commonResult = null;
try {
//1. 获取到要-+1的书的id
Integer id = Integer.valueOf(request.getParameter(“id”));
//2. 从session中获取购物车信息
Cart cart = (Cart) request.getSession().getAttribute(BookStoreConstants.CARTSESSIONKEY);
//3. 调用购物车的+1方法
cart.itemCountIncrease(id);
//将服务器端最新的购物车totalCount和totalAmount响应给客户端<br /> Map<String, Object> responseMap = new HashMap<>();<br /> responseMap.put("totalCount",cart.getTotalCount());<br /> responseMap.put("totalAmount",cart.getTotalAmount());<br /> commonResult = CommonResult.ok().setResultData(responseMap);<br /> } catch (Exception e) {<br /> e.printStackTrace();<br /> commonResult = CommonResult.error();<br /> }
JsonUtils.writeResult(response,commonResult);<br />}<br />
功能五(扩展功能) 点击-号将购物项的数量减一
HTML和Vue的代码
-
cartItemCountDecrease(count,bookName,id,index){
//判断:输入框的内容是否是1
if (count == 1) {
//则弹出提示框问你是否要删除
if (!confirm(bookName + “的数量已经是1了,你确定还要减少吗?”)) {
//不需要减少
return;
}
}
//需要减少:发送异步请求
axios({
“method”:”post”,
“url”:”protected/cart”,
“params”:{
“method”:”countDecrease”,
“id”:id
}
}).then(response => {
if (response.data.flag) {
//减1成功
this.cart.cartItemList[index].count —
//判断如果count是0,就将这条数据删掉<br /> if (this.cart.cartItemList[index].count == 0) {<br /> this.cart.cartItemList.splice(index,1)<br /> }
//重新设置页面totalCount和totalAmount<br /> this.cart.totalCount = response.data.resultData.totalCount<br /> this.cart.totalAmount = response.data.resultData.totalAmount<br /> }<br /> })<br />}<br />
CartServlet的代码
/*
购物车中某个一个购物项的数量-1
@param request
@param response
@throws IOException
/
public void countDecrease(HttpServletRequest request,HttpServletResponse response) throws IOException {
CommonResult commonResult = null;
try {
//1. 获取到要-1的书的id
Integer id = Integer.valueOf(request.getParameter(“id”));
//2. 从session中获取购物车信息
Cart cart = (Cart) request.getSession().getAttribute(BookStoreConstants.CARTSESSIONKEY);
//3. 调用购物车的-1方法
cart.itemCountDecrease(id);
//将服务器端最新的购物车totalCount和totalAmount响应给客户端<br /> Map<String, Object> responseMap = new HashMap<>();<br /> responseMap.put("totalCount",cart.getTotalCount());<br /> responseMap.put("totalAmount",cart.getTotalAmount());<br /> commonResult = CommonResult.ok().setResultData(responseMap);<br /> } catch (Exception e) {<br /> e.printStackTrace();<br /> commonResult = CommonResult.error();<br /> }<br /> JsonUtils.writeResult(response, commonResult);<br />}<br />
功能六(扩展功能) 点击删除按钮删除购物项
HTML和Vue的代码
deleteCartItem(bookName,id,index){
if (confirm(“你确定要删除这个”+bookName+”吗?”)) {
//表示要删除,才发送异步请求
axios({
“method”:”post”,
“url”:”protected/cart”,
“params”:{
“method”:”removeCartItem”,
“id”:id
}
}).then(response => {
if (response.data.flag) {
//表示要将当前这行,就是将cart.cartItemList对应index的这行删掉
this.cart.cartItemList.splice(index,1)
//重新设置页面totalCount和totalAmount<br /> this.cart.totalCount = response.data.resultData.totalCount<br /> this.cart.totalAmount = response.data.resultData.totalAmount<br /> }<br /> })<br /> }<br />}<br />
CartServlet的代码
/*
删除购物项
@param request
@param response
@throws IOException
/
public void removeCartItem(HttpServletRequest request,HttpServletResponse response) throws IOException {
CommonResult commonResult = null;
try {
//1. 获取要删除的购物项的书的id
Integer id = Integer.valueOf(request.getParameter(“id”));
//2.从session中获取购物车
Cart cart = (Cart) request.getSession().getAttribute(BookStoreConstants.CARTSESSIONKEY);
//3. 调用cart的删除购物项的方法
cart.removeCartItem(id);
//将服务器端最新的购物车totalCount和totalAmount响应给客户端<br /> Map<String, Object> responseMap = new HashMap<>();<br /> responseMap.put("totalCount",cart.getTotalCount());<br /> responseMap.put("totalAmount",cart.getTotalAmount());<br /> commonResult = CommonResult.ok().setResultData(responseMap);<br /> } catch (Exception e) {<br /> e.printStackTrace();<br /> commonResult = CommonResult.error();<br /> }<br /> JsonUtils.writeResult(response,commonResult);<br />}<br />
功能七(扩展功能) 修改购物项的数量
HTML和Vue的代码
updateCartItemCount(bookId){
//获取newCount
var newCount = event.target.value;
//校验newCount的格式是否正确<br /> var reg = /^[1-9][0-9]*$/
if (reg.test(newCount)) {<br /> //发送异步请求携带请求参数<br /> axios({<br /> "method":"post",<br /> "url":"protected/cart",<br /> "params":{<br /> "method":"updateCartItemCount",<br /> "id":bookId,<br /> "newCount":newCount<br /> }<br /> }).then(response => {<br /> if (response.data.flag) {<br /> //重新设置页面totalCount和totalAmount<br /> this.cart.totalCount = response.data.resultData.totalCount<br /> this.cart.totalAmount = response.data.resultData.totalAmount<br /> }<br /> })<br /> }else {<br /> alert("请输入正确的数量")<br /> }<br />}<br />
CartServlet的代码
/*
修改购物项的数量
@param request
@param response
@throws IOException
/
public void updateCartItemCount(HttpServletRequest request,HttpServletResponse response) throws IOException {
CommonResult commonResult = null;
try {
//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(BookStoreConstants.CARTSESSIONKEY);
//3. 调用cart中跟新数量的方法
cart.updateItemCount(id,newCount);
//将服务器端最新的购物车totalCount和totalAmount响应给客户端<br /> Map<String, Object> responseMap = new HashMap<>();<br /> responseMap.put("totalCount",cart.getTotalCount());<br /> responseMap.put("totalAmount",cart.getTotalAmount());<br /> commonResult = CommonResult.ok().setResultData(responseMap);
} catch (Exception e) {<br /> e.printStackTrace();<br /> commonResult = CommonResult.error();<br /> }
JsonUtils.writeResult(response,commonResult);<br />}