文章目录
1添加到购物车
1.1 接口说明
参数
post:
productId
selected: true
返回结果:
1.2 将商品的不变的属性存在redis当中
商品存在redis,不是商品的所有属性都存在redis当中,例如商品的价格就随时在变化,如果存在redis中,会造成数据的不准确性,所以对商品的某些不变的属性进行存储。
新建一个新的对象,存不变的属性
1.2.1 新增对象
@Data
public class Cart {
private Integer productId;
private Integer quantity;
private Boolean productSelected;
public Cart() {
}
public Cart(Integer productId, Integer quantity, Boolean productSelected) {
this.productId = productId;
this.quantity = quantity;
this.productSelected = productSelected;
}
}
1.2.2存在redis中
list带来的麻烦就是得遍历每一个对象,然后在更改数量,所以我们用hash存,小key是productID,value是对象
数量的改变:
先从redis中读出来数据,如果有就加一,没有就新增记录
1.3总的代码:
1.3.1添加入参对象
public class CartAddForm {
@NotNull
private Integer productId;
private Boolean selected = true;
}
1.3.2代码:
@PostMapping("/carts")
public ResponseVo<CartVo> add(@Valid @RequestBody CartAddForm cartAddForm,
HttpSession session) {
User user = (User) session.getAttribute(MallConst.CURRENT_USER);
return cartService.add(user.getId(), cartAddForm);
@Override
public ResponseVo<CartVo> add(Integer uid, CartAddForm form) {
Integer quantity = 1;
Product product = productMapper.selectByPrimaryKey(form.getProductId());
//商品是否存在
if (product == null) {
return ResponseVo.error(ResponseEnum.PRODUCT_NOT_EXIST);
}
//商品是否正常在售
if (!product.getStatus().equals(ProductStatusEnum.ON_SALE.getCode())) {
return ResponseVo.error(ResponseEnum.PRODUCT_OFF_SALE_OR_DELETE);
}
//商品库存是否充足
if (product.getStock() <= 0) {
return ResponseVo.error(ResponseEnum.PROODUCT_STOCK_ERROR);
}
//写入到redis1 先从redis中读出来数据,如果有就加一,没有就新增)
//key: cart_1
HashOperations<String, String, String> opsForHash = redisTemplate.opsForHash();
String redisKey = String.format(CART_REDIS_KEY_TEMPLATE, uid);
Cart cart;
String value = opsForHash.get(redisKey, String.valueOf(product.getId()));
if (StringUtils.isEmpty(value)) {
//没有该商品, 新增
cart = new Cart(product.getId(), quantity, form.getSelected());
}else {
//已经有了,数量+1
cart = gson.fromJson(value, Cart.class);
cart.setQuantity(cart.getQuantity() + quantity);
}
opsForHash.put(redisKey,
String.valueOf(product.getId()),
gson.toJson(cart));
return list(uid);
}
2 查询购物车
2.1 分析
计算总价:
//计算总价(只计算选中的)
if (cart.getProductSelected()) {
cartTotalPrice = cartTotalPrice.add(cartProductVo.getProductTotalPrice());
}
2.2总代码:
@GetMapping("/carts")
public ResponseVo<CartVo> list(HttpSession session) {
User user = (User) session.getAttribute(MallConst.CURRENT_USER);
return cartService.list(user.getId());
}
public ResponseVo<CartVo> list(Integer uid) {
HashOperations<String, String, String> opsForHash = redisTemplate.opsForHash();
String redisKey = String.format(CART_REDIS_KEY_TEMPLATE, uid);
Map<String, String> entries = opsForHash.entries(redisKey);
boolean selectAll = true;
Integer cartTotalQuantity = 0;
BigDecimal cartTotalPrice = BigDecimal.ZERO;
CartVo cartVo = new CartVo();
List<CartProductVo> cartProductVoList = new ArrayList<>();
for (Map.Entry<String, String> entry : entries.entrySet()) {
Integer productId = Integer.valueOf(entry.getKey());
Cart cart = gson.fromJson(entry.getValue(), Cart.class);
//TODO 需要优化,使用mysql里的in
Product product = productMapper.selectByPrimaryKey(productId);
if (product != null) {
CartProductVo cartProductVo = new CartProductVo(productId,
cart.getQuantity(),
product.getName(),
product.getSubtitle(),
product.getMainImage(),
product.getPrice(),
product.getStatus(),
product.getPrice().multiply(BigDecimal.valueOf(cart.getQuantity())),
product.getStock(),
cart.getProductSelected()
);
cartProductVoList.add(cartProductVo);
if (!cart.getProductSelected()) {
selectAll = false;
}
//计算总价(只计算选中的)
if (cart.getProductSelected()) {
cartTotalPrice = cartTotalPrice.add(cartProductVo.getProductTotalPrice());
}
}
cartTotalQuantity += cart.getQuantity();
}
//有一个没有选中,就不叫全选
cartVo.setSelectedAll(selectAll);
cartVo.setCartTotalQuantity(cartTotalQuantity);
cartVo.setCartTotalPrice(cartTotalPrice);
cartVo.setCartProductVoList(cartProductVoList);
return ResponseVo.success(cartVo);
}
3 更新购物车
3.1 接口说明:
** PUT /carts/{
productId}
quantity //非必填
selected: true //非必填
{
"status": 0,
"data": {
"cartProductVoList": [
{
"productId": 1,
"quantity": 12,
"productName": "iphone7",
"productSubtitle": "双十一促销",
"productMainImage": "mainimage.jpg",
"productPrice": 7199.22,
"productStatus": 1,
"productTotalPrice": 86390.64,
"productStock": 86,
"productSelected": true
},
{
"productId": 2,
"quantity": 1,
"productName": "oppo R8",
"productSubtitle": "oppo促销进行中",
"productMainImage": "mainimage.jpg",
"productPrice": 2999.11,
"productStatus": 1,
"productTotalPrice": 2999.11,
"productStock": 86,
"productSelected": true,
}
],
"selectedAll": true,
"cartTotalPrice": 89389.75,
"cartTotalQuantity": 13
3.2 代码
3.2.1 添加入参对象
@Data
public class CartUpdateForm {
private Integer quantity;
private Boolean selected;
}
3.2.1 代码:
@PutMapping("/carts/{productId}")
public ResponseVo<CartVo> update(@PathVariable Integer productId,
@Valid @RequestBody CartUpdateForm form,
HttpSession session) {
User user = (User) session.getAttribute(MallConst.CURRENT_USER);
return cartService.update(user.getId(), productId, form);
}
主要修改【数量】和【选择不选择】两个
public ResponseVo<CartVo> update(Integer uid, Integer productId, CartUpdateForm form) {
HashOperations<String, String, String> opsForHash = redisTemplate.opsForHash();
String redisKey = String.format(CART_REDIS_KEY_TEMPLATE, uid);
String value = opsForHash.get(redisKey, String.valueOf(productId));
if (StringUtils.isEmpty(value)) {
//没有该商品, 报错
return ResponseVo.error(ResponseEnum.CART_PRODUCT_NOT_EXIST);
}
//已经有了,修改内容
Cart cart = gson.fromJson(value, Cart.class);
if (form.getQuantity() != null
&& form.getQuantity() >= 0) {
cart.setQuantity(form.getQuantity());
}
if (form.getSelected() != null) {
cart.setProductSelected(form.getSelected());
}
opsForHash.put(redisKey, String.valueOf(productId), gson.toJson(cart));
return list(uid);
}
4删除购物车
4.1 接口说明
** DELETE /carts/{
productId}
productId
{
"status": 0,
"data": {
"cartProductVoList": [
{
"productId": 2,
"quantity": 1,
"productName": "oppo R8",
"productSubtitle": "oppo促销进行中",
"productMainImage": "mainimage.jpg",
"productPrice": 2999.11,
"productStatus": 1,
"productTotalPrice": 2999.11,
"productStock": 86,
"productSelected": true
}
],
"selectedAll": true,
"cartTotalPrice": 2999.11,
"cartTotalQuantity": 1
}
}
4.2代码
@DeleteMapping("/carts/{productId}")
public ResponseVo<CartVo> delete(@PathVariable Integer productId,
HttpSession session) {
User user = (User) session.getAttribute(MallConst.CURRENT_USER);
return cartService.delete(user.getId(), productId);
}
@Override
public ResponseVo<CartVo> delete(Integer uid, Integer productId) {
HashOperations<String, String, String> opsForHash = redisTemplate.opsForHash();
String redisKey = String.format(CART_REDIS_KEY_TEMPLATE, uid);
String value = opsForHash.get(redisKey, String.valueOf(productId));
if (StringUtils.isEmpty(value)) {
//没有该商品, 报错
return ResponseVo.error(ResponseEnum.CART_PRODUCT_NOT_EXIST);
}
opsForHash.delete(redisKey, String.valueOf(productId));
return list(uid);
}
5全选=
5.1 接口说明
** PUT /carts/selectAll
返回
同接口 获取购物车列表
5.2代码
@Override
public ResponseVo<CartVo> selectAll(Integer uid) {
HashOperations<String, String, String> opsForHash = redisTemplate.opsForHash();
String redisKey = String.format(CART_REDIS_KEY_TEMPLATE, uid);
for (Cart cart : listForCart(uid)) {
cart.setProductSelected(true);
opsForHash.put(redisKey,
String.valueOf(cart.getProductId()),
gson.toJson(cart));
}
return list(uid);
}
private List<Cart> listForCart(Integer uid) {
HashOperations<String, String, String> opsForHash = redisTemplate.opsForHash();
String redisKey = String.format(CART_REDIS_KEY_TEMPLATE, uid);
Map<String, String> entries = opsForHash.entries(redisKey);
List<Cart> cartList = new ArrayList<>();
for (Map.Entry<String, String> entry : entries.entrySet()) {
cartList.add(gson.fromJson(entry.getValue(), Cart.class));
}
return cartList;
}
6全不选=
6.1 接口说明
** PUT /carts/unSelectAll
返回
同接口 获取购物车列表
6.2代码
@Override
public ResponseVo<CartVo> unSelectAll(Integer uid) {
for (Cart cart : listForCart(uid)) {
cart.setProductSelected(false);
opsForHash.put(redisKey,
String.valueOf(cart.getProductId()),
gson.toJson(cart));
}
return list(uid);
}
private List<Cart> listForCart(Integer uid) {
HashOperations<String, String, String> opsForHash = redisTemplate.opsForHash();
String redisKey = String.format(CART_REDIS_KEY_TEMPLATE, uid);
Map<String, String> entries = opsForHash.entries(redisKey);
List<Cart> cartList = new ArrayList<>();
for (Map.Entry<String, String> entry : entries.entrySet()) {
cartList.add(gson.fromJson(entry.getValue(), Cart.class));
}
return cartList;
}
7#### 7.获取购物中所有商品数量总和
** GET /carts/products/sum
无参数,需要登录状态
response:
{
“status”: 0,
“data”: 2
}
@Override
public ResponseVo<Integer> sum(Integer uid) {
Integer sum = listForCart(uid).stream()
.map(Cart::getQuantity)
.reduce(0, Integer::sum);
return ResponseVo.success(sum);
}