Java-springboot生鲜电商项目(五)购物车模块

本文详细介绍了一个基于Java SpringBoot的生鲜电商平台购物车模块的开发过程,包括接口设计、业务流程、异常处理及常见错误避免。从购物车列表、商品添加、数量更新到商品删除,全面解析了购物车功能的实现细节。

购物车功能

  1. 添加商品到购物车
  2. 全选和全不选
  3. 增加数量

涉及到的接口,购物车模块(都是前台的)

  1. 购物车列表
  2. 添加商品到购物车
  3. 更新购物车某个商品的数量
  4. 删除购物车的某个商品
  5. 选中/不选中购物车的某个商品
  6. 全选/全不选购物车的某个商品

业务流程

  1. 判断商品是否存在,提示用户
  2. 商品是否在购物车,添加商品和追加商品

总结

  1. mybatis返回非标准对象,后期计算单样商品的总价
  2. 添加商品到购物车时,根据是否已经存在该商品,有不同逻辑

常见错误

  1. 不做越权判断

(一)购物车列表

dao

List<CartVO> selectList(@Param("userId") Integer userId);

mapper

  <select id="selectList" resultType="com.hyb.mall.model.vo.CartVO" parameterType="java.lang.Integer">
    select
    c.id as id,
    p.id as productId,
    c.user_id as userId,
    c.quantity as quantity,
    c.selected as selected,
    p.price as price,
    p.name as productName,
    p.image as productImage
    from imooc_mall_cart c
    left join imooc_mall_product p on p.id = c.product_id
    where c.user_id =#{userId}
    and p.status = 1
  </select>

service

    @Override
    public List<CartVO> list(Integer userId) {
        List<CartVO> cartVOS = cartMapper.selectList(userId);
        //计算总价
        for (int i = 0; i < cartVOS.size(); i++) {
            CartVO cartVO = cartVOS.get(i);
            cartVO.setTotalPrice(cartVO.getPrice() * cartVO.getQuantity());
        }
        return cartVOS;
    }

(二)添加商品到购物车

对用户的过滤器开发:因为购物车的功能是用户的行为操作,所以在添加商品到购物车的时候,先判断是否是用户,可以借鉴管理员过滤器的开发

filter包中创建UserFilter

package com.hyb.mall.filter;
import com.hyb.mall.common.Constant;
import com.hyb.mall.model.pojo.User;
import com.hyb.mall.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;

import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpServletResponseWrapper;
import javax.servlet.http.HttpSession;
import java.io.IOException;
import java.io.PrintWriter;

/**
 * 描述:用户校验过滤器
 * 登录后做更深层的校验,可以拿到用户信息
 */
public class UserFilter implements Filter {
    //登录后,能将用户信息保存下来
    public static User currentUser;

    @Autowired
    private UserService userService;
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {}

    @Override
    public void doFilter(ServletRequest servletRequest, 
                         ServletResponse servletResponse, 
                         FilterChain filterChain) throws IOException, ServletException {
        HttpServletRequest request = (HttpServletRequest) servletRequest;
        HttpSession session = request.getSession();
        //1.获取session中的用户
        currentUser = (User) session.getAttribute(Constant.HYB_MALL_USER);
        //2.判断当前用户是否为空,为空则需要登录
        if (currentUser == null) {
            PrintWriter out = new HttpServletResponseWrapper((HttpServletResponse)servletResponse).getWriter();
            out.write("{\n" +
                    "    \"status\": 10007,\n" +
                    "    \"msg\": \"NEED_LOGIN\",\n" +
                    "    \"data\": null\n" +
                    "}");
            out.flush();
            out.close();
            return;
        }
        //3.通过用户校验
        filterChain.doFilter(servletRequest,servletResponse);
    }

    @Override
    public void destroy() {}
}

对过滤器进行config配置

package com.hyb.mall.config;

import com.hyb.mall.filter.AdminFilter;
import com.hyb.mall.filter.UserFilter;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * 描述:用户过滤器的配置
 */
@Configuration
public class UserFilterConfig {
    @Bean
    public UserFilter userFilter(){
        return new UserFilter();
    }

    //将整个filter放到整个链路中去
    @Bean(name = "userFilterConf") //设置的名字不能和类名一样不然会有冲突
    public FilterRegistrationBean adminFilterConfig(){
        FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean();
        filterRegistrationBean.setFilter(userFilter());
        //设置拦截的URL
        filterRegistrationBean.addUrlPatterns("/cart/*");
        filterRegistrationBean.addUrlPatterns("/order/*");
        //给过滤器配置设置名字,以便于区分不同的名字
        filterRegistrationBean.setName("UserFilterConfig");
        return filterRegistrationBean;
    }
}

coding到这里,我发现有个小小的笔误,我在controller中@PostMapping("")注解中,映射的地址开头有些有“/”有些没有,然后我进行统一处理,全加上了,重新测试接口,到没有发现出bug。

在MallExceptionEnum中加入异常处理

