1. 程式人生 > >淘淘商城67-商城購物車系統實現之登入與未登入狀態下新增商品到購物車

淘淘商城67-商城購物車系統實現之登入與未登入狀態下新增商品到購物車

目錄

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層

業務邏輯:

  1. 根據商品的id與使用者id從redis查詢商品的資訊
  2. 判斷要新增的商品是否存在與redis中
  3. 如果存在,將新增商品的數量與redis已存在的商品數量相加後,存入redis
  4. 如果不存在,直接設定商品數量為新增的商品數量,並設定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

返回值:新增購物車成功頁面。

處理的邏輯:

  1. 呼叫sso的服務,獲取使用者相關的資訊
  2. 呼叫manager的服務,獲取商品的相關的資訊
  3. 判斷如果是登入的狀態,呼叫登入的新增購物車的service
  4. 如果是未登入的狀態,呼叫的是未登入的新增購物車的方法。

由於要呼叫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中是否存入了購物車

可以看到未登入的情況下,新增購物車成功

相關推薦

商城67-商城購物車系統實現登入登入狀態新增商品購物車

目錄 1.匯入靜態資源 將參考資料中的購物車靜態頁面下js、css、images匯入webapp下,將jsp匯入WEB-INF下 2.修改商品詳情頁 商品詳情在taotao-item-web系統的item

商城69-商城購物車系統實現登入登入狀態更新購物車商品數量

目錄 1.更新購物車的商品數量的js分析 在taotao-cart-web的cart.js中有更新商品時js事件處理。 商品數量加一、減一時會觸發對應的事件,修改dom,從而修改前端展示的價格 然後會非同步請求u

商城68-商城購物車系統實現登入登入狀態展示購物車

目錄 1.功能分析 新增商品到購物車後,會提示去購物車結算,會跳轉到cart/cart.html,可以看到購物車中商品列。 在cart.jsp,我們可以看到需要準備一個cartList商品集合到model中。需要修改$

day79_商城專案_商城購物車系統實現三種方案總結

1、商城購物車系統實現的三種方案 1.1、session   將購物車直接存放到與使用者相關的session中。優點:  程式碼實現超級簡單。缺點:  購物車存在session當中,如果session銷燬,購物車就沒有了。(session只存在於一次會話中。)  使用者未登入的時候不能新增購物車

資料一致性-分割槽可用性-效能——多副本強同步資料庫系統實現我見

新浪微博:@何_登成 1背景    1 5總結    10 背景 最近,@阿里正祥(陽老師)發了上面的一條微博,誰知一石激起千層浪,國內各路資料庫領域的朋友在此條微博上發散出無數新的話題,爭吵有之,激辯有之,抨擊有之,不一而足。總體來說,大家重

【Linux初學】系統分割槽分割槽格式化

前言:該部落格主要為慕課網上一節課的筆記 系統分割槽之分割槽與格式化 在此感謝老師通俗易懂的講解 前幾天我在鬧電腦時也遇到了關於分割槽的問題:主分割槽與邏輯分割槽的區別,在此篇部落格都記錄了下來。 1.分割槽的概念  首先,什麼是分割槽?分割槽其實就是我們的硬碟需要分成

億級流量系統架構如何在上萬併發場景設計可擴充套件架構(上)?【石杉的架構筆記】

歡迎關注個人公眾號:石杉的架構筆記(ID:shishan100) 週一至週五早8點半!精品技術文章準時送上! 一、寫在前面 之前更新過一個“億級流量系統架構”系列,主要講述了一個大規模商家資料平臺的如下幾個方面: 如何承載百億級資料儲存 如何設計高容錯的分散式架構 如何設計承載百億流量的高效能架構

億級流量系統架構如何在上萬併發場景設計可擴充套件架構(中)?【石杉的架構筆記】

歡迎關注個人公眾號:石杉的架構筆記(ID:shishan100) 週一至週五早8點半!精品技術文章準時送上! 目錄 一、前情提示 二、清晰劃分系統邊界 三、引入訊息中介軟體解耦 四、利用訊息中介軟體削峰填谷 五、手動流量開關配合資料庫運維 六、支援多系統同時訂閱資料 七、系統解耦後的感受 八、下集預告

億級流量系統架構如何在上萬併發場景設計可擴充套件架構()?【石杉的架構筆記】

歡迎關注個人公眾號:石杉的架構筆記(ID:shishan100) 週一至週五早8點半!精品技術文章準時送上! 一、前情提示 上一篇文章億級流量系統架構之如何在上萬併發場景下設計可擴充套件架構(中)?分析了一下如何利用訊息中介軟體對系統進行解耦處理。 同時,我們也提到了使用訊息中介軟體還有利

