Springboot电商系统-生鲜电商-蔬菜商城

基于Spring Boot的生鲜电子商务网站的设计与实现

该项目也用到了Redis缓存(也有商品分类缓存的相关代码)最下方有我的联系方式。

功能
本产品包括用户注册、登陆、商品管理、订单管理、前台商品显示、商品购买以及结账七个主要范围。
用户注册包括:用户注册,建立账号。
用户登录包括:用户登陆后可以查看自己的订单还可以购物。
商品管理包括:管理员对商品的查看、增加、修改、删除四种功能。
订单管理包括:管理员对订单的删除、修改、查询三种功能。
前台商品显示包括:显示商品的图片和详细介绍,及链接地址。
商品购买包括:购物车以及生成订单,购物车包括商品的照片,详细信息介绍。
结账包括:通过生成订单来进行结账

设计图:
架构设计图
E-R图设计:
E-R图内容

1.购物车代码:

/**
 * 描述:     购物车Service实现类
 */
@Service
public class CartServiceImpl implements CartService {
    @Autowired
    ProductMapper productMapper;

    @Autowired
    CartMapper cartMapper;

    /**
     * 获取用户购买的单一商品并计算总价格
     */
    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;
    }

    @Override
    public List<CartVO> add(Integer userId, Integer productId, Integer count) {
        validProduct(productId, count);
        Cart cart = cartMapper.selectCartByUserIdAndProductId(userId, productId);
        if (cart == null) {
            //这个商品之前不在购物车里,需要新增一个记录
            cart = new Cart();
            cart.setProductId(productId);
            cart.setUserId(userId);
            cart.setQuantity(count);
            cart.setSelected(Constant.Cart.CHECKED);
            cartMapper.insertSelective(cart);
        } else {
            //这个商品已经在购物车里了,则数量相加
            count = cart.getQuantity() + count;
            Cart cartNew = new Cart();
            cartNew.setSelected(Constant.Cart.CHECKED);
            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(SaleStatus.NOT_SALE)) {
            throw new MallException(MallExceptionEnum.NOT_SALE);
        }
        //判断商品库存
        if (count > product.getStock()) {
            throw new MallException(MallExceptionEnum.NOT_ENOUGH);
        }
    }

    @Override
    public List<CartVO> update(Integer userId, Integer productId, Integer count) {
        validProduct(productId, count);
        Cart cart = cartMapper.selectCartByUserIdAndProductId(userId, productId);
        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.CHECKED);
            cartMapper.updateByPrimaryKeySelective(cartNew);
        }
        return this.list(userId);
    }

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

    @Override
    public List<CartVO> selectOrNot(Integer userId, Integer productId, Integer selected) {
        Cart cart = cartMapper.selectCartByUserIdAndProductId(userId, productId);
        if (cart == null) {
            //这个商品之前不在购物车里,无法选择/不选中
            throw new MallException(MallExceptionEnum.UPDATE_FAILED);
        } else {
            //这个商品已经在购物车里了,则可以选中/不选中
            cartMapper.selectOrNot(userId, productId, selected);
        }
        return this.list(userId);
    }

    @Override
    public List<CartVO> selectAllOrNot(Integer userId, Integer selected) {
        //改变选中状态
        cartMapper.selectOrNot(userId, null, selected);
        return this.list(userId);
    }
}

2.购物车实体

/**
 * 描述:     CartVO,给前端展示用
 */
public class CartVO {

    private Integer id;

    private Integer productId;

    private Integer userId;

    private Integer quantity;

    private Integer selected;

    private Integer price;

    private Integer totalPrice;

    private String productName;

    private String productImage;

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public Integer getProductId() {
        return productId;
    }

    public void setProductId(Integer productId) {
        this.productId = productId;
    }

    public Integer getUserId() {
        return userId;
    }

    public void setUserId(Integer userId) {
        this.userId = userId;
    }

    public Integer getQuantity() {
        return quantity;
    }

    public void setQuantity(Integer quantity) {
        this.quantity = quantity;
    }

    public Integer getSelected() {
        return selected;
    }

    public void setSelected(Integer selected) {
        this.selected = selected;
    }

    public Integer getPrice() {
        return price;
    }

    public void setPrice(Integer price) {
        this.price = price;
    }

    public Integer getTotalPrice() {
        return totalPrice;
    }

    public void setTotalPrice(Integer totalPrice) {
        this.totalPrice = totalPrice;
    }

    public String getProductName() {
        return productName;
    }

    public void setProductName(String productName) {
        this.productName = productName;
    }

    public String getProductImage() {
        return productImage;
    }

    public void setProductImage(String productImage) {
        this.productImage = productImage;
    }
}

