目录
1.导入静态资源
将参考资料中的购物车静态页面下js、css、images导入webapp下,将jsp导入WEB-INF下
2.修改商品详情页
商品详情在taotao-item-web系统的item.jsp中
给加入购物车添加一个事件javascript:addCartItem();
function addCartItem(){
//购买商品数量
var num=$("#buy-num").val();
window.location.href="http://localhost:8089/cart/add/${item.id}.html?num="+num;
}
在前端点击添加购物车,就会触发addCartItem函数,跳转url:cart/add/itemId.html?num=123,我们需要接收itemId与num,同步到redis或者cookie
3.登录状态下添加购物车
3.1服务层
3.1.1dao层
直接通过jedisClient操作redis数据库
3.1.2service层
业务逻辑:
- 根据商品的id与用户id从redis查询商品的信息
- 判断要添加的商品是否存在与redis中
- 如果存在,将添加商品的数量与redis已存在的商品数量相加后,存入redis
- 如果不存在,直接设置商品数量为添加的商品数量,并设置image属性为第一张图片,然后存入redis
首先在taotao-cart-interface下创建接口包com.taotao.cart.service,在接口包下创建接口CartService.java
使用hash类型,可以给key设置一个前缀用于分类。在taotao-cart-service的src/main/resources下创建resource.properties文件
#购物车的前缀
TT_CART_REDIS_PRE_KEY=TT_CART_REDIS_PRE_KEY
在taotao-cart-service下创建实现类包com.taotao.cart.service.impl,在实现类包下创建CartServiceImpl实现CartService
这里封装了一个根据key:itemId,filed:userId,从redis获取itemJson的方法queryItemByItemAndUserId(Long itemId,Long userId)
后面还很常用
package com.taotao.cart.service.impl;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import com.taotao.cart.jedis.JedisClient;
import com.taotao.cart.service.CartService;
import com.taotao.common.pojo.TaotaoResult;
import com.taotao.common.utils.JsonUtils;
import com.taotao.pojo.TbItem;
@Service
public class CartServiceImpl implements CartService {
/**发布服务*/
/**注入依赖*/
@Autowired
private JedisClient jedisClient;
/**redis缓存购物车的前缀*/
@Value("${TT_CART_REDIS_PRE_KEY}")
private String TT_CART_REDIS_PRE_KEY;
/**登录状态下添加购物车*/
@Override
public TaotaoResult addItemCart(TbItem tbItem, Integer num, Long userId) {
//1.根据 key和field查询某一个商品
TbItem tbItem2 = queryItemByItemAndUserId(tbItem.getId(), userId);
//2.判断要添加的商品是否存在于列表中
if(tbItem2 != null) {
//3.如果存在,直接数量相加
tbItem2.setNum(tbItem2.getNum()+num);
//存入redis中
jedisClient.hset(TT_CART_REDIS_PRE_KEY+":"+userId, tbItem2.getId()+"", JsonUtils.objectToJson(tbItem2));
}else {
//4.如果不存在,设置商品数量,设置图片
tbItem.setNum(num);
if(tbItem.getImage()!=null) {
tbItem.setImage(tbItem.getImage().split(",")[0]);
}
//存入redis中
jedisClient.hset(TT_CART_REDIS_PRE_KEY+":"+userId, tbItem.getId()+"", JsonUtils.objectToJson(tbItem));
}
return TaotaoResult.ok();
}
/**
* key:itemId,filed:userId,获取itemJson
* @param itemId
* @param userId
* @return
*/
private TbItem queryItemByItemAndUserId(Long itemId,Long userId) {
String itemJson = jedisClient.hget(TT_CART_REDIS_PRE_KEY+":"+userId,itemId+"");
if(StringUtils.isNoneBlank(itemJson)) {
TbItem tbItem = JsonUtils.jsonToPojo(itemJson, TbItem.class);
return tbItem;
}
return null;
}
}
配置springmvc.xml文件
要注意图中标注的地方
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context" xmlns:p="http://www.springframework.org/schema/p"
xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:dubbo="http://code.alibabatech.com/schema/dubbo" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.2.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.2.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.2.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.2.xsd
http://code.alibabatech.com/schema/dubbo http://code.alibabatech.com/schema/dubbo/dubbo.xsd
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-4.2.xsd">
<!-- 加载properties文件 -->
<context:property-placeholder location="classpath:resource/*.properties" />
<!-- 注解扫描 -->
<context:component-scan base-package="com.taotao.cart.service"/>
<!-- 使用dubbo发布服务 -->
<!-- 提供方应用信息,用于计算依赖关系 -->
<dubbo:application name="taotao-cat" />
<dubbo:registry protocol="zookeeper" address="192.168.25.133:2181" />
<!-- 用dubbo协议在20884端口暴露服务 -->
<dubbo:protocol name="dubbo" port="20884" />
<!-- 声明需要暴露的服务接口 -->
<dubbo:service interface="com.taotao.cart.service.CartService" ref="cartServiceImpl" timeout="300000"/>
</beans>
3.2表现层
3.2.1properties文件
由于要将购物车存入cookie中,所以需要给购物车存入cookie时设置一个name,获取token时正好也需要一个name,可以将这两个name放在properties文件中
resource.properties
#COOKIE中存放token的key
COOKIE_TOKEN_KEY=COOKIE_TOKEN_KEY
#COOKIE中存放购物车的key
COOKIE_CART_KEY=COOKIE_CART_KEY
3.2.2controller
url: /cart/add/{itemId}
参数:itemId,num
返回值:添加购物车成功页面。
处理的逻辑:
- 调用sso的服务,获取用户相关的信息
- 调用manager的服务,获取商品的相关的信息
- 判断如果是登录的状态,调用登录的添加购物车的service
- 如果是未登录的状态,调用的是未登录的添加购物车的方法。
由于要调用taotao-sso与taotao-manager的服务
需要在pom.xml中添加依赖
<dependency>
<groupId>com.taotao</groupId>
<artifactId>taotao-manager-interface</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>com.taotao</groupId>
<artifactId>taotao-cart-interface</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>com.taotao</groupId>
<artifactId>taotao-sso-interface</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
在taotao-cart-web下创建controller包com.taotao.cart.controller,在controller中创建CartController
package com.taotao.cart.controller;
import java.util.ArrayList;
import java.util.List;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import com.taotao.cart.service.CartService;
import com.taotao.common.pojo.TaotaoResult;
import com.taotao.common.utils.CookieUtils;
import com.taotao.common.utils.JsonUtils;
import com.taotao.pojo.TbItem;
import com.taotao.pojo.TbUser;
import com.taotao.service.ItemService;
import com.taotao.sso.service.UserLoginService;
@Controller
public class CartController {
/** 引入服务 */
/** 注入依赖 */
@Autowired
private CartService cartService;
@Autowired
private ItemService itemService;
@Autowired
private UserLoginService loginService;
/** COOKIE中存放token的key */
@Value("${COOKIE_TOKEN_KEY}")
private String COOKIE_TOKEN_KEY;
/** COOKIE中存放购物车的key */
@Value("${COOKIE_CART_KEY}")
private String COOKIE_CART_KEY;
/**
* 添加商品到redis或cookie购物车
*
* @param itemId
* @param num
* @param request
* @param response
* @return
*/
// /cart/add/149204693130763.html?num=4
@RequestMapping("/cart/add/{itemId}")
public String addItemCart(@PathVariable Long itemId, Integer num, HttpServletRequest request,
HttpServletResponse response) {
// 1.从cookie中获取token
String token = CookieUtils.getCookieValue(request, COOKIE_TOKEN_KEY);
// 2根据token调用SSO的服务,获取用户的信息
TaotaoResult result = loginService.getUserByToken(token);
// 3.判断,如果用户存在,说明已经登录
// 3.1首先调用商品服务的方法,获取商品的数据tbitem
TbItem tbItem = itemService.getItemById(itemId);
if (result.getStatus() == 200) {
// 3.2获取用户信息中的userId
TbUser tbUser = (TbUser) result.getData();
// 3.3调用添加购物车的方法 将商品数据添加到redis中
cartService.addItemCart(tbItem, num, tbUser.getId());
} else {
// 4.判断,如果用户不存在,说明未登录,将商品数据添加到cookie中
// 4.1先根据cookie获取购物车的列表
}
return "cartSuccess";
}
3.2.3配置springmvc.xml
加载properties文件与引入服务
<context:property-placeholder location="classpath:resource/resource.properties" />
<dubbo:reference interface="com.taotao.cart.service.CartService" id="cartService" timeout="300000" />
3.3测试访问
安装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-portal-web不用管,回退到商品搜索页,会发现已经登录了,说明cookie中写入了token。点击小米6x
点击加入购物车
提示成功加入购物车
查看redis是否已经加入购物车,商品已经成功存入。
4.未登录状态下添加购物车
4.1服务层
服务层不变,存入cookie,需要要使用servlet原生response对象,跟service没什么关系,所以放在controller中。
4.2表现层
在addItemCart判断用户没登录中添加如下,需要判断cookie中是否已存在该商品,存在的话商品数量需要相加,不存在的话直接设置商品数量,还需要设置图片为第一张图片,最后设置cookie存放时间为一个星期(7*24*3600)
由于从cookie中获取购物车方法经常使用单独抽成一个私有方法
完整代码:
package com.taotao.cart.controller;
import java.util.ArrayList;
import java.util.List;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import com.taotao.cart.service.CartService;
import com.taotao.common.pojo.TaotaoResult;
import com.taotao.common.utils.CookieUtils;
import com.taotao.common.utils.JsonUtils;
import com.taotao.pojo.TbItem;
import com.taotao.pojo.TbUser;
import com.taotao.service.ItemService;
import com.taotao.sso.service.UserLoginService;
@Controller
public class CartController {
/** 引入服务 */
/** 注入依赖 */
@Autowired
private CartService cartService;
@Autowired
private ItemService itemService;
@Autowired
private UserLoginService loginService;
/** COOKIE中存放token的key */
@Value("${COOKIE_TOKEN_KEY}")
private String COOKIE_TOKEN_KEY;
/** COOKIE中存放购物车的key */
@Value("${COOKIE_CART_KEY}")
private String COOKIE_CART_KEY;
/**
* 添加商品到redis或cookie购物车
*
* @param itemId
* @param num
* @param request
* @param response
* @return
*/
// /cart/add/149204693130763.html?num=4
@RequestMapping("/cart/add/{itemId}")
public String addItemCart(@PathVariable Long itemId, Integer num, HttpServletRequest request,
HttpServletResponse response) {
// 1.从cookie中获取token
String token = CookieUtils.getCookieValue(request, COOKIE_TOKEN_KEY);
// 2根据token调用SSO的服务,获取用户的信息
TaotaoResult result = loginService.getUserByToken(token);
// 3.判断,如果用户存在,说明已经登录
// 3.1首先调用商品服务的方法,获取商品的数据tbitem
TbItem tbItem = itemService.getItemById(itemId);
if (result.getStatus() == 200) {
// 3.2获取用户信息中的userId
TbUser tbUser = (TbUser) result.getData();
// 3.3调用添加购物车的方法 将商品数据添加到redis中
cartService.addItemCart(tbItem, num, tbUser.getId());
} else {
// 4.判断,如果用户不存在,说明未登录,将商品数据添加到cookie中
// 4.1先根据cookie获取购物车的列表
List<TbItem> cartList = getCookieCartList(request);
boolean flag = false;
// 4.2判断如果购物车中有包含要添加的商品 商品数量相加
for (TbItem tbItem2 : cartList) {
// 4.3 找到列表中的商品 更新数量
if (tbItem2.getId() == itemId.longValue()) {
tbItem2.setNum(tbItem2.getNum() + num);
flag = true;
break;
}
}
if (!flag) {
// 4.4如果没有就直接添加到购物车
// 4.5设置数量与图片
tbItem.setNum(num);
if (tbItem.getImage() != null) {
tbItem.setImage(tbItem.getImage().split(",")[0]);
}
cartList.add(tbItem);
}
// 4.6存到cookie中
CookieUtils.setCookie(request, response, COOKIE_CART_KEY, JsonUtils.objectToJson(cartList), 7 * 24 * 3600,
true);
}
return "cartSuccess";
}
/** 获取购物车列表 */
private List<TbItem> getCookieCartList(HttpServletRequest request) {
// 1.从cookie中获取购物车列表
String cartJson = CookieUtils.getCookieValue(request, COOKIE_CART_KEY, true);
// 2.将cartJson转为List<TbItem>
if (StringUtils.isNotBlank(cartJson)) {
List<TbItem> list = JsonUtils.jsonToList(cartJson, TbItem.class);
return list;
}
return new ArrayList<>();
}
}
4.3访问测试
首先退出用户
添加商品到购物车
提示添加成功
使用我已经做好的查看购物车列表的功能,查看cookie中是否存入了购物车
可以看到未登录的情况下,添加购物车成功