NOT_SALE(10016,"商品状态不可售"),
NOT_ENOUGH(10016,"商品库存不足"),

在common常量类中设置商品上下架以及购物车选中状态

    /**
     * 增加商品的上下架状态
     */
    public interface SaleStatus{
        int NOT_SALE = 0;//商品的下架状态
        int SALE = 1;//商品的上架状态
    }
        /**
     * 购物车是否选中状态
     */
    public interface Cart{
        int UN_CHCKED = 0;//购物车未选中
        int CHCKED = 1;//购物车选中
    }

cartDAO

 Cart selectCartByUserIdAndProduct(@Param("userId") Integer userId,@Param("productId") Integer productId);

cart mapper

  <select id="selectCartByUserIdAndProduct" resultMap="BaseResultMap" parameterType="map">
    select
    <include refid="Base_Column_List"/>
    from imooc_mall_cart
    where user_id = #{userId}
    and product_id = #{productId}
  </select>

service

package com.hyb.mall.service.impl;

import com.hyb.mall.common.Constant;
import com.hyb.mall.exception.MallException;
import com.hyb.mall.exception.MallExceptionEnum;
import com.hyb.mall.model.dao.CartMapper;
import com.hyb.mall.model.dao.ProductMapper;
import com.hyb.mall.model.pojo.Cart;
import com.hyb.mall.model.pojo.Product;
import com.hyb.mall.model.vo.CartVO;
import com.hyb.mall.service.CartSrvice;
import io.swagger.models.auth.In;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;


/**
 * 描述:购物车service实现类
 */
@Service
public class CartSrviceImpl implements CartSrvice {

    @Autowired
    ProductMapper productMapper;

    @Autowired
    CartMapper cartMapper;
    @Override
    public List<CartVO> add(Integer userId, Integer productId, Integer count){
        validProduct(productId,count);
        Cart cart = cartMapper.selectCartByUserIdAndProduct(userId, productId);
        //判断查出来的cart是不是为空
        if (cart == null) {
            //这个商品之前不再购物车,需要新增一个记录
            cart = new Cart();
            cart.setProductId(productId);
            cart.setUserId(userId);
            cart.setQuantity(count);
            cart.setSelected(Constant.Cart.CHCKED);
            cartMapper.insertSelective(cart);
        }else {
            //这个商品已经在购物车里了,则数量相加
            count = cart.getQuantity() +count;
            Cart cartNew = new Cart();
            cartNew.setQuantity(count);
            cartNew.setId(cart.getId());
            cartNew.setProductId(cart.getProductId());
            cartNew.setUserId(cart.getUserId());
            cartNew.setSelected(Constant.Cart.CHCKED);
            cartMapper.updateByPrimaryKeySelective(cartNew);
        }
        return this.list(userId);
    }


    //验证添加是不是合法的
    private void validProduct(Integer productId, Integer count) {
        Product product = productMapper.selectByPrimaryKey(productId);
        //判断商品是否存在,商品是否上架
        if (product == null  || product.getStatus().equals(Constant.SaleStatus.NOT_SALE)) {
            throw new MallException(MallExceptionEnum.NOT_SALE);
        }
        //判断商品库存
        if (count > product.getStock()){
            throw new MallException(MallExceptionEnum.NOT_ENOUGH);
        }
    }

}

controller

package com.hyb.mall.controller;

import com.hyb.mall.common.ApiRestResponse;
import com.hyb.mall.filter.UserFilter;
import com.hyb.mall.service.CartSrvice;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

/**
 * 描述:购物车controller
 */
@RestController
@RequestMapping("/cart")
public class CartController {
    @Autowired
    CartSrvice cartSrvice;

    @ApiOperation("添加商品到购物车")
    @PostMapping("/add")
    public ApiRestResponse add(@RequestParam Integer productId,
                               @RequestParam Integer count){
                List<CartVO> cartVOList = cartSrvice.add(UserFilter.currentUser.getId(), productId, count);
        return ApiRestResponse.success(cartVOList);
    }
}

使用postman添加商品到购物车在查询商品列表

在这里插入图片描述
在这里插入图片描述

(三)更新购物车接口

service

    //更新购物车
    @Override
    public List<CartVO> update(Integer userId, Integer productId, Integer count) {
        validProduct(productId, count);
        Cart cart = cartMapper.selectCartByUserIdAndProduct(userId, productId);
        //判断查出来的cart是不是为空
        if (cart == null) {
            //这个商品之前不再购物车,无法更新
            throw new MallException(MallExceptionEnum.UPDATE_FAILED);
        } else {
            //这个商品已经在购物车里了,则更新数量
            Cart cartNew = new Cart();
            cartNew.setQuantity(count);
            cartNew.setId(cart.getId());
            cartNew.setProductId(cart.getProductId());
            cartNew.setUserId(cart.getUserId());
            cartNew.setSelected(Constant.Cart.CHCKED);
            cartMapper.updateByPrimaryKeySelective(cartNew);
        }
        return this.list(userId);
    }
    @ApiOperation("更新购物车")
    @PostMapping("/update")
    public ApiRestResponse update(@RequestParam Integer productId,
                               @RequestParam Integer count) {
        List<CartVO> cartVOList = cartSrvice.update(UserFilter.currentUser.getId(), productId, count);
        return ApiRestResponse.success(cartVOList);
    }

