文章大纲
一、购物车流程
二、购物车系统的搭建
三、购物车系统实现分析
四、购物车系统实现的准备工作
五、添加商品到购物车
六、展示购物车列表
七、更新购物车的商品数量
八、删除购物车中的商品
九、参考博客
课程大纲
一共14天课程
(1)第一天:电商介绍–互联网术语-SOA-分布式-集群介绍-环境配置-框架搭建
(2)第二天:Dubbo介绍_dubbo框架整合_商品列表查询实现_分页_逆向工程
(3)第三天:Git&.Nginx,类目选择,新增商品
(4)第四天:门户网站介绍&商城首页搭建&内容系统创建&CMS实现
(5)第五天:首页轮播图显示实现,Redis环境搭建,Redis实现缓存
(6)第六天:solr索引库搭建&solr搜索功能实现&图片显示问题解决
(7)第七天:solr集群搭建_全局异常处理
(8)第八天:activeMQ介绍_搭建_解决同步索引库问题
(9)第九天:FreeMark入门_静态化页面标签介绍_静态化页面实现
(10)第十天:Nginx代理详解…单点登录系统工程搭建_接口文档讲解
(11)第十一天:SSO系统的搭建&单点登录系统实现_用户名回显_cookie跨域问题
(12)第十二天:购物车订单系统的实现。
(13)第十三天:订单提交的功能实现&项目的部署&服务器的域名规划。
(14)项目总结。
用户将商品添加到购物车时,判断用户是否登录,如果已经登录将购物车放入session中。
存在的问题:
购物车使用了session,而session是存在于内存资源中,消耗了大量的内存资源。非常不好。
购物车存在session当中,如果session销毁(浏览器关闭),购物车就没有了。
session无法共享,无法进行水平扩展。
解决方案:给购物车做持久化。
持久化,需要用到数据库(把数据存储到服务端,较安全)。
a、mysql数据库(数据完整性比较好)
b、redis数据库(读写速度快)
用户未登录的时候不能添加购物车。
解决方案:未登录的状态下,可以把购物车放在cookie中。
在不登陆的情况下添加购物车。把购物车信息写入cookie。(数据保存在客户端,数据完整性差)。
优点:
1、不占用服务端存储空间。
2、用户体验好。
3、代码实现简单。
缺点:
1、cookie中保存的容量有限。最大4k。
2、把购物车信息保存在cookie中,更换设备购物车信息不能同步。
这里我们不使用这种方法。
对于未登陆用户,将购物车放到cookie中。对于已登陆用户将购物车放入redis缓存中。可以实现,用户未登录或者登录状况下的添加购物车(并进行购物车的增删查改)。
购物车系统架构:
可以参考taotao-manager、taotao-manager-web创建。
taotao-cart
taotao-cart打包方式pom。
可以参考taotao-manager工程的创建。
New --> Maven Project --> 不使用骨架创建工程 --> Next
pom.xml
taotao-cart-interface
New --> Other–> Maven Module --> 不使用骨架创建
千万不要创建成Maven Project。
taotao-cart-interface打包方式jar。
pom.xml
taotao-cart-service
New --> Other–> Maven Module --> 不使用骨架创建
千万不要创建成Maven Project。
taotao-cart-service打包方式war。
pom.xml
在web.xml中配置spring的监听器,内容如下:
web.xml
框架整合
将taotao-manager-service的src/main/resources下的配置文件全部复制到taotao-cart-service的src/main/resources中
删除或清空与数据库相关的配置文件,因为购物车主要使用redis缓存,所以需要将redis的工具类添加进来:
修改applicationContext-service.xml中spring注解包扫描的类与dubbo暴露服务的端口:
在taotao-cart-interface工程的src/main/java中创建com.taotao.cart.service包;
在taotao-cart-service工程的src/main/java中创建com.taotao.cart.service.impl包。
taotao-cart-web
表现层为一个单独的工程,所以需要创建Maven Project。
New --> Maven Project
千万不要创建成Maven Module。
taotao-cart-web的打包方式是war。
pom.xml
web.xml
框架整合
将表现层taotao-manager-web工程下的src/main/resources下面的配置文件复制到taotao-cart-web下的src/main/resources中
删除或清空相关的配置文件:
修改springmvc.xml中controller注解扫描的位置:
由于购物车中的商品属性与TbItem类似,所以可以将TbItem当做购买的商品。TbItem中的num属性原用作后台管理系统的商品库存数量,在这里可以将num属性用作购买商品的数量,所以List就是一个购物车。一个用户对应一个购物车,一个购物车对应多个商品。
对于存入cookie中,我们可以自定义key,然后将购物车List转为json串,存到cookie。
由于一个用户对应一个购物车,一个购物车购买多个商品。相当于一个用户可以购买多个商品。
对于存入redis中,我们有两种实现方案:
1.方案一:
使用String类型,将用户userId作为key,将购物List转为json串作为value。
2.方案二:
使用hash类型,将用户userId作为key,将商品itemId作为filed,将购物车List转为json串作为value。
推荐使用hash,可以提高修改的效率(性能的提升),如果是String存储大数据量的时候速度较慢。redis是单线程。
分析需要存储的商品的信息的属性有:
商品的ID、商品的名称、商品的价格、购买商品的数量、商品的图片(取一张即可)。
可以直接使用TbItem。
由于购物车系统的运行,依赖很多其他系统,为了防止登录注册等其他情况,url错误报404导致不好测试,需要修改整个淘淘商城系统中的url为正确的url。
4.1、修改所有登录注册的url
Ctrl+H,搜索所有的:http://localhost:8084/page,将8084改为8088
将参考资料中的购物车静态页面下的js、css、images导入webapp下,将jsp导入WEB-INF下:
商品详情在taotao-item-web系统的item.jsp中,给加入购物车添加一个事件javascript:addCartItem();
注意一定要修改这个,要不然到后面购物车列表会有一个很大的坑,在计算数量的时候,num=null,我就因为这个找了一上午的BUG
在前端点击添加购物车,就会触发addCartItem函数,跳转url:cart/add/itemId.html?num=123,我们需要接收itemId与num,同步到redis或者cookie中。
添加购物车功能的分析:
url:/cart/add/{itemId}?num=2
参数:商品的id以及num
另外:用户的id(因为要保证redis中存储数据的正确性,必须要求要存放于哪一个用户的购物车数据)
返回值:逻辑视图,cartSuccess.jsp 。
Dao层
直接通过JedisClient对象操作redis数据库。
Service层
业务逻辑:
1、根据商品的ID查询商品的信息。
2、设置商品的数量和图片(只需要设置图片的一张即可,数量使用num字段来表示,因为原来的num存放的是库存,所以需要重新设置一下)。
3、根据商品id和用户id从redis数据库中查询用户的购物车的商品的列表,看是否存在(需要将JSON转成java对象)。
4、如果没有存在,则直接添加到redis中(需要将java对象转成JSON)。
5、如果存在,则更新商品购买的数量即可。
首先在taotao-cart-interface下创建接口包com.taotao.cart.service,在接口包下创建接口CartService.java。
使用hash类型,可以给key设置一个前缀用于分类。在taotao-cart-service的src/main/resources下创建resource.properties文件,文件内容如下:
在taotao-cart-service下创建实现类包com.taotao.cart.service.impl,在实现类包下创建CartServiceImpl实现CartService:
发布服务
先在taotao-cart-service工程中的pom.xml文件中配置对taotao-cart-interface的依赖,因为服务层发布服务要通过该接口,
再在taotao-cart-service工程中的applicationContext-service.xml文件中发布服务
引用服务
先在taotao-cart-web工程中的pom.xml文件中配置对taotao-cart-interface的依赖,因为表现层引用服务要通过该接口,
再在taotao-cart-web工程中的springmvc.xml文件中引用服务
Controller
url: /cart/add/{itemId}
参数:itemId, num
返回值:添加购物车成功页面。
业务逻辑:
1、调用SSO的服务,获取用户相关的信息。
2、调用商品(manage)的服务,获取商品的相关的信息。
3、判断如果是登录的状态,则调用登录的添加购物车的service。
4、如果是未登录的状态,则调用的是未登录的添加购物车的方法。
在taotao-cart-web下创建controller的包com.taotao.cart.controller,在包controller中创建CartController.java:
首先退出用户登录状态,使用我们已经做好的查看购物车列表的功能,查看cookie中是否存入了购物车,可以看到未登录的情况下,添加购物车成功。
如果用户登录状态,展示购物车列表以redis为准。如果未登录,以cookie为准。
添加商品到购物车后,会提示【去购物车结算】,点击【去购物车结算】,会跳转到http://localhost:8089/cart/cart.html页面,可以看到购物车中商品列表。
在cart.jsp,我们可以看到需要准备一个cartList商品集合到model中。需要修改{cart.image}。
url: /cart/cart
参数:用户id
返回值:购物车页面,需要传递模型数据list
直接通过JedisClient对象操作redis数据库。
在taotao-cart-interface创建接口
在taotao-cart-service编写实现类
业务逻辑:
1、根据用户的ID查询redis中所有的field的值(map)。
2、遍历map对象,将其添加到List中。
3、返回一个List。
发布服务与引用服务
url: /cart/cart
参数:无
返回值:购物车展示列表的页面
业务逻辑:
1、根据token调用SSO的服务,获取用户的信息。
2、判断,如果有用户的信息,说明用户已登录,调用CartService服务中查询购物车的商品列表的方法。
3、如果没有用户信息,说明用户未登录,调用从cookie中获取购物车商品列表的方法。
4、将购物车对象放入request域。
5、返回逻辑页面cart.jsp。
代码如下:
安装taotao-cart。
由于要调用taotao-sso与taotao-manager查询用户与商品信息,所以需要启动taotao-sso、taotao-manager。
需要登录在cookie中写入toekn,所以要启动taotao-sso-web。
需要搜索商品,所以要启动taotao-search、taotao-search-web。(如果手动输入url进入商品详情页,可以不启动)
需要将商品详情页加入购物车,所以需要启动taotao-item-web。
最后购物车的taotao-cart、taotao-cart-web也要启动。
在taotao-cart-web的cart.js中有更新商品时js事件处理。
商品数量加一、减一时会触发对应的事件,修改dom,从而修改前端展示的商品价格。
然后会异步请求url:/cart/update/num/" + _thisInput.attr(“itemId”) + “/” + _thisInput.val()
也就是url:/cart/update/num/itemId/num,修改服务端的数据。
refreshTotalPrice函数用于重新计算总价。
注意:我们的请求是以.action结尾的。为什么呢?
答:因为在springmvc.xml中拦截*.html结尾的请求不可以返回json数据。
直接通过JedisClient对象操作redis数据库。
在taotao-cart-interface创建接口
在taotao-cart-service创建实现类
业务逻辑:
从redis中获取到对应的商品的对象,设置对象的商品数量,转成JSON,存入redis中。
发布服务与引用服务
url:/cart/update/num/{itemId}/{num}
参数:itemId、num
从cookie中获取token,根据token查询redis,判断用户是否登录,已登录更新购物车到redis中,未登录更新到cookie中。
更新cookie中的购物车思路比较简单:从cookie中获取所有购物车,遍历购物车找到对应商品更新数量,重新存入cookie即可。
解决请求*.html后缀无法返回json格式的数据的问题:
问题原因:因为在springmvc.xml中拦截*.html结尾的请求不可以返回json数据。
解决方式:由于我们的请求是以.action结尾的,所以我们修改web.xml,添加url拦截格式。
用户点击删除,未登录从cookie中删除该商品、已登录从redis中删除该商品。
url:/cart/delete/${cart.id}.html
参数:cartid,其实是就是itemId
根据商品id,从cookie或者redis中删除商品。
返回值:展示购物车列表页面。url需要做redirect跳转(重定向)。
直接通过JedisClient对象操作redis数据库。
在taotao-cart-interface创建接口
在taotao-cart-service创建实现类
业务逻辑:
根据userid、itemid删除redis中购物车列表的商品
url:/cart/delete/${cart.id}.html
参数:cartid,其实是就是itemId
根据商品id,从cookie或者redis中删除商品
返回值:展示购物车列表页面。url需要做redirect跳转到商品列表展示的controller。