基于springboot的外星人电脑商城项目(六)购物车

基于springboot的外星人电脑商城项目(六)

  • 外星人商城项目介绍
    • 项目背景
    • 项目功能
    • 项目技术
    • 项目模块
    • 项目要求
  • 外星人商城项目开发流程
    • 第一节 基础构建
    • 第二节 用户注册
    • 第三节 用户登录
    • 第四节 用户管理
    • 第五节 热销商品
    • 第六节 购物车
      • 1. 购物车 - 数据库
      • 2. 购物车 - 实体类
      • 3. 购物车 - 持久层
      • 4. 购物车 - 业务层
      • 5. 购物车 - 控制层
      • 6. 购物车 - 前端页面
    • 第七节 订单
    • 第八节 商品秒杀
  • 外星人商城项目总结

外星人商城项目介绍

项目背景

外星人公司(狗头)委托我开发一个一个专门的外星人商城(模仿京东、天猫),出售外星人电子产品以及周边,实现了以下功能。
本项目已经搭载了服务器,网址给定:
链接: 外星人官方网站.

项目功能

  • 登录
  • 注册
  • 用户管理
  • 热销商品
  • 购物车
  • 订单
  • 商品秒杀

项目技术

  • 项目框架:springboot
  • 数据库框架:mybaits
  • 前端技术:JS、JQuery、Ajax

项目模块

持久层:依据业务要求规划相关的SQL语句,以及进行配置
业务层:核心功能控制、业务操作以及异常处理
控制层:接受请求,处理响应
前端开发:JS、JQuery、Ajax
单元测试:junit

项目要求

  • JDK8
  • maven3.6.1
  • 数据库mysql5.1
  • idea

外星人商城项目开发流程

第一节 基础构建

第二节 用户注册

第三节 用户登录

第四节 用户管理

第五节 热销商品

第六节 购物车

基于springboot的外星人电脑商城项目(六)购物车_第1张图片

基于springboot的外星人电脑商城项目(六)购物车_第2张图片

1. 购物车 - 数据库


#创建数据库
CREATE DATABASE compution;

USE compution;
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;

基于springboot的外星人电脑商城项目(六)购物车_第3张图片

2. 购物车 - 实体类

/** 购物车数据的实体类 */
@Data
public class Cart extends BaseEntity implements Serializable {
    private Integer cid;
    private Integer uid;
    private Integer pid;
    private Long price;
    private Integer num;
}

3. 购物车 - 持久层

