我们首先来看看京东的购物车的实现,根据操作的我们可以发现两点:1.加入购物车是一个新工程,因此我们需要新增一个工程;2.购物车是不用登录就可以操作的了,而且加到购物车里面的商品可以一直保存着;我们在学cookie的时候应该说过一个应用就是电商,将购物车的内容保存到购物车中
image.png image.png
1.工程搭建
我们知道购物车是和商品挂钩的。我么前面已经实现了商品服务了,因此我们直接调用商品服务就好了;我们只需要建一个前台工程taotao-cart-web;
搭建的流程可以参考taotao-manager-web
需要修改里面的配置,具体可以从GitHub上下载下来后直接复制黏贴过去~
传送门:https://github.com/AslanYJ/shopping.git
然后导入静态资源;
工程搭建完后我们要实现以下功能:
1.添加到购物车
2.更新购物车中商品的数量
3.删除购物车中的商品
4.展示购物车
2.添加购物车
在不登陆的情况下也可以添加购物车。把购物车信息写入cookie。
优点:
1、不占用服务端存储空间
2、用户体验好。
3、代码实现简单。
缺点:
1、cookie中保存的容量有限。最大4k
2、把购物车信息保存在cookie中,更换设备购物车信息不能同步。
改造商品详情页面
先写一个js的脚本
image.png image.png
- Controller
请求的url:/cart/add/{itemId}
参数:
1)商品id: Long itemId
2)商品数量: int num
业务逻辑:
1、从cookie中查询商品列表。
2、判断商品在商品列表中是否存在。
3、如果存在,商品数量相加。
4、不存在,根据商品id查询商品信息。
5、把商品添加到购车列表。
6、把购车商品列表写入cookie。
返回值:逻辑视图
Cookie保存购物车
1)key:TT_CART
2)Value:购物车列表转换成json数据。需要对数据进行编码。
3)Cookie的有效期:保存7天。
商品列表:
List<TbItem>,每个商品数据使用TbItem保存。当根据商品id查询商品信息后,取第一张图片保存到image属性中即可。
读写cookie可以使用CookieUtils工具类实现。
@Controller
public class CartController {
@Value("${TT_CART}")
private String TT_CART;
@Value("${CART_EXPIRE}")
private Integer CART_EXPIRE;
@Autowired
private ItemService itemService;
@RequestMapping("/cart/add/{itemId}")
public String addCartItem(@PathVariable Long itemId, Integer num,
HttpServletRequest request, HttpServletResponse response) {
// 1、从cookie中查询商品列表。
List<TbItem> cartList = getCartList(request);
// 2、判断商品在商品列表中是否存在。
boolean hasItem = false;
for (TbItem tbItem : cartList) {
//对象比较的是地址,应该是值的比较
if (tbItem.getId() == itemId.longValue()) {
// 3、如果存在,商品数量相加。
tbItem.setNum(tbItem.getNum() + num);
hasItem = true;
break;
}
}
if (!hasItem) {
// 4、不存在,根据商品id查询商品信息。
TbItem tbItem = itemService.getItemById(itemId);
//取一张图片
String image = tbItem.getImage();
if (StringUtils.isNoneBlank(image)) {
String[] images = image.split(",");
tbItem.setImage(images[0]);
}
//设置购买商品数量
tbItem.setNum(num);
// 5、把商品添加到购车列表。
cartList.add(tbItem);
}
// 6、把购车商品列表写入cookie。
CookieUtils.setCookie(request, response, TT_CART, JsonUtils.objectToJson(cartList), CART_EXPIRE, true);
return "cartSuccess";
}
/**
* 从cookie中取购物车列表
* <p>Title: getCartList</p>
* <p>Description: </p>
* @param request
* @return
*/
private List<TbItem> getCartList(HttpServletRequest request) {
//取购物车列表
String json = CookieUtils.getCookieValue(request, TT_CART, true);
//判断json是否为null
if (StringUtils.isNotBlank(json)) {
//把json转换成商品列表返回
List<TbItem> list = JsonUtils.jsonToList(json, TbItem.class);
return list;
}
return new ArrayList<>();
}
}
这里有技巧~
我们可以把用的比较多的代码抽取出来重构,比如从cookie中取list,我们不仅添加用到,删除,更新都会用到。
-
引入服务
image.png -
测试
启动工程。
搜索少儿
image.png
image.png
image.png
3.展示购物车商品列表
请求的url:/cart/cart
参数:无
返回值:逻辑视图
业务逻辑:
1、从cookie中取商品列表。
2、把商品列表传递给页面。
- Controller
@RequestMapping("/cart/cart")
public String showCartList(HttpServletRequest request, Model model) {
//取购物车商品列表
List<TbItem> cartList = getCartList(request);
//传递给页面
model.addAttribute("cartList", cartList);
return "cart";
}
- 测试
如上图所示
4.修改购物车数量
-
功能分析
1、在页面中可以修改商品数量
2、重新计算小计和总计。
3、修改需要写入cookie。
4、每次修改都需要向服务端发送一个ajax请求,在服务端修改cookie中的商品数量。
以下是涉及数量修改后与后台交互的ajax代码
image.png
请求的url:/cart/update/num/{itemId}/{num}
参数:long itemId、int num
业务逻辑:
1、接收两个参数
2、从cookie中取商品列表
3、遍历商品列表找到对应商品
4、更新商品数量
5、把商品列表写入cookie。
6、响应TaoTaoResult。Json数据。
返回值:
TaoTaoResult。Json数据
@RequestMapping("/cart/update/num/{itemId}/{num}")
@ResponseBody
public TaotaoResult updateNum(@PathVariable Long itemId, @PathVariable Integer num,
HttpServletRequest request, HttpServletResponse response) {
// 1、接收两个参数
// 2、从cookie中取商品列表
List<TbItem> cartList = getCartList(request);
// 3、遍历商品列表找到对应商品
for (TbItem tbItem : cartList) {
if (tbItem.getId() == itemId.longValue()) {
// 4、更新商品数量
tbItem.setNum(num);
}
}
// 5、把商品列表写入cookie。
CookieUtils.setCookie(request, response, TT_CART, JsonUtils.objectToJson(cartList), CART_EXPIRE, true);
// 6、响应TaoTaoResult。Json数据。
return TaotaoResult.ok();
}
-
测试
image.png
image.png
5.删除购物车商品信息
image.png- 功能分析
请求的url:/cart/delete/{itemId}
参数:商品id
返回值:展示购物车列表页面。Url需要做redirect跳转。
业务逻辑:
1、从url中取商品id
2、从cookie中取购物车商品列表
3、遍历列表找到对应的商品
4、删除商品。
5、把商品列表写入cookie。
6、返回逻辑视图:在逻辑视图中做redirect跳转。 - Controller
@RequestMapping("/cart/delete/{itemId}")
public String deleteCartItem(@PathVariable Long itemId, HttpServletRequest request,
HttpServletResponse response) {
// 1、从url中取商品id
// 2、从cookie中取购物车商品列表
List<TbItem> cartList = getCartList(request);
// 3、遍历列表找到对应的商品
for (TbItem tbItem : cartList) {
if (tbItem.getId() == itemId.longValue()) {
// 4、删除商品。
cartList.remove(tbItem);
break;
}
}
// 5、把商品列表写入cookie。
CookieUtils.setCookie(request, response, TT_CART, JsonUtils.objectToJson(cartList), CART_EXPIRE, true);
// 6、返回逻辑视图:在逻辑视图中做redirect跳转。
return "redirect:/cart/cart.html";
}
6.购物车总结
购物车总结:
我们当前实现的购物车是以Cookie的方式实现的,这样做的优点有以下两点:
1、实现简单
2、不需要占用服务端存储空间
缺点也很明显,主要有以下两点:
1、存储容量有限(Cookie中保存的数据量毕竟是比较有限的)
2、更换设备后,购物车信息不能同步。
那么针对上面的缺点,我们应该怎样解决呢?这里给大家提供一下思路:
1、要求用户登录。
2、把购物车商品列表保存到数据库中。推荐使用redis。
3、如果存到redis的话,key最好用用户的ID,value便是购物车中商品列表。在redis中存储有五种存储方式,我们比较适合使用hash方式,规定一个hash,然后key是商品ID,value是商品基本信息。这样做的好处是存储的内容不是很长,效率比较高。
4、在用户未登录的情况下写入cookie当中,当用户登录后,访问购物车列表时
a} 把cookie中的数据同步到redis。
b} 把cookie中的数据删除
c) 展示购物车列表时以redis为准。
d) 如果redis中有数据cookie中也有数据,需要做数据合并。相同的商品数量相加,不同商品添加一个新商品。
5、如果用户登录状态,展示购物车列表以redis为准。如果未登录,以cookie为准。
网友评论