(四)删除购物车接口

service

    //删除购物车商品
    @Override
    public List<CartVO> delete(Integer userId, Integer productId) {
        Cart cart = cartMapper.selectCartByUserIdAndProduct(userId, productId);
        //判断查出来的cart是不是为空
        if (cart == null) {
            //这个商品之前不再购物车,无法删除
            throw new MallException(MallExceptionEnum.DELETE_FAILE);
        } else {
            //这个商品已经在购物车里了,则可以删除
            cartMapper.deleteByPrimaryKey(cart.getId());
        }
        return this.list(userId);
    }

controller

    @ApiOperation("删除购物车")
    @PostMapping("/delete")
    public ApiRestResponse delete(@RequestParam Integer productId) {
        //不能传入userID和cartID,防止黑客攻击
        List<CartVO> cartVOList = cartSrvice.delete(UserFilter.currentUser.getId(), productId);
        return ApiRestResponse.success(cartVOList);
    }

postman测试

在这里插入图片描述
在这里插入图片描述

(五)单选和反选购物车商品

dao

    Integer selectOrNot(@Param("userId") Integer userId,
                        @Param("productId") Integer productId,
                        @Param("selected") Integer selected);

mapper

  <update id="selectOrNot" parameterType="map">
    update imooc_mall_cart
    set selected = #{selected}
    where user_id = #{userId}
    <if test="productId !=null">
      and product_id = #{productId}
    </if>
  </update>

service

    //单选和反选购物车的商品
    @Override
    public List<CartVO> selectOrNot(Integer userId, Integer productId, Integer selected){
        //将购物车查询出来
        Cart cart = cartMapper.selectCartByUserIdAndProduct(userId, productId);
        //判断查出来的cart是不是为空
        if (cart == null) {
            //这个商品之前不再购物车,无法更新
            throw new MallException(MallExceptionEnum.UPDATE_FAILED);
        } else {
            //这个商品已经在购物车里了,则可以删除
            cartMapper.selectOrNot(userId,productId,selected);
        }
        return this.list(userId);
    }

controller

    @ApiOperation("单选和反选购物车的某商品")
    @PostMapping("/select")
    public ApiRestResponse select(@RequestParam Integer productId,
                                  @RequestParam Integer selected) {
        //不能传入userID和cartID,防止黑客攻击
        List<CartVO> cartVOList = cartSrvice.selectOrNot(UserFilter.currentUser.getId(), productId,selected);
        return ApiRestResponse.success(cartVOList);
    }

(六)全选和全不选购物车商品

service:不用谢productId,这样就能将所有的购物车商品选中,将全部查询出来

    //全选和全不选购物车商品
    @Override
    public List<CartVO> selectAllOrNot(Integer userId, Integer selected) {
        //改变选中状态
        cartMapper.selectOrNot(userId, null, selected);
        return this.list(userId);
    }

controller

    @ApiOperation("全选和全不选购物车商品")
    @PostMapping("/selectAll")
    public ApiRestResponse selectAll(@RequestParam Integer productId,
                                  @RequestParam Integer selected) {
        //不能传入userID和cartID,防止黑客攻击
        List<CartVO> cartVOList = cartSrvice.selectAllOrNot(UserFilter.currentUser.getId(),selected);
        return ApiRestResponse.success(cartVOList);
    }

postman

在这里插入图片描述

这份资源是一个基于SpringBoot+Vue的生鲜超市管理系统的完整开发源码,包括前端、后端、数据库等部分。该系统主要用于生鲜超市的管理,包括商品管理、库存管理、销售管理等功能。该系统支持管理员、销售员、仓库管理员等多个角色,并可以实现数据报表、数据分析、销售预测等功能。 为了更好地使用本资源,我们提供了详细的部署说明和系统介绍。在部署说明中,我们详细介绍了如何将本资源部署到本地或远程服务器上,并配置相关环境参数。在系统介绍中,我们对生鲜超市管理系统的各项功能、前后端框架和技术栈进行了详细介绍和解释,以帮助开发者更好地理解系统的设计思路和功能实现。 对于想要深入学习和了解源码的开发者,我们还提供了源码解释。通过逐行分析源码,我们对系统的技术实现、API设计、业务逻辑等进行深入解读和分析,帮助开发者更好地理解源码和在其基础上进行二次开发,并提供更多开发思路和技巧。 总之,本资源适合对SpringBoot、Vue、生鲜超市管理系统开发有一定基础的开发者学习和参考。生鲜超市管理系统的设计思路、技术实现和业务逻辑等方面都具有高参考价值,为开发者提供了实践和实现超市管理的宝贵经验和思路。该系统可用于优化超市管理流程、提高管理效率,也可拓展至其他类似的零售行业中。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值