规划sql语句

    <!-- 插入购物车数据:Integer insert(Cart cart) -->
    <insert id="insert" useGeneratedKeys="true" keyProperty="cid">
        INSERT INTO compution.t_cart (uid, pid, price, num, created_user, created_time, modified_user, modified_time)
        VALUES (#{uid}, #{pid}, #{price}, #{num}, #{createdUser}, #{createdTime}, #{modifiedUser}, #{modifiedTime})
    </insert>
    <update id="updateNumByCid">
        UPDATE
            compution.t_cart
        SET
            num=#{num},
            modified_user=#{modifiedUser},
            modified_time=#{modifiedTime}
        WHERE
            cid=#{cid}
    </update>
        <select id="findByUidAndPid" resultMap="CartEntityMap">
        SELECT
            *
        FROM
            compution.t_cart
        WHERE
            uid=#{uid} AND pid=#{pid}
    </select>
    <select id="findVOByUid" resultType="com.cy.store.vo.CartVO">
        SELECT
            cid,
            uid,
            pid,
            t_cart.price,
            t_cart.num,
            t_product.title,
            t_product.price AS realPrice,
            t_product.image
        FROM
            compution.t_cart
                LEFT JOIN compution.t_product ON t_cart.pid = t_product.id
        WHERE
            uid = #{uid}
        ORDER BY
            t_cart.created_time DESC
    </select>
    <!-- 根据购物车数据id查询购物车数据详情:Cart findByCid(Integer cid) -->
    <select id="findByCid" resultMap="CartEntityMap">
        SELECT
            *
        FROM
            compution.t_cart
        WHERE
            cid = #{cid}
    </select>

4. 购物车 - 业务层

/** 处理商品数据的业务层接口 */
public interface ICartService {
    /**
     * 将商品添加到购物车
     * @param uid 当前登录用户的id
     * @param pid 商品的id
     * @param amount 增加的数量
     * @param username 当前登录的用户名
     */
    void addToCart(Integer uid, Integer pid, Integer amount, String username);

    /**
     * 查询某用户的购物车数据
     * @param uid 用户id
     * @return 该用户的购物车数据的列表
     */
    List<CartVO> getVOByUid(Integer uid);

    /**
     * 将购物车中某商品的数量加1
     * @param cid 购物车数量的id
     * @param uid 当前登录的用户的id
     * @param username 当前登录的用户名
     * @return 增加成功后新的数量
     */
    Integer addNum(Integer cid, Integer uid, String username);

    /**
     * 根据若干个购物车数据id查询详情的列表
     * @param uid 当前登录的用户的id
     * @param cids 若干个购物车数据id
     * @return 匹配的购物车数据详情的列表
     */
    List<CartVO> getVOByCids(Integer uid, Integer[] cids);
}

Impl

/** 处理购物车数据的业务层实现类 */
@Service
public class CartServiceImpl implements ICartService {
    @Autowired
    private CartMapper cartMapper;
    @Autowired
    private IProductService productService;

    @Override
    public void addToCart(Integer uid, Integer pid, Integer amount, String username) {
        // 根据参数pid和uid查询购物车中的数据
        Cart result = cartMapper.findByUidAndPid(uid, pid);
        Date now = new Date();
        // 判断查询结果是否为null
        if (result == null) {
            // 是:表示该用户并未将该商品添加到购物车
            // 创建Cart对象
            Cart cart = new Cart();
            // 封装数据:uid,pid,amount
            cart.setUid(uid);
            cart.setPid(pid);
            cart.setNum(amount);
            // 调用productService.findById(pid)查询商品数据,得到商品价格
            Product product = productService.findById(pid);
            // 封装数据:price
            cart.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 {
            // 否:表示该用户的购物车中已有该商品
            // 从查询结果中获取购物车数据的id
            Integer cid = result.getCid();
            // 从查询结果中取出原数量,与参数amount相加,得到新的数量
            Integer num = result.getNum() + amount;
            // 执行更新数量
            Integer rows = cartMapper.updateNumByCid(cid, num, username, now);
            if (rows != 1) {
                throw new InsertException("修改商品数量时出现未知错误,请联系系统管理员");
            }
        }
    }

    @Override
    public List<CartVO> getVOByUid(Integer uid) {
        return cartMapper.findVOByUid(uid);
    }

    @Override
    public Integer addNum(Integer cid, Integer uid, String username) {
        // 调用findByCid(cid)根据参数cid查询购物车数据
        Cart result = cartMapper.findByCid(cid);
        // 判断查询结果是否为null
        if (result == null) {
            // 是:抛出CartNotFoundException
            throw new CartNotFoundException("尝试访问的购物车数据不存在");
        }

        // 判断查询结果中的uid与参数uid是否不一致
        if (!result.getUid().equals(uid)) {
            // 是:抛出AccessDeniedException
            throw new AccessDeniedException("非法访问");
        }

        // 可选:检查商品的数量是否大于多少(适用于增加数量)或小于多少(适用于减少数量)
        // 根据查询结果中的原数量增加1得到新的数量num
        Integer num = result.getNum() + 1;

        // 创建当前时间对象,作为modifiedTime
        Date now = new Date();
        // 调用updateNumByCid(cid, num, modifiedUser, modifiedTime)执行修改数量
        Integer rows = cartMapper.updateNumByCid(cid, num, username, now);
        if (rows != 1) {
            throw new InsertException("修改商品数量时出现未知错误,请联系系统管理员");
        }

        // 返回新的数量
        return num;
    }

    @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;
    }
}

5. 购物车 - 控制层

@RestController
@RequestMapping("carts")
public class CartController extends BaseController {
    @Autowired
    private ICartService cartService;

    @RequestMapping("add_to_cart")
    public JsonResult<Void> addToCart(Integer pid, Integer amount, HttpSession session) {
        System.out.println("pid=" + pid);
        System.out.println("amount=" + amount);
        // 从Session中获取uid和username
        Integer uid = getUidFromSession(session);
        String username = getUsernameFromSession(session);
        // 调用业务对象执行添加到购物车
        cartService.addToCart(uid, pid, amount, username);
        // 返回成功
        return new JsonResult<Void>(OK);
    }

    @GetMapping({"", "/"})
    public JsonResult<List<CartVO>> getVOByUid(HttpSession session) {
        // 从Session中获取uid
        Integer uid = getUidFromSession(session);
        // 调用业务对象执行查询数据
        List<CartVO> data = cartService.getVOByUid(uid);
        // 返回成功与数据
        return new JsonResult<List<CartVO>>(OK, data);
    }

    @RequestMapping("{cid}/num/add")
    public JsonResult<Integer> addNum(@PathVariable("cid") Integer cid, HttpSession session) {
        // 从Session中获取uid和username
        /**
            protected final Integer getUidFromSession(HttpSession session) {
        return Integer.valueOf(session.getAttribute("uid").toString());
    }
        */
        Integer uid = getUidFromSession(session);
        String username = getUsernameFromSession(session);
        // 调用业务对象执行增加数量
        Integer data = cartService.addNum(cid, uid, username);
        // 返回成功
        return new JsonResult<Integer>(OK, data);
    }

    @GetMapping("list")
    public JsonResult<List<CartVO>> getVOByCids(Integer[] cids, HttpSession session) {
        // 从Session中获取uid
        Integer uid = getUidFromSession(session);
        // 调用业务对象执行查询数据
        List<CartVO> data = cartService.getVOByCids(uid, cids);
        // 返回成功与数据
        return new JsonResult<>(OK, data);
    }
}

6. 购物车 - 前端页面

/**商品页面用json格式提交数据 */ 
					data: {
						"pid": id,
						"amount": $("#num").val()
					},


$("#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";
					}
				});
			});
