目錄
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中是否存入了購物車
可以看到未登錄的情況下,添加購物車成功