一、现在每个电商网站的购物车的操作,你会发现网速变慢了,是它故意让服务变慢,减速带,避免大量的高并发把服务器打崩。
1、这里使用ajax异步操作
2、异步操作一般都是返回json,这里做的是,返回内嵌页面,刷新当前页面
3、把购物车列表的内嵌页面放到一个新的html页面中,服务器只需要返回并刷新这个内嵌页面即可!
4、每次点击按钮,都会调用该事件checkSku(this),该事件在主页面上
二、实现前后端交互的异步操作(导师留下的前端bug,作为后端的开发人员表示看的很头痛!!!)
执行该事件(这里有三个重大bug未修复,先留着先————————
1、如果使用innerhtml这个方法,当用户点击某件商品的选中状态时,后端传递的是正常的所有商品的总价格,但是前端却无法正常显示。(使用html方法可以解决,但是会存在以下两个bug,我裂开了)
2、并且替换掉的内嵌页面也存在重大bug,无法点击增加数量和删除。
3、替换掉的内嵌页面,是从缓存查询过来的数据,商品的排序存在问题,每次点击被选中状态,商品的位置都发生了改变,用户体验极其不好!!!):
function checkSku(chkbox){
var skuId= $(chkbox).attr("value");
var checked=$(chkbox).prop("checked");
var isCheckedFlag="0";
if(checked){
isCheckedFlag="1"; //如果是被勾选状态,就等于1;否则为0
}
var param="isChecked="+isCheckedFlag+"&"+"skuId="+skuId; //传递的参数:某件商品id的勾选状态isChecked为1或0
$.post("checkCart",param,function (html) { //这里会传递param的参数给服务器的checkCart方法,并返回新的页面html给ajax
$("#cartListInner").innerHTML(html) //这个新的内嵌页面html,替换掉原来的内嵌页面对象cartListInner
});
}
4、在control层服务器的代码:
//修改购物车商品的选中状态(1、修改db中的选中状态 2、查询缓存-db)
@RequestMapping("checkCart")
public String checkCart(String isChecked, String skuId, HttpServletRequest request, HttpServletResponse response, ModelMap modelMap) {
String memberId = "2";
OmsCartItem omsCartItem = new OmsCartItem();
omsCartItem.setMemberId(memberId);
omsCartItem.setIsChecked(isChecked);
omsCartItem.setProductSkuId(skuId);
//修改db中的被选中的状态1或者0
cartService.checkCart(omsCartItem);
//查询某个用户id的购物车列表
List<OmsCartItem> omsCartItemList = cartService.cartList(memberId);
modelMap.put("cartList",omsCartItemList);
//返回新的内嵌页面
return "cartListInner";
}
5、在service层实现:
//修改购物车商品的选中状态
@Override
public void checkCart(OmsCartItem omsCartItem) {
//修改db中被选中的状态
Example e = new Example(OmsCartItem.class);
e.createCriteria().andEqualTo("memberId",omsCartItem.getMemberId()). //根据用户id和商品id为条件,两个条件!!!
andEqualTo("productSkuId",omsCartItem.getProductSkuId());
omsCartItemMapper.updateByExampleSelective(omsCartItem,e); //去修改数据库中的购物车被选中状态1或者0,传递过来的字段有值才修改数据库的字段!!!
//同步缓存
flushCartCache(omsCartItem.getMemberId());
}
6、最终就实现异步操作功能了!数据库被修改成功,缓存也同步成功!
用户每次修改选中状态,都要执行下面三个操作(已完成并测试成功!):
(1)ajax异步+内嵌页
(2)修改数据库的购物车状态
(3)数据库修改后同步缓存
三、计算总价格(一定一定要使用BigDecimal类型!!!!保证计算不会出错!!!并且需要在服务器进来计算)
1、计算所有商品的总价格(有两处1、商品被选中状态发生改变时 2、查看购物车列表):
//修改购物车商品的选中状态(1、修改db中的选中状态 2、查询缓存-db)
@RequestMapping("checkCart")
public String checkCart(String isChecked, String skuId, HttpServletRequest request, HttpServletResponse response, ModelMap modelMap) {
String memberId = "2";
OmsCartItem omsCartItem = new OmsCartItem();
omsCartItem.setMemberId(memberId);
omsCartItem.setIsChecked(isChecked);
omsCartItem.setProductSkuId(skuId);
//修改db中的被选中的状态1或者0
cartService.checkCart(omsCartItem);
//查询某个用户id的购物车列表
//注意这里查询的缓存购物车,要计算总价格!!!bug!!!可以在同步缓存之前把价格算出来先
List<OmsCartItem> omsCartItemList = cartService.cartList(memberId);
//用户每次点击商品被勾选的状态时,这里都会重新计算所有商品的总价格
BigDecimal TotalAmount = getTotalAmount(omsCartItemList);
modelMap.put("TotalAmount",TotalAmount);
modelMap.put("cartList",omsCartItemList);
//返回新的内嵌页面
return "cartListInner";
}
//查看购物车列表(1、未登陆(查cookie) 2、已登陆(查缓存-db))
@RequestMapping("cartList")
public String addToCart(HttpServletRequest request, HttpServletResponse response, ModelMap modelMap){
String memberId = "2";
List<OmsCartItem> omsCartItemList = new ArrayList<>();
if(StringUtils.isBlank(memberId)){ //memberId为空,用户未登陆,去查询cookie是否有数据
String cartListCookie = CookieUtil.getCookieValue(request, "cartListCookie", true);
if(cartListCookie!=null){
omsCartItemList = JSON.parseArray(cartListCookie, OmsCartItem.class);
for (OmsCartItem omsCartItem : omsCartItemList) { //计算某个sku商品总价=添加的数量*单价
omsCartItem.setTotalPrice(omsCartItem.getPrice().multiply(omsCartItem.getQuantity()));
}
}
}else { //不为空,即用户已经登陆,需要查询db,但是此操作最为频繁!需要加中间件缓存服务器!!!保护db
omsCartItemList = cartService.cartList(memberId); //先查缓存
if(omsCartItemList!=null){
for (OmsCartItem omsCartItem : omsCartItemList) { //计算某个sku商品总价=添加的数量*单价
omsCartItem.setTotalPrice(omsCartItem.getPrice().multiply(omsCartItem.getQuantity()));
}
}
}
//查看购物车列表也要计算所有商品的总价格!!!
BigDecimal TotalAmount = getTotalAmount(omsCartItemList);
modelMap.put("TotalAmount",TotalAmount);
modelMap.put("cartList",omsCartItemList);
return "cartList";
}
//计算所有商品的总价格
private BigDecimal getTotalAmount(List<OmsCartItem> omsCartItemList) {
BigDecimal TotalAmount = new BigDecimal("0");
for (OmsCartItem omsCartItem : omsCartItemList) {
BigDecimal TotalPrice = omsCartItem.getPrice().multiply(omsCartItem.getQuantity());
//检索商品被选中的状态,如为1则被选中,并且计算被选中的所有商品的总价格
if(omsCartItem.getIsChecked().equals("1")){
TotalAmount = TotalAmount.add(TotalPrice);
}
}
return TotalAmount;
}