1.课程计划
第十二天:
- 购物车实现
- 订单确认页面展示
2.购物车的实现
2.1 功能分析
1、购物车是一个独立的表现层工程。
2、添加购物车不要求登录。可以指定购买商品的数量。
3、展示购物车列表页面
4、修改购物车商品数量
5、删除购物车商品
2.2 工程搭建
复制依赖到e3-cart工程:
<dependencies>
<dependency>
<groupId>cn.e3mall</groupId>
<artifactId>e3-common</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
</dependencies>
<!-- 配置tomcat插件 -->
<build>
<plugins>
<plugin>
<groupId>org.apache.tomcat.maven</groupId>
<artifactId>tomcat7-maven-plugin</artifactId>
<configuration>
<path>/</path>
<port>8089</port>
</configuration>
</plugin>
</plugins>
</build>
复制依赖到e3-cart-interface工程:
<dependencies>
<dependency>
<groupId>cn.e3mall</groupId>
<artifactId>e3-manager-pojo</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
</dependencies>
复制依赖到e3-cart-service工程:
<dependencies>
<dependency>
<groupId>cn.e3mall</groupId>
<artifactId>e3-manager-dao</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>cn.e3mall</groupId>
<artifactId>e3-cart-interface</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
<!-- spring的依赖 -->
<!-- Spring -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jms</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
</dependency>
<!-- dubbo相关 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>dubbo</artifactId>
<exclusions>
<!-- 排除dubbo自带的spring 防止冲突 -->
<exclusion>
<groupId>org.springframework</groupId>
<artifactId>spring</artifactId>
</exclusion>
<!-- 排除dubbo自带的netty 防止冲突 -->
<exclusion>
<groupId>org.jboss.netty</groupId>
<artifactId>netty</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.apache.zookeeper</groupId>
<artifactId>zookeeper</artifactId>
</dependency>
<dependency>
<groupId>com.github.sgroschupf</groupId>
<artifactId>zkclient</artifactId>
</dependency>
</dependencies>
复制e3-content-service所有配置到e3-cart-service工程下:
1.清空resource.properties内容
2.修改applicationContext-service.xml配置文件:
3.创建包:
4.修改applicationContext-trans.xml配置文件:
5.复制web.xml文件到e3-cart-service工程:
6.创建e3-cart-web工程(可以参考e3-portal-web):
7.复制依赖到e3-cart-web工程:
<dependencies>
<dependency>
<groupId>cn.e3mall</groupId>
<artifactId>e3-cart-interface</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
<!-- JSP相关 -->
<dependency>
<groupId>jstl</groupId>
<artifactId>jstl</artifactId>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jsp-api</artifactId>
<scope>provided</scope>
</dependency>
<!-- spring的依赖 -->
<!-- Spring -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jms</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
</dependency>
<!-- dubbo相关 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>dubbo</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework</groupId>
<artifactId>spring</artifactId>
</exclusion>
<exclusion>
<groupId>org.jboss.netty</groupId>
<artifactId>netty</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.apache.zookeeper</groupId>
<artifactId>zookeeper</artifactId>
</dependency>
<dependency>
<groupId>com.github.sgroschupf</groupId>
<artifactId>zkclient</artifactId>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
</dependency>
<!-- <dependency>
<groupId>org.freemarker</groupId>
<artifactId>freemarker</artifactId>
</dependency>
<dependency>
<groupId>org.apache.activemq</groupId>
<artifactId>activemq-all</artifactId>
</dependency> -->
</dependencies>
<build>
<plugins>
<!-- 配置Tomcat插件 -->
<plugin>
<groupId>org.apache.tomcat.maven</groupId>
<artifactId>tomcat7-maven-plugin</artifactId>
<configuration>
<path>/</path>
<port>8090</port>
</configuration>
</plugin>
</plugins>
</build>
8.复制web.xml文件到e3-cart-web工程:
9.复制e3-item-web配置文件到e3-cart-web工程:
清空resource.properties内容
删除applicationContext-activemq.xml配置文件
10.修改springmvc.xml配置文件:
11.创建包:
2.2.1 Pom文件
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>cn.e3mall</groupId> <artifactId>e3-parent</artifactId> <version>0.0.1-SNAPSHOT</version> </parent> <groupId>cn.e3mall</groupId> <artifactId>e3-cart-web</artifactId> <version>0.0.1-SNAPSHOT</version> <packaging>war</packaging> <dependencies> <dependency> <groupId>cn.e3mall</groupId> <artifactId>e3-manager-interface</artifactId> <version>0.0.1-SNAPSHOT</version> </dependency> <!-- Spring --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-beans</artifactId> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-jdbc</artifactId> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-aspects</artifactId> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-jms</artifactId> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context-support</artifactId> </dependency> <!-- JSP相关 --> <dependency> <groupId>jstl</groupId> <artifactId>jstl</artifactId> </dependency> <dependency> <groupId>javax.servlet</groupId> <artifactId>servlet-api</artifactId> <scope>provided</scope> </dependency> <dependency> <groupId>javax.servlet</groupId> <artifactId>jsp-api</artifactId> <scope>provided</scope> </dependency> <!-- dubbo相关 --> <dependency> <groupId>com.alibaba</groupId> <artifactId>dubbo</artifactId> <!-- 排除依赖 --> <exclusions> <exclusion> <groupId>org.springframework</groupId> <artifactId>spring</artifactId> </exclusion> <exclusion> <groupId>org.jboss.netty</groupId> <artifactId>netty</artifactId> </exclusion> </exclusions> </dependency> <dependency> <groupId>org.apache.zookeeper</groupId> <artifactId>zookeeper</artifactId> </dependency> <dependency> <groupId>com.github.sgroschupf</groupId> <artifactId>zkclient</artifactId> </dependency> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> </dependency> </dependencies> <!-- 配置tomcat插件 --> <build> <plugins> <plugin> <groupId>org.apache.tomcat.maven</groupId> <artifactId>tomcat7-maven-plugin</artifactId> <configuration> <port>8089</port> <path>/</path> </configuration> </plugin> </plugins> </build> </project> |
2.3 添加购物车
2.3.1 功能分析
在不登陆的情况下也可以添加购物车。把购物车信息写入cookie。
优点:
- 不占用服务端存储空间
- 用户体验好。
- 代码实现简单。
缺点:
- cookie中保存的容量有限。最大4k
- 把购物车信息保存在cookie中,更换设备购物车信息不能同步。
改造商品详情页面e3-item-web工程item.jsp(crtl+h全文搜索):
请求的url:/cart/add/{itemId}
参数:
1.)商品id: Long itemId
2.)商品数量: int num
业务逻辑:
- 从cookie中查询商品列表。
- 判断商品在商品列表中是否存在。
- 如果存在,商品数量相加。
- 不存在,根据商品id查询商品信息。
- 把商品添加到购车列表。
- 把购车商品列表写入cookie。
返回值:逻辑视图
Cookie保存购物车
1)key:TT_CART
2)Value:购物车列表转换成json数据。需要对数据进行编码。
3)Cookie的有效期:保存7天。
商品列表:
List<TbItem>,每个商品数据使用TbItem保存。当根据商品id查询商品信息后,取第一张图片保存到image属性中即可。
读写cookie可以使用CookieUtils工具类实现。
2.3.2 Controller
@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<>(); }
} |
添加依赖:
引用服务:
resource.properties:
加入购物车页面:
安装e3-cart工程
2.4 展示购物车商品列表
参数:无
返回值:逻辑视图
业务逻辑:
- 从cookie中取商品列表。
- 把商品列表传递给页面。
2.4.1 Controller
@RequestMapping("/cart/cart") public String showCartList(HttpServletRequest request, Model model) { //取购物车商品列表 List<TbItem> cartList = getCartList(request); //传递给页面 model.addAttribute("cartList", cartList); return "cart"; } |
2.5 修改购物车商品数量
2.5.1 功能分析
- 在页面中可以修改商品数量
- 重新计算小计和总计。
- 修改需要写入cookie。
- 每次修改都需要向服务端发送一个ajax请求,在服务端修改cookie中的商品数量。
请求成功执行重新计算总价:
请求的url:/cart/update/num/{itemId}/{num}
参数:long itemId、int num
业务逻辑:
- 接收两个参数
- 从cookie中取商品列表
- 遍历商品列表找到对应商品
- 更新商品数量
- 把商品列表写入cookie。
- 响应e3Result。Json数据。
返回值:
e3Result。Json数据
2.5.2 Controller
@RequestMapping("/cart/update/num/{itemId}/{num}") @ResponseBody public e3Result 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, "cart", JsonUtils.objectToJson(cartList), CART_EXPIRE, true); // 6、响应e3Result。Json数据。 return e3Result.ok(); } |
2.5.3 解决请求*.html后缀无法返回json数据的问题
在springmvc中请求*.html不可以返回json数据。
修改web.xml,添加url拦截格式。
2.6 删除购物车商品
2.6.1 功能分析
请求的url:/cart/delete/{itemId}
参数:商品id
返回值:展示购物车列表页面。Url需要做redirect跳转。
业务逻辑:
- 从url中取商品id
- 从cookie中取购物车商品列表
- 遍历列表找到对应的商品
- 删除商品。
- 把商品列表写入cookie。
- 返回逻辑视图:在逻辑视图中做redirect跳转。
2.6.2 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, "cart", JsonUtils.objectToJson(cartList), CART_EXPIRE, true); // 6、返回逻辑视图:在逻辑视图中做redirect跳转。 return "redirect:/cart/cart.html"; } |
2.7 小结
使用cookie实现购物车:
优点:
- 实现简单
- 不需要占用服务端存储空间。
缺点:
- 存储容量有限
- 更换设备购车信息不能同步。
实现购车商品数据同步:
1.要求用户登录。
2.把购物车商品列表保存到数据库中。推荐使用redis。
3.Key:用户id,value:购车商品列表。推荐使用hash,hash的field:商品id,value:商品信息。
4.在用户未登录情况下写cookie。当用户登录后,访问购物车列表时,
a) 把cookie中的数据同步到redis。
b) 把cookie中的数据删除
d) 展示购物车列表时以redis为准。
c) 如果redis中有数据cookie中也有数据,需要做数据合并。相同商品数量相加,不同商品添加一个新商品。
5.如果用户登录状态,展示购物车列表以redis为准。如果未登录,以cookie为准。
e3-cart-web工程添加依赖:
引用单点登录服务:
拦截器:
添加购物车(登录状态写入redis,未登录状态写入cookie,使用拦截器获取token进行是否登录验证):
resouce.properties:
e3-common工程:
e3-cart-interface工程:
e3-cart-service工程:
发布服务:
e3-cart-web工程:
1.添加依赖:
2.引用服务:
配置拦截器:
安装e3-cart-interface工程
配置断点查看:
1.RUN >> DEBUG Configuractions
1.复制e3-portal-web工程shortcut.jsp页面到e3-cart-web覆盖(验证效果)
2.复制e3-portal-web工程e3mall.js到e3-cart-web覆盖(验证效果)
3.修改主页进入我的购物车连接
展示购物车列表(登录状态需合并Cookie中商品并同步redis)逻辑:
添加合并购物车方法:
添加获取redis中购物车方法:
Cookie购物车数量加上缓存数量则成功实现:
修改购物车列表(登录状态需合并Cookie中商品并同步redis)逻辑:
删除购物车列表(登录状态需合并Cookie中商品并同步redis)逻辑:
安装e3-cart-interface工程