<form action="orderConfirm.html" role="form" >
	<!--购物车表格开始-->
	<table class="cart-table" width="100%">
		<thead>
			<tr>
				<th width="8%">
					<input type="checkbox" class="ckall" onclick="checkall(this)" />全选</th>
				<th width="110"></th>
				<th width="29%">商品</th>
				<th width="11%">单价</th>
				<th width="15%">数量</th>
				<th width="11%">金额</th>
				<th>操作</th>
			</tr>
		</thead>
		<tbody id="cart-list" class="cart-body">
			<tr>
				<td>
					<input type="checkbox" class="ckitem" />
				</td>
				<td><img src="../images/portal/12DELLXPS13-silvery/collect.png" class="img-responsive" /></td>
				<td>联想(Lenovo)小新Air13 Pro 13.3英寸14.8mm超轻薄笔记本电脑</td>
				<td>¥<span id="goodsPrice1">5298</span></td>
				<td>
					<input type="button" value="-" class="num-btn" onclick="reduceNum(1)" />
					<input id="goodsCount1" type="text" size="2" readonly="readonly" class="num-text" value="1">
					<input class="num-btn" type="button" value="+" onclick="addNum(1)" />
				</td>
				<td><span id="goodsCast1"></span></td>
				<td>
					<input type="button" onclick="delCartItem(this)" class="cart-del btn btn-default btn-xs" value="删除" />
				</td>
			</tr>
			
		</tbody>
	</table>
	<div class="total-bar">
		<a href="javascript:selDelCart()" class="cart-del-sel btn btn-default btn-xs">删除所选商品</a>
		<span class="pull-right">已选商品
		<span id="selectCount">0</span>件 总价¥
		<span id="selectTotal">0</span></span>
	</div>
	<div>
		<span class="pull-right">
		<input type="submit" value="  结  算  " class="btn btn-primary btn-lg link-account" />
	</span>
	</div>
</form>


<script type="text/javascript">
$(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 = ''
							+ ''
							+ 	'<input name="cids" value="#{cid}" type="checkbox" class="ckitem" />'
							+ ''
							+ '<td><img src="..#{image}collect.png" class="img-responsive" /></td>'
							+ '<td>#{title}#{msg}</td>'
							+ '<td>¥<span id="price-#{cid}">#{realPrice}</span></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>¥<span id="total-price-#{cid}">#{totalPrice}</span></td>'
							+ ''
							+ 	'<input type="button" onclick="delCartItem(this)" class="cart-del btn btn-default btn-xs" value="删除" />'
							+ ''
						 + '';
				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);
			}
		}
	});
}

第七节 订单

第八节 商品秒杀

外星人商城项目总结

你可能感兴趣的:(外星人官方笔记本商城,spring,boot,后端,java)