億級流量系統架構如何保證百億流量的資料一致性(上)【石杉的架構筆記】

歡迎關注個人公眾號:石杉的架構筆記(ID:shishan100) 週一至週五早8點半!精品技術文章準時送上! 目錄 一、前情提示 二、什麼是資料一致性? 三、一個數據計算鏈路的梳理 四、資料計算鏈路的bug 五、電商庫存資料的不一致問題 六、大型系統的資料不一致排查有多困難 七、下篇預告 一、前情提示

億級流量系統架構如何保證百億流量的資料一致性(中)?【石杉的架構筆記】

歡迎關注個人公眾號:石杉的架構筆記(ID:shishan100) 週一至週五早8點半!精品技術文章準時送上! 目錄 一、多系統訂閱資料回顧 二、核心資料的監控系統 三、電商庫存資料如何監控 四、資料計算鏈路追蹤 五、百億流量下的資料鏈路追蹤 六、自動化資料鏈路分析 七、下篇預告

億級流量系統架構如何保證百億流量的資料一致性()?【石杉的架構筆記】

歡迎關注個人公眾號:石杉的架構筆記(ID:shishan100) 週一至週五早8點半!精品技術文章準時送上! 目錄 一、前情提示 二、選擇性訂閱部分核心資料 三、RabbitMQ的queue與exchange的繫結回顧 四、direct exchange實現訊息路由 五、按需訂閱數的程式碼實現 六、更加強

演算法實現寶石石頭

題目描述: 給定字串 J 代表石頭中寶石的型別,和字串 S代表你擁有的石頭。 S中每個字元代表了一種你擁有的石頭的型別,你想知道你擁有的石頭中有多少是寶石。 J 中的字母不重複,J 和

Linux——系統分割槽分割槽格式化

分割槽型別 主分割槽: 最多隻能有4個:由硬碟的結果決定的   每個扇區512個位元組  446個位元組用來記錄儲存資訊 剩下的64個位元組用來進行分割槽表示   所以只能最多表示4個   每個16位元組 擴充套件分割槽: 最多隻能有1個  強制概念主分割槽加擴充套件分割

實現Struts2中對登入的jsp頁面進行攔截功能(採用的是Struts2中過濾器進行過濾攔截)

Struts2中攔截器大家都很經常使用,但是攔截器只能攔截action不能攔截jsp頁面。這個時候就有點尷尬了,按道理來說沒登入的使用者只能看login介面不能夠通過輸入URL進行介面跳轉,這顯然是不合理的。這裡介紹Struts2中Filter實現jsp頁面攔截的功能。(有

day79_商城專案_12_購物車流程 + 商城購物車系統的搭建 + 商城購物車系統實現分析 + 購物車實現增刪改查_匠心筆記

課程計劃 1、購物車的流程 2、購物車的實現 a) 登入狀態下的購物車實現 b) 未登入狀態下的購物車實現 1、購物車流程 1.1、以前的購物車流程 使用者將商品新增到購物車時,判斷使用者是否登入,如果已經登入將購物車放入se

day79_商城專案_12_購物車流程 + 商城購物車系統的搭建 + 商城購物車系統實現分析(cookie+redis方案) + 購物車實現增刪改查_匠心筆記

淘淘商城專案_12 1、購物車流程 1.1、以前的購物車流程 1.2、現在的購物車流程 2、商城購物車系統的搭建 2.1、購物車系統的架構 2.2、服務層工程搭建

學習商城第九十六課(購物車實現分析及工程搭建)

        關於購物車模組,京東和淘寶並不一樣,京東允許使用者在沒有登入的情況下就使用購物車,而且加到購物車裡面的商品可以一直儲存著(其實是放到了Cookie當中,如果清空了Cookie也就清空購物車了)。而淘寶則是必須先登入才能將商品新增到購物車當中,就使用者體驗來說

帶你逐步深入瞭解SSM框架——商城專案購物車+訂單實現

1   今日大綱 1、  實現淘淘商城的購物車功能 2、  實現訂單系統。 2   購物車功能 2.1  功能說明 1、商品加入購物車時,不是必須要求登入。 2、計算購物車中商品的總價。當商品數量發

day80_商城專案_13_訂單系統搭建 + 展示訂單確認頁面 + 使用者身份認證(SpringMVC攔截器) + 實現提交訂單功能_匠心筆記

淘淘商城專案_13 1、訂單系統搭建 1.1、功能分析 1.2、工程搭建 1.2.1、建立訂單服務層工程 1.2.2、建立訂單表現層工程 2、展示訂單確認頁面