3.商品分类使用Redis代码

    @Override
    @Cacheable(value = "listCategoryForCustomer")// 这里获取缓存的注解
    public List<CategoryVO> listCategoryForCustomer(Integer parentId) {
        ArrayList<CategoryVO> categoryVOList = new ArrayList<>();
        recursivelyFindCategories(categoryVOList, parentId);
        return categoryVOList;
    }

    private void recursivelyFindCategories(List<CategoryVO> categoryVOList, Integer parentId) {
        //递归获取所有子类别,并组合成为一个“目录树”
        List<Category> categoryList = categoryMapper.selectCategoriesByParentId(parentId);
        if (!CollectionUtils.isEmpty(categoryList)) {
            for (int i = 0; i < categoryList.size(); i++) {
                Category category = categoryList.get(i);
                CategoryVO categoryVO = new CategoryVO();
                BeanUtils.copyProperties(category, categoryVO);
                categoryVOList.add(categoryVO);
                recursivelyFindCategories(categoryVO.getChildCategory(), categoryVO.getId());
            }
        }
    }

4.将分类存入Redis缓存中的方法

    @Override
    public PageInfo list(ProductListReq productListReq) {
        //构建Query对象
        ProductListQuery productListQuery = new ProductListQuery();

        //搜索处理
        if (!StringUtils.isEmpty(productListReq.getKeyword())) {
            String keyword = new StringBuilder().append("%").append(productListReq.getKeyword())
                    .append("%").toString();
            productListQuery.setKeyword(keyword);
        }

        //目录处理:如果查某个目录下的商品,不仅是需要查出该目录下的,还要把所有子目录的所有商品都查出来,所以要拿到一个目录id的List
        if (productListReq.getCategoryId() != null) {
            List<CategoryVO> categoryVOList = categoryService
                    .listCategoryForCustomer(productListReq.getCategoryId());
            ArrayList<Integer> categoryIds = new ArrayList<>();
            categoryIds.add(productListReq.getCategoryId());
            getCategoryIds(categoryVOList, categoryIds);
            productListQuery.setCategoryIds(categoryIds);
        }

        //排序处理
        String orderBy = productListReq.getOrderBy();
        if (ProductListOrderBy.PRICE_ASC_DESC.contains(orderBy)) {
            PageHelper
                    .startPage(productListReq.getPageNum(), productListReq.getPageSize(), orderBy);
        } else {
            PageHelper
                    .startPage(productListReq.getPageNum(), productListReq.getPageSize());
        }

        List<Product> productList = productMapper.selectList(productListQuery);
        PageInfo pageInfo = new PageInfo(productList);
        return pageInfo;
    }

数据库设计:
表mall_cart

字段名类型是否可为空注释
idintTrue购物车id
product_idintTrue商品id
user_idintTrue用户id
quantityintTrue商品数量
selectedintTrue是否已勾选:0代表未勾选,1代表已勾选
create_timetimestampTrue创建时间
update_timetimestampTrue更新时间

表mall_category

字段名类型是否可为空注释
idintTrue主键
namevarcharTrue分类目录名称
typeintTrue分类目录级别,例如1代表一级,2代表二级,3代表三级
parent_idintTrue父id,也就是上一级目录的id,如果是一级目录,那么父id为0
order_numintTrue目录展示时的排序
create_timetimestampTrue创建时间
update_timetimestampTrue更新时间

表mall_order:

字段名类型是否可为空注释
idintTrue主键id
order_novarcharTrue订单号(非主键id)
user_idintTrue用户id
total_priceintTrue订单总价格
receiver_namevarcharTrue收货人姓名快照
receiver_mobilevarcharTrue收货人手机号快照
receiver_addressvarcharTrue收货地址快照
order_statusintTrue订单状态: 0用户已取消,10未付款(初始状态),20已付款,30已发货,40交易完成
postageintFalse运费,默认为0
payment_typeintTrue支付类型,1-在线支付
delivery_timetimestampFalse发货时间
pay_timetimestampFalse支付时间
end_timetimestampFalse交易完成时间
create_timetimestampTrue创建时间
update_timetimestampTrue更新时间

表mall_order_item

字段名类型是否可为空注释
idintTrue主键id
order_novarcharTrue归属订单id
product_idintTrue商品id
product_namevarcharTrue商品名称
product_imgvarcharTrue商品图片
unit_priceintTrue单价(下单时的快照)
quantityintTrue商品数量
total_priceintTrue商品总价
create_timetimestampTrue创建时间
update_timetimestampTrue更新时间

表mall_product

字段名类型是否可为空注释
id intTrue商品主键id
namevarcharTrue商品名称
imagevarcharFalse产品图片,相对路径地址
detailvarcharFalse商品详情
category_idintTrue分类id
priceintTrue价格,单位-分
stockintTrue库存数量
statusintTrue商品上架状态:0-下架,1-上架
create_timetimestampTrue创建时间
update_timetimestampTrue更新时间

表mall_user:

字段名类型是否可为空注释
idintTrue用户id
usernamevarcharTrue用户名
passwordvarcharTrue用户密码,MD5加密
personalized_signaturevarcharTrue个性签名
roleintTrue角色,1-普通用户,2-管理员
create_timetimestampTrue创建时间
update_timetimestampTrue更新时间

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

项目需要可以找我私聊。

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值