購物車原理以及實現
本文講什麼
可以看到,購物車這樣一個功能模組,在各種購物類APP或者web應用中絕對是必不可少的東西.不論在大學中的課程設計,還是在實際的專案開發中,絕對非常重要且有些複雜的內容.
在實際操作中,身邊有很多的小夥伴遇到編寫購物車的程式碼的時候,有時候真的是一臉懵逼,總是搞不明白設計的思路,這就是本文寫作的原因.
所以,本文適合搞不清楚購物車實現原理,知道原理但是實際編碼不知道如何下手的小夥伴,我將給出一個思路以及實際的程式碼供大家參考.
在本文中,我將會用盡可能簡單的句子,表達出我想表達的意思.廢話不多說,開始我們的購物車實戰!
購物車的幾種實現方式
購物車的實現方式有很多,但是最常見的就三種:Cookie,Session,資料庫.三種方法各有優劣,適合的場景各不相同.
- Cookie方法:通過把購物車中的商品資料寫入Cookie中,再通過瀏覽器進行讀取.這個方法,適合在使用者沒有登入的情況下使用,但是有個非常嚴重的缺點,即在使用者禁用了Cookie的時候是無法使用的.
- Session方法:通過Session來儲存商品資訊,這確實是個好的方法,適合使用者已經登入的情況,將資料放在Session中,使用者就能讀取購物車中的商品資訊,而且速度十分的快.但是缺點也很明顯,由於Session是建立在使用者客戶端和伺服器之間的,在Session中儲存資料,無疑會增加伺服器的負擔.
- 資料庫(Redis):資料庫無疑是一種非常棒的儲存購物車中資訊的有效途徑,且能夠持久化儲存,但是問題也很明顯,那就是讀取速度會差強人意.
好了,下面來說一下幾種實現方式的應用場景.
- 當用戶沒有登入的情況下,使用者將商品加入購物車,此時的商品資訊是寫入了Cookie中,並且會設定一個儲存時間,即使關閉瀏覽器過一段時間訪問仍能看到購物車中的資訊.(或者將購物資料寫入Session中,但是關閉瀏覽器,購物車中的資訊也就不見了)
- 使用者登陸後,如果在Session中儲存了商品資訊且沒有關閉瀏覽器(如果在Cookie中儲存了商品資訊且沒有過期),將會讀取其中的商品資訊,並且將這些資訊寫入資料庫中進行持久儲存.
本文的行文方式說明
經過上面的講解,我想你一定對購物車有所瞭解,為了使讀者更加清晰的明白購物車的實現,我們省去了在未結算的狀態下的持久化資料庫.
也就是說,在文章中,我將使用Session來實現購物車,並且當用戶沒有登入的情況下,禁止使用者將商品加入購物車.當然你不必為此擔憂,即使我這樣做,我的程式碼已經包括了整個購物操作的絕大多數步驟.請耐心向下看.
此外,本文使用SSM框架作為行文程式碼.
如果你是初學者也不必擔心,我將為你提供一套專案的原始碼,可以在我的GitHub中獲取—->
購物車模組的實現
資料庫設計
- 使用者表
欄位 | 意義 |
---|---|
id | 使用者id |
userName | 使用者名稱 |
password | 使用者密碼 |
- 商品表
欄位 | 意義 |
---|---|
id | 商品id |
commName | 商品名稱 |
price | 商品價格 |
- 訂單表
欄位 | 意義 |
---|---|
id | 訂單id |
commName | 商品名稱 |
count | 商品數量 |
subtotal | 商品小計 |
total | 總價 |
使用者登入
為了實現我上述的思路,肯定是要求使用者先行登入.程式碼如下.
- LoginController
@Controller
public class LoginController {
private LoginService loginService;
private CommonService commonService;
@Autowired
public LoginController(LoginService loginService, CommonService commonService) {
this.loginService = loginService;
this.commonService = commonService;
}
@RequestMapping("/login")
public String login(User user, HttpSession session, Model model) {
//登入驗證
if (loginService.isUser(user)) {
List<Common> commons = commonService.selectAllCommons();
model.addAttribute("commons", commons);
model.addAttribute("username", user.getUsername());
//把使用者資訊儲存到session中
session.setAttribute("user", user);
return "shopping";
} else {
model.addAttribute("message", "使用者名稱或密碼錯誤");
return "index";
}
}
}
這是最常規的使用者登入的程式碼,思路就是拿著使用者名稱到資料庫裡面查詢,如果能查到,則說明使用者名稱無誤,如果查不到則說明沒有此使用者,提示使用者註冊.如果使用者名稱存在,再比對密碼,一般密碼不會像我們這樣直接在資料庫裡面使用明文密碼,都是會加鹽的(MD5演算法).如果比對密碼的結果為true,則使用者可以登入.比對過程isUser的程式碼如下.
@Service
public class LoginService {
private UserMapper userMapper;
@Autowired
public LoginService(UserMapper userMapper) {
this.userMapper = userMapper;
}
/**
* 判斷使用者名稱或密碼是否正確
* @param user
* @return
*/
public boolean isUser(User user){
UserExample example = new UserExample();
UserExample.Criteria criteria = example.createCriteria();
criteria.andUsernameEqualTo(user.getUsername());
List<User> eqUser = userMapper.selectByExample(example);
//如果沒有查詢到user,則返回false
if (eqUser == null){
return false;
}
return eqUser.get(0).getPassword().equals(user.getPassword());
}
}
確認使用者登入以後,需要把使用者資訊放在session中以便後續過程使用.
使用者購物模組
當用戶登入以後,展示在使用者眼前的介面是這樣的(頁面模板來自菜鳥教程,經過改編):
左欄中的資料來自登入程式碼中的
List<Common> commons = commonService.selectAllCommons();
model.addAttribute("commons", commons);
當點選加入購物車以後,觸發onlick事件:onclick="javascript:joinCart(${common.id})"
詳細程式碼如下:
function joinCart(id) {
$.ajax({
url: "${pageContext.request.contextPath}/shop/joinCart",
data: "id=" + id,
type: "POST",
success: function (result) {
alert("加入購物車成功!");
//清空購物車列表
$("#shop_cart tbody").empty();
//動態構建購物車列表
var obj = result;
$.each(obj,function (index,item) {
var emptyTd = $("<td></td>").append("#");
var commnameTd = $("<td></td>").append(item.commname);
var countTd = $("<td></td>").append(item.count);
var subtotalTd = $("<td></td>").append(item.subtotal);
$("<tr></tr>")
.append(emptyTd)
.append(commnameTd)
.append(countTd)
.append(subtotalTd)
.appendTo("#shop_cart tbody");
//設定總金額
var totalSpan = document.getElementById("subtotal");
totalSpan.innerHTML = item.total;
});
}
})
}
可以看到,當觸發這個方法時,實際上是使用了非同步請求的方式向服務端傳送資料,服務端做相應處理以後,封裝購物車列表,然後把購物車商品列表以JSON格式傳回,也就是封裝在result中,利用js,動態構建購物車列表.於是就出現下面這種情況.
當將商品加入購物車以後:
首先提示使用者已經加入購物車,然後在利用非同步請求構建整個購物車,如果你對前端的瞭解並不是很深,不必擔心,這部分內容實際上很簡單,你可以隨便百度一下這個知識點,記住就好了.實際上就是利用js操作json資料而已.
其實對於初學者來說,感覺上面的過程挺神奇的,其實不然.前端的程式碼看完了,我就來給你詳細的解釋一下後端的程式碼.
首先,可以將後段程式碼分成兩部分,一部分是判斷,各種判斷,另外一部分是封裝資料,相對簡單.
//識別符號:判斷是否存在此商品
boolean flag = false;
//通過id查詢商品資訊
Common common = shopService.selectCommById(Integer.parseInt(id));
//從session中獲取購物車資訊
List<Order> shopcart = (List<Order>) session.getAttribute("shopcart");
//獲取使用者資訊
User user = (User) session.getAttribute("user");
if (user == null) {
//如果使用者為空,則直接返回,讓使用者登入
throw new RuntimeException("使用者未登入");
}
//判斷購物車列表是否為空
if (shopcart == null) {
//new 一個集合
shopcart = new ArrayList<>();
}
先判斷使用者是否已經登入,如果使用者已經登入,則執行後續流程,如果使用者沒有登入,則直接丟擲異常,交給非同步請求的error處理,提示使用者登入即可.
如果使用者已經登入,則繼續下面的步驟,判斷購物車是否為空,為空也就是說明使用者沒有將任何商品加入購物車,則需要建立一個新的ArrayList集合,同時利用商品id查詢出的商品資訊,封裝訂單物件.
else {
for (Order order : shopcart) {
//判斷是否存在此商品,存在則數量+1
if (order.getCommname().equals(common.getCommname())) {
flag = true;
order.setCount(order.getCount() + 1);
order.setSubtotal(order.getCount() * common.getPrice());
}
}
}
在遍歷的過程中,如果遍歷的資料的commName和查到的name相同的話,則證明是同一件商品,則將此商品的數量+1,然後再設定小計價格即可.同時將flag設定為true,表示遍歷到了同樣的資料.
如果沒有遍歷到名稱相同的商品,則直接新建一個物件,封裝資料,加入集合.
//如果購物車中沒有當前商品的資訊,則新增商品
if (!flag) {
Order order = new Order();
order.setCommname(common.getCommname());
order.setCount(1);
order.setSubtotal(common.getPrice());
//把商品加入集合
shopcart.add(order);
}
最後一步就是計算總價格,封裝資料即可.
//計算總價格
Double total = 0d;
for (Order order : shopcart) {
total += order.getSubtotal();
}
for (Order order : shopcart) {
order.setTotal(total);
}
//設定session
session.setAttribute("shopcart", shopcart);
//返回list
return shopcart;
購物車全部程式碼如下:
Controller
@RequestMapping("/shop")
public class ShopController {
private ShopService shopService;
public ShopController(ShopService shopService) {
this.shopService = shopService;
}
@RequestMapping("/joinCart")
@ResponseBody
public List<Order> joinCart(String id, HttpSession session, Model model) {
//識別符號:判斷是否存在此商品
boolean flag = false;
//通過id查詢商品資訊
Common common = shopService.selectCommById(Integer.parseInt(id));
//從session中獲取購物車資訊
List<Order> shopcart = (List<Order>) session.getAttribute("shopcart");
//獲取使用者資訊
User user = (User) session.getAttribute("user");
if (user == null) {
//如果使用者為空,則直接返回,讓使用者登入
throw new RuntimeException("使用者未登入");
}
//判斷購物車列表是否為空
if (shopcart == null) {
//new 一個集合
shopcart = new ArrayList<>();
} else {
for (Order order : shopcart) {
//判斷是否存在此商品,存在則數量+1
if (order.getCommname().equals(common.getCommname())) {
flag = true;
order.setCount(order.getCount() + 1);
order.setSubtotal(order.getCount() * common.getPrice());
}
}
}
//如果購物車中沒有當前商品的資訊,則新增商品
if (!flag) {
Order order = new Order();
order.setCommname(common.getCommname());
order.setCount(1);
order.setSubtotal(common.getPrice());
//把商品加入集合
shopcart.add(order);
}
//計算總價格
Double total = 0d;
for (Order order : shopcart) {
total += order.getSubtotal();
}
for (Order order : shopcart) {
order.setTotal(total);
}
//設定session
session.setAttribute("shopcart", shopcart);
//返回list
return shopcart;
}
}
關於操作購物車商品數量及結算
首先說操作購物車商品數量,既然我們能夠按照通過id加商品的數量,肯定也是能夠按照商品id減商品的數量,這部分無需多說,相信按照上面的程式碼,以你的聰明才智,肯定是能夠做出來的.
至於結算操作,就更加單了.
使用者點選結算按鈕以後,跳轉到後臺,通過後臺程式碼,先把session中儲存的資料取出,然後遍歷將資料寫入資料庫,進行持久化的操作即可.
以上.
獲取文中專案程式碼:https://download.csdn.net/download/yanmiao0715/10570386
如果您的積分不夠,歡迎關注我的微信公眾號:最高許可權位元流,回覆”購物車原始碼”進行下載.
結語
感謝您的閱讀,如果您對文章有任何問題,歡迎留言,歡迎聯絡我:[email protected]
也歡迎您關注我的微信公眾號:最高許可權位元流.
以及我的個人部落格:www.roobtyan.cn
相關推薦
購物車原理以及實現
本文講什麼 可以看到,購物車這樣一個功能模組,在各種購物類APP或者web應用中絕對是必不可少的東西.不論在大學中的課程設計,還是在實際的專案開發中,絕對非常重要且有些複雜的內容. 在實際操作中,身邊有很多的小夥伴遇到編寫購物車的程式碼的時候,有時候真的是一
瞭解MmMapIoSpace以及MmUnmapIoSpace函式的實現原理以及實現方法
分享一下我老師大神的人工智慧教程!零基礎,通俗易懂!http://blog.csdn.net/jiangjunshow 也歡迎大家轉載本篇文章。分享知識,造福人民,實現我們中華民族偉大復興!  
python中裝飾器的原理以及實現,
python版本 3.6 1.python的裝飾器說白了就是閉包函式的一種應用場景,在運用的時候我們遵循 #開放封閉原則:對修改封閉,對拓展開放 2.什麼是裝飾器 #裝飾他人的器具,本身可以是任意可呼叫的物件,被裝飾者也可以是任意可呼叫物件 #裝飾器的原則:1.不可修改被裝飾物件的原始
決策樹(ID3,C4.5,CART)原理以及實現
決策樹 決策樹是一種基本的分類和迴歸方法.決策樹顧名思義,模型可以表示為樹型結構,可以認為是if-then的集合,也可以認為是定義在特徵空間與類空間上的條件概率分佈. [圖片上傳失敗...(image-2e6565-1543139272117)] 決策樹的中間節點可以看做是對一種特徵的判斷,也是符合上一
Ajax原理以及實現(js實現以及jquery實現)
1.Ajax簡介 Ajax:非同步js,xml 非同步重新整理:如果網頁中某一個地方需要修改,非同步重新整理可以使只重新整理的地方修改,而不是全域性修改,比如,你看視訊點贊不可能你點一個贊就重新整理整個視訊頁面吧 2.js實現Ajax js: XMLHttpReques
Early Retransmit for TCP原理以及實現
Early Retransmit for TCP(ER)是google為了解決快重傳的一些侷限,從而對快重傳(fast retransmit)做出的一些改變,其中ER在linux kernel 3.5進入了核心,他的paper在這裡: 首先我們要知道快重傳演算法的弱點很多,比如如果傳送端接收不到足夠數量(一
棧的原理以及實現(基於陣列)
棧的定義: 限制僅在表的一端進行插入和刪除運算的線性表。 可以實現“先進後出(或者叫後進先出)”的儲存結構。 棧頂(Top): 允許操作的一端。 棧底(Bottom): 不允許操作的一端。 特點:後進先出。 舉例:物流裝車,先裝車的後出來,後裝車的先出來。 棧的結構: 空
排序演算法原理以及實現
1.氣泡排序演算法 2.插入排序演算法 /* * 1.第一個元素開始,假設第一個元素已排序 * 2.取下一個元素temp_val,在已排序的區間從後往前掃描,如果大於temp_val,則往後移 * 3.直到小於的時候,將其後一位置為temp_val即可 * 4.重複n-1次2、3步驟
socket通訊原理以及實現
服務端 package com.hmsm.socket.server; import java.io.DataInputStream; import java.io.DataOutputStream
目標檢測演算法(二)——具體原理以及實現
1.1光流法原理 光流的概念是Gibson在1950年首先提出來的。它是空間運動物體在觀察成像平面上的畫素運動的瞬時速度,是利用影象序列中畫素在時間域上的變化以及相鄰幀之間的相關性來找到上一幀跟當前幀之間存在的對應關係,從而計算出相鄰幀之間物體的運動資訊的一種方法。一般而言,光流是由
CART演算法的原理以及實現
CART 分類迴歸樹(classification and regression tree,CART)模型由Breiman等人在1984年提出,是應用廣泛的決策樹學習方法。CART同樣由特徵選擇、樹的生成以及剪枝組成,既可以用於分類也可以用於迴歸。同
微信域名檢測 騰訊微信域名檢測的機制原理以及實現方式
array mstr location ati dsp 營銷 lse ram csdn 最近在網上看到很多網友在問微信域名攔截檢測API接口。有的是想找一個穩定靠譜的服務商,有的是剛接觸這方面的業務想通過程序來代替之前的人工檢測,更有甚者想具體了解微信域名檢測API接口的原
資料結構 — 淺析紅黑樹原理以及實現
淺析紅黑樹原理以及實現我們在上一篇部落格認識到了平衡二叉樹(AVLTree),瞭解到平衡二叉樹的性質,其實平衡二叉樹最大的作用就是查詢,AVL樹的查詢、插入和刪除在平均和最壞情況下都是O(logn)。AVL樹的效率就是高在這個地方。如果在AVL樹中插入或刪除節點後,使得高度之
【java專案實踐】詳解Ajax工作原理以及實現非同步驗證使用者名稱是否存在+原始碼下載(java版)
一年前,從不知道Ajax是什麼,伴隨著不斷的積累,到現在經常使用,逐漸有了深入的認識。今天,如果想開發一個更加人性化,友好,無重新整理,互動性更強的網頁,那您的目標一定是Ajax。 介紹
微信域名檢測、騰訊微信域名檢測的機制原理以及實現方式
不知道 bsp 商家 線程 推廣 雲安全 lan img 用戶 需求解析 針對微信轉發分享鏈接等過程中,域名被QQ管家雲安全過濾攔截而無法正常瀏覽,或者直接被微信攔截,例如該網頁包含誘導分享內容,被多人投訴等問題一直困擾了很多小團隊。首先解決不掉微信攔截域名的問題,其次是做
(9)launcher3 之 外部 更換主題Theme APP demo 實現原理以及demo
解壓 work ace fontsize 思路 con 鎖屏 解壓文件夾 更新 先說下我的思路: luancher3裏面更換圖標的邏輯例如以下: 先從APP資源包裏查詢--數據庫查詢--其它地方查詢ICON 因此,我們僅僅須要把 從數據庫獲取ICON 代碼提前到 從A
八大排序算法原理以及Java實現(直接插入排序)
不能 oat 設立 side 堆排 八大排序 算法 line load 概述 排序有內部排序和外部排序,內部排序是數據記錄在內存中進行排序,而外部排序是因排序的數據很大,一次不能容納全部的排序記錄,在排序過程中需要訪問外存。 我們這裏說說八大排序就是內部排序。
ConcurrentHashMap實現原理以及源碼分析
賦值 already 設計 [] 取數 ole vat 復制 變化 ConcurrentHashMap是HashMap的高並發版本,是線程安全的,而HashMap是非線程安全的 一、底層實現 底層結構跟hashmap一樣,都是通過數組+鏈表+紅黑樹實現的,不過它要保證線程
svm原理以及利用現成庫實現
blog tps 就是 print ear 原理 允許 ins tails SVM 1 由來利用一根直線或者一個超平面把數據按照某種規則區分開來 2 最大間隔分類器上面我們推導出了間隔的表達式,自然的,我們想讓數據點離超平面越遠越好: 3 核函數在前面的討論中,我們假設數據
CopyOnWriteArrayList實現原理以及原始碼解析
CopyOnWriteArrayList實現原理以及原始碼解析 1、CopyOnWrite容器(併發容器) Copy-On-Write簡稱COW,是一種用於程式設計中的優化策略。 其基本思路是,從一開始大家都在共享同一個內容,當某個人想要修改這個內容的時候,才