加入購物車
1 購物車-創建數據表
1.使用use命令先選中store數據庫。
USE store;
2.在store數據庫中創建t_cart用戶數據表。
CREATE TABLE t_cart (cid INT AUTO_INCREMENT COMMENT '購物車數據id',uid INT NOT NULL COMMENT '用戶id',pid INT NOT NULL COMMENT '商品id',price BIGINT COMMENT '加入時商品單價',num INT COMMENT '商品數量',created_user VARCHAR(20) COMMENT '創建人',created_time DATETIME COMMENT '創建時間',modified_user VARCHAR(20) COMMENT '修改人',modified_time DATETIME COMMENT '修改時間',PRIMARY KEY (cid)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
2 購物車-創建實體類
????????在com.cy.store.entity包下創建購物車的Cart實體類。
package com.cy.store.entity;
import java.io.Serializable;
?
/** 購物車數據的實體類 */
public class Cart extends BaseEntity implements Serializable {private Integer cid;private Integer uid;private Integer pid;private Long price;private Integer num;
?// Generate: Getter and Setter、Generate hashCode() and equals()、toString()
}
3 購物車-添加購物車-持久層
3.1 規劃需要執行的SQL語句
????????向購物車表中插入商品數據的SQL語句大致是:
insert into t_cart (除了cid以外的字段列表) values (匹配的值列表);
????????如果用戶曾經將某個商品加入到購物車過,則點擊“加入購物車”按鈕只會對購物車中相同商品數量做遞增操作。
update t_cart set num=? where cid=?
????????關于判斷“到底應該插入數據,還是修改數量”,可以通過“查詢某用戶是否已經添加某商品到購物車”來完成。如果查詢到某結果,就表示該用戶已經將該商品加入到購物車了,如果查詢結果為null,則表示該用戶沒有添加過該商品。
select * from t_cart where uid=? and pid=?
3.2 接口與抽象方法
????????在com.cy.store.mapper包下創建CartMapper接口,并添加抽象相關的方法。
package com.cy.store.mapper;
import com.cy.store.entity.Cart;
import org.apache.ibatis.annotations.Param;
import java.util.Date;
?
/** 處理購物車數據的持久層接口 */
public interface CartMapper {/*** 插入購物車數據* @param cart 購物車數據* @return 受影響的行數*/Integer insert(Cart cart);
?/*** 修改購物車數據中商品的數量* @param cid 購物車數據的id* @param num 新的數量* @param modifiedUser 修改執行人* @param modifiedTime 修改時間* @return 受影響的行數*/Integer updateNumByCid(@Param("cid") Integer cid,@Param("num") Integer num,@Param("modifiedUser") String modifiedUser,@Param("modifiedTime") Date modifiedTime);
?/*** 根據用戶id和商品id查詢購物車中的數據* @param uid 用戶id* @param pid 商品id* @return 匹配的購物車數據,如果該用戶的購物車中并沒有該商品,則返回null*/Cart findByUidAndPid(@Param("uid") Integer uid,@Param("pid") Integer pid);
}
3.3 配置SQL映射
1.在resources.mapper文件夾下創建CartMapper.xml文件,并在文件中配置以上三個方法的映射。
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.cy.store.mapper.CartMapper"><resultMap id="CartEntityMap" type="com.cy.store.entity.Cart"><id column="cid" property="cid"/><result column="created_user" property="createdUser"/><result column="created_time" property="createdTime"/><result column="modified_user" property="modifiedUser"/><result column="modified_time" property="modifiedTime"/></resultMap>
?<!-- 插入購物車數據:Integer insert(Cart cart) --><insert id="insert" useGeneratedKeys="true" keyProperty="cid">INSERT INTO t_cart (uid, pid, price, num, created_user, created_time, modified_user, modified_time)VALUES (#{uid}, #{pid}, #{price}, #{num}, #{createdUser}, #{createdTime}, #{modifiedUser}, #{modifiedTime})</insert>
?<!-- 修改購物車數據中商品的數量:Integer updateNumByCid(@Param("cid") Integer cid,@Param("num") Integer num,@Param("modifiedUser") String modifiedUser,@Param("modifiedTime") Date modifiedTime) --><update id="updateNumByCid">UPDATEt_cartSETnum=#{num},modified_user=#{modifiedUser},modified_time=#{modifiedTime}WHEREcid=#{cid}</update>
?<!-- 根據用戶id和商品id查詢購物車中的數據:Cart findByUidAndPid(@Param("uid") Integer uid,@Param("pid") Integer pid) --><select id="findByUidAndPid" resultMap="CartEntityMap">SELECT*FROMt_cartWHEREuid=#{uid} AND pid=#{pid}</select>
</mapper>
2.在com.cy.store.mapper包下創建CartMapperTests測試類,并添加測試方法。
package com.cy.store.mapper;
import com.cy.store.entity.Cart;
import com.cy.store.entity.Product;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
import java.util.Date;
import java.util.List;@RunWith(SpringRunner.class)
@SpringBootTest
public class CartMapperTests {@Autowiredprivate CartMapper cartMapper;@Testpublic void insert() {Cart cart = new Cart();cart.setUid(1);cart.setPid(2);cart.setNum(3);cart.setPrice(4L);Integer rows = cartMapper.insert(cart);System.out.println("rows=" + rows);}@Testpublic void updateNumByCid() {Integer cid = 1;Integer num = 10;String modifiedUser = "購物車管理員";Date modifiedTime = new Date();Integer rows = cartMapper.updateNumByCid(cid, num, modifiedUser, modifiedTime);System.out.println("rows=" + rows);}@Testpublic void findByUidAndPid() {Integer uid = 1;Integer pid = 2;Cart result = cartMapper.findByUidAndPid(uid, pid);System.out.println(result);}
}
4 購物車-添加購物車-業務層
4.1 規劃異常
????????在插入數據時,可能拋出InsertException異常;在修改數據時,可能拋出UpdateException異常。如果不限制購物車中的記錄的數量,則沒有其它異常。
4.2 接口與抽象方法
????????在com.cy.store.service包下創建ICartService接口,并添加抽象方法。
package com.cy.store.service;/** 處理商品數據的業務層接口 */
public interface ICartService {/*** 將商品添加到購物車* @param uid 當前登錄用戶的id* @param pid 商品的id* @param amount 增加的數量* @param username 當前登錄的用戶名*/void addToCart(Integer uid, Integer pid, Integer amount, String username);
}
4.3 實現抽象方法
1.創建com.cy.store.service.impl.CartServiceImpl類,并實現ICartService接口,并在類的定義前添加@Service注解。在類中聲明CartMapper持久層對象和IProductService處理商品數據的業務對象,并都添加@Autowired注修飾。
package com.cy.store.service.impl;
import com.cy.store.entity.Cart;
import com.cy.store.entity.Product;
import com.cy.store.mapper.CartMapper;
import com.cy.store.service.ICartService;
import com.cy.store.service.IProductService;
import com.cy.store.service.ex.InsertException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.Date;/** 處理購物車數據的業務層實現類 */
@Service
public class CartServiceImpl implements ICartService {@Autowiredprivate CartMapper cartMapper;@Autowiredprivate IProductService productService;
}
2.在CartServiceImpl類中實現業務層ICartService接口中定義的抽象方法。
@Override
public void addToCart(Integer uid, Integer pid, Integer amount, String username) {// 根據參數pid和uid查詢購物車中的數據// 判斷查詢結果是否為null// 是:表示該用戶并未將該商品添加到購物車// -- 創建Cart對象// -- 封裝數據:uid,pid,amount// -- 調用productService.findById(pid)查詢商品數據,得到商品價格// -- 封裝數據:price// -- 封裝數據:4個日志// -- 調用insert(cart)執行將數據插入到數據表中// 否:表示該用戶的購物車中已有該商品// -- 從查詢結果中獲取購物車數據的id// -- 從查詢結果中取出原數量,與參數amount相加,得到新的數量// -- 執行更新數量
}
3.addToCart(Integer uid, Integer pid, Integer amount, String username)方法的代碼具體實現。
@Override
public void addToCart(Integer uid, Integer pid, Integer amount, String username) {// 根據參數pid和uid查詢購物車中的數據Cart result = cartMapper.findByUidAndPid(uid, pid);Integer cid = result.getCid();Date now = new Date();// 判斷查詢結果是否為nullif (result == null) {// 是:表示該用戶并未將該商品添加到購物車// 創建Cart對象Cart cart = new Cart();// 封裝數據:uid,pid,amountcart.setUid(uid);cart.setPid(pid);cart.setNum(amount);// 調用productService.findById(pid)查詢商品數據,得到商品價格Product product = productService.findById(pid);// 封裝數據:pricecart.setPrice(product.getPrice());// 封裝數據:4個日志cart.setCreatedUser(username);cart.setCreatedTime(now);cart.setModifiedUser(username);cart.setModifiedTime(now);// 調用insert(cart)執行將數據插入到數據表中Integer rows = cartMapper.insert(cart);if (rows != 1) {throw new InsertException("插入商品數據時出現未知錯誤,請聯系系統管理員");}} else {// 否:表示該用戶的購物車中已有該商品// 從查詢結果中獲取購物車數據的idInteger cid = result.getCid();// 從查詢結果中取出原數量,與參數amount相加,得到新的數量Integer num = result.getNum() + amount;// 執行更新數量Integer rows = cartMapper.updateNumByCid(cid, num, username, now);if (rows != 1) {throw new InsertException("修改商品數量時出現未知錯誤,請聯系系統管理員");}}
}
4.在com.cy.store.service包下創建測試類CartServiceTests類,并編寫測試方法。
package com.cy.store.service;
import com.cy.store.entity.Product;
import com.cy.store.service.ex.ServiceException;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
import java.util.List;@RunWith(SpringRunner.class)
@SpringBootTest
public class CartServiceTests {@Autowiredprivate ICartService cartService;@Testpublic void addToCart() {try {Integer uid = 2;Integer pid = 10000007;Integer amount = 1;String username = "Tom";cartService.addToCart(uid, pid, amount, username);System.out.println("OK.");} catch (ServiceException e) {System.out.println(e.getClass().getSimpleName());System.out.println(e.getMessage());}}
}
5 購物車-添加購物車-控制器
5.1 處理異常
說明:無異常。
5.2 設計請求
????????設計用戶提交的請求,并設計響應的方式。
請求路徑:/carts/add_to_cart
請求參數:Integer pid, Integer amount, HttpSession session
請求類型:POST
響應結果:JsonResult<Void>
5.3 處理請求
1.在com.cy.store.controller包下創建CartController類并繼承自BaseController類,添加@RequestMapping("carts")和@RestController注解;在類中聲明ICartService業務對象,并使用@Autowired注解修飾。
package com.cy.store.controller;
import com.cy.store.service.ICartService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;@RestController
@RequestMapping("carts")
public class CartController extends BaseController {@Autowiredprivate ICartService cartService;}
2.在CartController類中添加處理請求的addToCart()方法。
@RequestMapping("add_to_cart")
public JsonResult<Void> addToCart(Integer pid, Integer amount, HttpSession session) {// 從Session中獲取uid和usernameInteger uid = getUidFromSession(session);String username = getUsernameFromSession(session);// 調用業務對象執行添加到購物車cartService.addToCart(uid, pid, amount, username);// 返回成功return new JsonResult<Void>(OK);
}
3.完成后啟動項目,先登錄再訪問http://localhost:8080/carts/add_to_cart?pid=10000017&amount=3進行測試。
6 購物車-添加購物車-前端頁面
1.在product.html頁面中的body標簽內的script標簽里為“加入購物車”按鈕添加點擊事件。
$("#btn-add-to-cart").click(function() {$.ajax({url: "/carts/add_to_cart",type: "POST",data: {"pid": id,"amount": $("#num").val()},dataType: "JSON",success: function(json) {if (json.state == 200) {alert("增加成功!");} else {alert("增加失敗!" + json.message);}},error: function(xhr) {alert("您的登錄信息已經過期,請重新登錄!HTTP響應碼:" + xhr.status);location.href = "login.html";}});
});
????????$.ajax函數中參數data提交請參數的方式:
// 1.適用于參數較多,且都在同一個表單中
data: $("#form表單id屬性值").serialize()
// 2.僅適用于上傳文件
data: new FormData($("##form表單id屬性值")[0])
// 3.參數拼接形式提交
data: "pid=10000005&amount=3"
// 4.使用JSON格式提交參數
data: {"pid": 10000005,"amount": 3
}
2.完成后啟動項目,先登錄再訪問http://localhost:8080/web/index.html頁面進行測試。
?顯示購物車列表
1 購物車-顯示列表-持久層
1.1 規劃需要執行的SQL語句
????????顯示某用戶的購物車列表數據的SQL語句大致是。
SELECTcid,uid,pid,t_cart.price,t_cart.num,t_product.title,t_product.price AS realPrice,t_product.image
FROMt_cartLEFT JOIN t_product ON t_cart.pid = t_product.id
WHEREuid = #{uid}
ORDER BYt_cart.created_time DESC
1.2 接口與抽象方法
1.由于涉及多表關聯查詢,必然沒有哪個實體類可以封裝此次的查詢結果,因此需要創建VO類。創建com.cy.store.vo.CartVO類。
package com.cy.store.vo;
import java.io.Serializable;/** 購物車數據的Value Object類 */
public class CartVO implements Serializable {private Integer cid;private Integer uid;private Integer pid;private Long price;private Integer num;private String title;private Long realPrice;private String image;// Generate: Getter and Setter、Generate hashCode() and equals()、toString()
}
2.在CartMapper接口中添加抽象方法。
/*** 查詢某用戶的購物車數據* @param uid 用戶id* @return 該用戶的購物車數據的列表*/
List<CartVO> findVOByUid(Integer uid);
1.3 配置SQL映射
1.在CartMapper.xml文件中添加findVOByUid()方法的映射。
<!-- 查詢某用戶的購物車數據:List<CartVO> findVOByUid(Integer uid) -->
<select id="findVOByUid" resultType="com.cy.store.vo.CartVO">SELECTcid,uid,pid,t_cart.price,t_cart.num,t_product.title,t_product.price AS realPrice,t_product.imageFROMt_cartLEFT JOIN t_product ON t_cart.pid = t_product.id WHEREuid = #{uid}ORDER BYt_cart.created_time DESC
</select>
2.在CartMapperTests測試類中添加findVOByUid()方法的測試。
@Test
public void findVOByUid() {List<CartVO> list = cartMapper.findVOByUid(31);System.out.println(list);
}
2 購物車-顯示列表-業務層
2.1 規劃異常
說明:無異常。
2.2 接口與抽象方法
????????在ICartService接口中添加findVOByUid()抽象方法。
/*** 查詢某用戶的購物車數據* @param uid 用戶id* @return 該用戶的購物車數據的列表*/
List<CartVO> getVOByUid(Integer uid);
2.3 實現抽象方法
1.在CartServiceImpl類中重寫業務接口中的抽象方法。
@Override
public List<CartVO> getVOByUid(Integer uid) {return cartMapper.findVOByUid(uid);
}
2.在CartServiceTests測試類中添加getVOByUid()測試方法。
@Test
public void getVOByUid() {List<CartVO> list = cartService.getVOByUid(31);System.out.println("count=" + list.size());for (CartVO item : list) {System.out.println(item);}
}
3 購物車-顯示列表-控制器
3.1 處理異常
說明:無異常。
3.2 設計請求
????????設計用戶提交的請求,并設計響應的方式。
請求路徑:/carts/
請求參數:HttpSession session
請求類型:GET
響應結果:JsonResult<List<CartVO>>
3.3 處理請求
1.在CartController類中編寫處理請求的代碼。
@GetMapping({"", "/"})
public JsonResult<List<CartVO>> getVOByUid(HttpSession session) {// 從Session中獲取uidInteger uid = getUidFromSession(session);// 調用業務對象執行查詢數據List<CartVO> data = cartService.getVOByUid(uid);// 返回成功與數據return new JsonResult<List<CartVO>>(OK, data);
}
2.完成后啟動項目,先登錄再訪問http://localhost:8080/carts請求進行測試。
4 購物車-顯示列表-前端頁面
1.將cart.html頁面的head頭標簽內引入的cart.js文件注釋掉。
<!-- <script src="../js/cart.js" type="text/javascript" charset="utf-8"></script> -->
2.給form標簽添加action="orderConfirm.html"屬性、tbody標簽添加id="cart-list"屬性、結算按鈕的類型改為type="button"值。如果以上屬性值已經添加過無需重復添加。
3.在cart.html頁面body標簽內的script標簽中編寫展示購物車列表的代碼。
$(document).ready(function() {showCartList();
});function showCartList() {$("#cart-list").empty();$.ajax({url: "/carts",type: "GET",dataType: "JSON",success: function(json) {let list = json.data;for (let i = 0; i < list.length; i++) {let tr = '<tr>'+ '<td>'+ '<input name="cids" value="#{cid}" type="checkbox" class="ckitem" />'+ '</td>'+ '<td><img src="..#{image}collect.png" class="img-responsive" /></td>'+ '<td>#{title}#{msg}</td>'+ '<td>¥<span id="price-#{cid}">#{realPrice}</span></td>'+ '<td>'+ '<input type="button" value="-" class="num-btn" onclick="reduceNum(1)" />'+ '<input id="num-#{cid}" type="text" size="2" readonly="readonly" class="num-text" value="#{num}">'+ '<input class="num-btn" type="button" value="+" onclick="addNum(#{cid})" />'+ '</td>'+ '<td>¥<span id="total-price-#{cid}">#{totalPrice}</span></td>'+ '<td>'+ '<input type="button" onclick="delCartItem(this)" class="cart-del btn btn-default btn-xs" value="刪除" />'+ '</td>'+ '</tr>';tr = tr.replace(/#{cid}/g, list[i].cid);tr = tr.replace(/#{title}/g, list[i].title);tr = tr.replace(/#{image}/g, list[i].image);tr = tr.replace(/#{realPrice}/g, list[i].realPrice);tr = tr.replace(/#{num}/g, list[i].num);tr = tr.replace(/#{totalPrice}/g, list[i].realPrice * list[i].num);if (list[i].realPrice < list[i].price) {tr = tr.replace(/#{msg}/g, "比加入時降價" + (list[i].price - list[i].realPrice) + "元");} else {tr = tr.replace(/#{msg}/g, "");}$("#cart-list").append(tr);}}});
}
4.完成后啟動項目,先登錄再訪問http://localhost:8080/web/cart.html頁面進行測試。
增加商品數量
1 購物車-增加商品數量-持久層
1.1 規劃需要執行的SQL語句
1.首先進行查詢需要操作的購物車數據信息。
SELECT * FROM t_cart WHERE cid=?
2.然后計算出新的商品數量值,如果滿足更新條件則執行更新操作。此SQL語句無需重復開發。
UPDATE t_cart SET num=?, modified_user=?, modified_time=? WHERE cid=?
1.2 接口與抽象方法
在CartMapper接口中添加抽象方法。
/*** 根據購物車數據id查詢購物車數據詳情* @param cid 購物車數據id* @return 匹配的購物車數據詳情,如果沒有匹配的數據則返回null*/
Cart findByCid(Integer cid);
1.3 配置SQL映射
1.在CartMapper文件中添加findByCid(Integer cid)方法的映射。
<!-- 根據購物車數據id查詢購物車數據詳情:Cart findByCid(Integer cid) -->
<select id="findByCid" resultMap="CartEntityMap">SELECT*FROMt_cartWHEREcid = #{cid}
</select>
2.在CartMapperTests測試類中添加findByCid()測試方法。
@Test
public void findByCid() {Integer cid = 6;Cart result = cartMapper.findByCid(cid);System.out.println(result);
}
2 購物車-增加商品數量-業務層
2.1 規劃異常
1.如果嘗試訪問的購物車數據不存在,則拋出CartNotFoundException異常。創建com.cy.store.service.ex.CartNotFoundException類。
/** 購物車數據不存在的異常 */
public class CartNotFoundException extends ServiceException {// Override Methods...
}
2.如果嘗試訪問的數據并不是當前登錄用戶的數據,則拋出AccessDeniedException異常。此異常類無需再次創建。
3.最終執行更新操作時,可能會拋出UpdateException異常。此異常類無需再次創建。
2.2 接口與抽象方法
在業務層ICartService接口中添加addNum()抽象方法。
/*** 將購物車中某商品的數量加1* @param cid 購物車數量的id* @param uid 當前登錄的用戶的id* @param username 當前登錄的用戶名* @return 增加成功后新的數量*/
Integer addNum(Integer cid, Integer uid, String username);
2.3 實現抽象方法
1.在CartServiceImpl類中,實現接口中的抽象方法并規劃業務邏輯。
public Integer addNum(Integer cid, Integer uid, String username) {// 調用findByCid(cid)根據參數cid查詢購物車數據// 判斷查詢結果是否為null// 是:拋出CartNotFoundException// 判斷查詢結果中的uid與參數uid是否不一致// 是:拋出AccessDeniedException// 可選:檢查商品的數量是否大于多少(適用于增加數量)或小于多少(適用于減少數量)// 根據查詢結果中的原數量增加1得到新的數量num// 創建當前時間對象,作為modifiedTime// 調用updateNumByCid(cid, num, modifiedUser, modifiedTime)執行修改數量
}
2.實現addNum()方法中的業務邏輯代碼。
@Override
public Integer addNum(Integer cid, Integer uid, String username) {// 調用findByCid(cid)根據參數cid查詢購物車數據Cart result = cartMapper.findByCid(cid);// 判斷查詢結果是否為nullif (result == null) {// 是:拋出CartNotFoundExceptionthrow new CartNotFoundException("嘗試訪問的購物車數據不存在");}// 判斷查詢結果中的uid與參數uid是否不一致if (!result.getUid().equals(uid)) {// 是:拋出AccessDeniedExceptionthrow new AccessDeniedException("非法訪問");}// 可選:檢查商品的數量是否大于多少(適用于增加數量)或小于多少(適用于減少數量)// 根據查詢結果中的原數量增加1得到新的數量numInteger num = result.getNum() + 1;// 創建當前時間對象,作為modifiedTimeDate now = new Date();// 調用updateNumByCid(cid, num, modifiedUser, modifiedTime)執行修改數量Integer rows = cartMapper.updateNumByCid(cid, num, username, now);if (rows != 1) {throw new InsertException("修改商品數量時出現未知錯誤,請聯系系統管理員");}// 返回新的數量return num;
}
3.在CartServiceTests測試類中添加addNum()測試方法。
@Test
public void addNum() {try {Integer cid = 6;Integer uid = 31;String username = "管理員";Integer num = cartService.addNum(cid, uid, username);System.out.println("OK. New num=" + num);} catch (ServiceException e) {System.out.println(e.getClass().getSimpleName());System.out.println(e.getMessage());}
}
3 購物車-增加商品數量-控制器
3.1 處理異常
在BaseController類中添加CartNotFoundException異常類的統一管理。
// ...
else if (e instanceof CartNotFoundException) {result.setState(4007);
}
// ...
3.2 設計請求
設計用戶提交的請求,并設計響應的方式。
請求路徑:/carts/{cid}/num/add
請求參數:@PathVariable("cid") Integer cid, HttpSession session
請求類型:POST
響應結果:JsonResult<Integer>
3.3 處理請求
1.在CartController類中添加處理請求的addNum()方法。
@RequestMapping("{cid}/num/add")
public JsonResult<Integer> addNum(@PathVariable("cid") Integer cid, HttpSession session) {// 從Session中獲取uid和usernameInteger uid = getUidFromSession(session);String username = getUsernameFromSession(session);// 調用業務對象執行增加數量Integer data = cartService.addNum(cid, uid, username);// 返回成功return new JsonResult<Integer>(OK, data);
}
2.完成后啟動項目,先登錄再訪問http://localhost:8080/carts/6/num/add頁面進行測試。
4 購物車-增加商品數量-前端頁面
1.首先確定在showCartList()函數中動態拼接的增加購物車按鈕是綁定了addNum()事件,如果已經添加無需重復添加。
<input class="num-btn" type="button" value="+" onclick="addNum(#{cid})" />
2.在script標簽中定義addNum()函數并編寫增加購物車數量的邏輯代碼。
function addNum(cid) {$.ajax({url: "/carts/" + cid + "/num/add",type: "POST",dataType: "JSON",success: function(json) {if (json.state == 200) {// showCartList();$("#num-" + cid).val(json.data);let price = $("#price-" + cid).html();let totalPrice = price * json.data;$("#total-price-" + cid).html(totalPrice);} else {alert("增加商品數量失敗!" + json.message);}},error: function(xhr) {alert("您的登錄信息已經過期,請重新登錄!HTTP響應碼:" + xhr.status);location.href = "login.html";}});
}
3.完成后啟動項目,先登錄再訪問http://localhost:8080/web/cart.html頁面點擊“+”按鈕進行測試。
顯示勾選的購物車數據
1 顯示確認訂單頁-顯示勾選的購物車數據-持久層
1.1 規劃需要執行的SQL語句
????????在“確認訂單頁”顯示的商品信息,應來自前序頁面(購物車列表)中勾選的數據,所以顯示的信息其實是購物車中的數據。到底需要顯示哪些取決于用戶的勾選操作,當用戶勾選了若干條購物車數據后,這些數據的id應傳遞到當前“確認訂單頁”中,該頁面根據這些id獲取需要顯示的數據列表。
????????所以在持久層需要完成“根據若干個不確定的id值,查詢購物車數據表,顯示購物車中的數據信息”。則需要執行的SQL語句大致是。
SELECTcid,uid,pid,t_cart.price,t_cart.num,t_product.title,t_product.price AS realPrice,t_product.image
FROMt_cartLEFT JOIN t_product ON t_cart.pid = t_product.id
WHEREcid IN (?, ?, ?)
ORDER BYt_cart.created_time DESC
1.2 接口與抽象方法
????????在CartMapper接口中添加findVOByCids(Integer[] cids)方法。
/*** 根據若干個購物車數據id查詢詳情的列表* @param cids 若干個購物車數據id* @return 匹配的購物車數據詳情的列表*/
List<CartVO> findVOByCids(Integer[] cids);
1.3 配置SQL映射
1.在CartMapper.xml文件中添加SQL語句的映射配置。
<!-- 根據若干個購物車數據id查詢詳情的列表:List<CartVO> findVOByCids(Integer[] cids) -->
<select id="findVOByCids" resultType="com.cy.store.vo.CartVO">SELECTcid,uid,pid,t_cart.price,t_cart.num,t_product.title,t_product.price AS realPrice,t_product.imageFROMt_cartLEFT JOIN t_product ON t_cart.pid = t_product.idWHEREcid IN (<foreach collection="array" item="cid" separator=",">#{cid}</foreach>)ORDER BYt_cart.created_time DESC
</select>
2.在CartMapperTests測試類中添加findVOByCids()測試方法。
@Test
public void findVOByCids() {Integer[] cids = {1, 2, 6, 7, 8, 9, 10};List<CartVO> list = cartMapper.findVOByCids(cids);System.out.println("count=" + list.size());for (CartVO item : list) {System.out.println(item);}
}
2 顯示確認訂單頁-顯示勾選的購物車數據-業務層
2.1 規劃異常
說明:無異常。
2.2 接口與抽象方法
在ICartService接口中添加getVOByCids()抽象方法。
/*** 根據若干個購物車數據id查詢詳情的列表* @param uid 當前登錄的用戶的id* @param cids 若干個購物車數據id* @return 匹配的購物車數據詳情的列表*/
List<CartVO> getVOByCids(Integer uid, Integer[] cids);
2.3 實現抽象方法
1.在CartServiceImpl類中重寫業務接口中的抽象方法。
@Override
public List<CartVO> getVOByCids(Integer uid, Integer[] cids) {List<CartVO> list = cartMapper.findVOByCids(cids);/**for (CartVO cart : list) {if (!cart.getUid().equals(uid)) {list.remove(cart);}}*/Iterator<CartVO> it = list.iterator();while (it.hasNext()) {CartVO cart = it.next();if (!cart.getUid().equals(uid)) {it.remove();}}return list;
}
2.在CartServiceTests測試類中添加getVOByCids()測試方法。
@Test
public void getVOByCids() {Integer[] cids = {1, 2, 6, 7, 8, 9, 10};Integer uid = 31;List<CartVO> list = cartService.getVOByCids(uid, cids);System.out.println("count=" + list.size());for (CartVO item : list) {System.out.println(item);}
}
3 顯示確認訂單頁-顯示勾選的購物車數據-控制器
3.1 處理異常
說明:無異常。
3.2 設計請求
????????設計用戶提交的請求,并設計響應的方式。
請求路徑:/carts/list
請求參數:Integer[] cids, HttpSession session
請求類型:GET
響應結果:JsonResult<List<CartVO>>
3.3 處理請求
1.在CartController類中添加處理請求的getVOByCids()方法。
@GetMapping("list")
public JsonResult<List<CartVO>> getVOByCids(Integer[] cids, HttpSession session) {// 從Session中獲取uidInteger uid = getUidFromSession(session);// 調用業務對象執行查詢數據List<CartVO> data = cartService.getVOByCids(uid, cids);// 返回成功與數據return new JsonResult<>(OK, data);
}
2.完成后啟動項目,先登錄再訪問http://localhost:8080/carts/list?cids=7&cids=8&cids=13&cids=14&cids=17地址進行測試。
4 顯示確認訂單頁-前端頁面
4.1 顯示勾選的購物車數據-前端頁面
1.在orderConfirm.html頁面的head標簽里注釋掉引入外部的orderConfirm.js文件。
<!-- <script src="../js/orderConfirm.js" type="text/javascript" charset="utf-8"></script> -->
2.在orderConfirm.html頁面中檢查必要控件的屬性是否添加,如果已添加無需重復添加。
3.在orderConfirm.html頁面中的body標簽內的最后添加srcipt標簽并在標簽內部添加處理購物車“訂單商品信息”列表展示的代碼。
<script type="text/javascript">
$(document).ready(function() {// showAddressList();showCartList();
});function showCartList() {$("#cart-list").empty();$.ajax({url: "/carts/list",data: location.search.substr(1),type: "GET",dataType: "JSON",success: function(json) {let list = json.data;console.log("count=" + list.length);let allCount = 0;let allPrice = 0;for (let i = 0; i < list.length; i++) {console.log(list[i].title);let tr = '<tr>'+ '<td><img src="..#{image}collect.png" class="img-responsive" /></td>'+ '<td><input type="hidden" name="cids" value="#{cid}" />#{title}</td>'+ '<td>¥<span>#{realPrice}</span></td>'+ '<td>#{num}</td>'+ '<td>¥<span>#{totalPrice}</span></td>'+ '</tr>';tr = tr.replace(/#{cid}/g, list[i].cid);tr = tr.replace(/#{image}/g, list[i].image);tr = tr.replace(/#{title}/g, list[i].title);tr = tr.replace(/#{realPrice}/g, list[i].realPrice);tr = tr.replace(/#{num}/g, list[i].num);tr = tr.replace(/#{totalPrice}/g, list[i].realPrice * list[i].num);$("#cart-list").append(tr);allCount += list[i].num;allPrice += list[i].realPrice * list[i].num;}$("#all-count").html(allCount);$("#all-price").html(allPrice);}});
}
</script>
4.完成后啟動項目,先登錄再訪問http://localhost:8080/web/cart.html頁面,勾選商品再點擊“結算”按鈕進行測試。
4.2 顯示選擇收貨地址-前端頁面
1.在orderConfirm.html頁面中的body標簽內的srcipt標簽中添加獲取收貨地址列表方法的定義。
function showAddressList() {$("#address-list").empty();$.ajax({url: "/addresses",type: "GET",dataType: "JSON",success: function(json) {let list = json.data;console.log("count=" + list.length);for (let i = 0; i < list.length; i++) {console.log(list[i].name);let opt = '<option value="#{aid}">#{name} | #{tag} | #{province}#{city}#{area}#{address} | #{phone}</option>';opt = opt.replace(/#{aid}/g, list[i].aid);opt = opt.replace(/#{tag}/g, list[i].tag);opt = opt.replace("#{name}", list[i].name);opt = opt.replace("#{province}", list[i].provinceName);opt = opt.replace("#{city}", list[i].cityName);opt = opt.replace("#{area}", list[i].areaName);opt = opt.replace("#{address}", list[i].address);opt = opt.replace("#{phone}", list[i].phone);$("#address-list").append(opt);}}});
}
2.在orderConfirm.html頁面中的body標簽內的srcipt標簽中添加展示收貨地址列表方法的調用。
<script type="text/javascript">$(document).ready(function() {showAddressList();showCartList();});
</script>
3.完成后啟動項目,先登錄再訪問http://localhost:8080/web/orderConfirm.html頁面進行測試。