1. 持久层
1.1 规划sql语句
- 执行更新t_cart表记录的num值
- 根据cid查询购物车的数据是否存在
select * from t_cart where cid=#{cid}
1.2 接口和抽象方法
/*** 获取购物车中商品的数据总数* @return 购物车中商品的数据总数*/Cart findByCid(Integer cid);
1.3 xml文件中sql映射
<select id="findByCid" resultMap="CartEntityMap">select * from t_cart where cid=#{cid}</select>
1.4 测试类中进行测试
@Testpublic void findByCid() {Integer cid = 1;Cart cart = cartMapper.findByCid(cid);System.out.println(cart);}
2. 业务层
2.1 规划异常
-
更新时产生的更新异常
-
查询时数据是否有访问的权限
-
要查询的数据不存在,CartNotFoundException异常
package com.cy.store.service.ex;public class CartNotFoundException extends ServiceException{public CartNotFoundException() {super();}public CartNotFoundException(String message) {super(message);}public CartNotFoundException(String message, Throwable cause) {super(message, cause);}public CartNotFoundException(Throwable cause) {super(cause);}protected CartNotFoundException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {super(message, cause, enableSuppression, writableStackTrace);}
}
2.2 接口和抽象方法
/*** 添加购物车数量* @param cid 购物车数据id* @param uid 用户id* @param username 用户名* @return 修改后的购物车商品数量*/Integer addNum(Integer cid, Integer uid, String username);/*** 减少购物车数量* @param cid 购物车数据id* @param uid 用户id* @param username 用户名* @return 修改后的购物车商品数量*/Integer cutNum(Integer cid, Integer uid, String username);
2.3 实现类实现接口,重写抽象方法
/*** 修改购物车商品的数量* @param cid 购物车id* @param uid 用户id* @param username 用户名* @return 修改后的商品数量*/@Overridepublic Integer addNum(Integer cid, Integer uid, String username) {
// 判断数据库中是否有购物车数据Cart cart = cartMapper.findByCid(cid);if (cart==null){throw new CartNotFoundException("购物车数据不存在");}if (cart.getUid()!=uid){throw new AccessDeniedException("非法访问");}
// 进行数量+1操作Integer newNum = cart.getNum()+1;Integer rows = cartMapper.updateNumByCid(cid,newNum,username,new Date());
// 如果返回影响行数不为1,则抛出更新数据产生未知的异常if (rows!=1){throw new UpdateException("更新数据时产生未知的异常");}// 返回数据库中商品的数量return newNum;}/*** 减少购物车商品的数量* @param cid 购物车id* @param uid 用户id* @param username 用户名* @return 修改后的商品数量*/@Overridepublic Integer cutNum(Integer cid, Integer uid, String username) {
// 判断数据库中是否有购物车数据Cart cart = cartMapper.findByCid(cid);if (cart==null){throw new CartNotFoundException("购物车数据不存在");}if (cart.getUid()!=uid){throw new AccessDeniedException("非法访问");}Integer newNum = null;if (cart.getNum()!=0){// 进行数量-1操作newNum = cart.getNum()-1;Integer rows = cartMapper.updateNumByCid(cid,newNum,username,new Date());// 如果返回影响行数不为1,则抛出更新数据产生未知的异常if (rows!=1){throw new UpdateException("更新数据时产生未知的异常");}}else {throw new CartNotFoundException("无法减少商品了");}// 返回数据库中商品的数量return newNum;}
}
3. 控制层
3.1 规划异常的处理
在BaseController中捕获CartNotFoundException异常
/*** 控制层基类*/
public class BaseController {//操作成功的状态码public static final int OK = 200;/*** 全局异常处理器,用于捕获并处理业务层抛出的异常。** @param e 捕获的异常对象* @return 返回封装后的 JsonResult 对象,包含状态码和错误信息*/
// 该项目中产生了异常,会被统一拦截到此方法中,这个方法此时就充当了请求处理方法,方法的返回值直接给前端浏览器,返回给前端的数据中,状态码,状态码对应信息,数据@ExceptionHandler({ServiceException.class, FileUploadException.class})public JsonResult<Void> handleException(Throwable e) {// 创建一个 JsonResult 实例,并初始化异常消息JsonResult<Void> result = new JsonResult<>(e);// 判断异常类型,设置对应的状态码和提示信息if (e instanceof UsernameDuplicatedException){// 用户名被占用时返回 400 状态码和相应提示result.setState(4000);result.setMessage("用户名被占用");} else if (e instanceof InsertException){// 插入数据失败时返回 500 状态码和相应提示result.setState(4000);result.setMessage("注册时产生未知的异常");}else if (e instanceof UsernameNotFoundException){result.setState(4001);result.setMessage("用户数据不存在");}else if (e instanceof PasswordNotMatchException){result.setState(4002);result.setMessage("用户密码错误");}else if (e instanceof AddressCountLimitException){result.setState(4003);result.setMessage("收货地址超出上限");}else if (e instanceof CartNotFoundException){result.setState(4007);result.setMessage("购物车数据不存在");}else if (e instanceof AccessDeniedException){result.setState(4004);result.setMessage("收货地址数据非法访问");}else if (e instanceof AddressNotFoundException){result.setState(4005);result.setMessage("收货地址数据不存在");}else if (e instanceof ProductNotFoundException){result.setState(4006);result.setMessage("商品数据不存在");}else if (e instanceof DeleteException){result.setState(5002);result.setMessage("删除数据时产生未知的异常");}else if (e instanceof UpdateException){result.setState(5003);result.setMessage("更新数据时产生未知的异常");} else if (e instanceof FileEmptyException) {result.setState(6000);} else if (e instanceof FileSizeException) {result.setState(6001);} else if (e instanceof FileTypeException) {result.setState(6002);} else if (e instanceof FileStateException) {result.setState(6003);} else if (e instanceof FileUploadIOException) {result.setState(6004);}// 返回最终的响应结果return result;}/*** 从Session中获取当前登录用户的uid* * @param session HttpSession对象,用于获取会话中的用户ID* @return 当前登录用户的uid* * `protected` 表示该方法只能被同一个包内的类或子类访问。* `final` 表示该方法不能被子类重写。*/protected final Integer getUidFromSession(HttpSession session) {// 从Session中获取uid// 从会话中获取uid属性并转换为整数类型返回return Integer.valueOf(session.getAttribute("uid").toString());}/*** 从Session中获取当前登录用户的用户名* @param session HttpSession对象,用于获取会话中的用户名* @return 当前登录用户的用户名*/protected final String getUsernameFromSession(HttpSession session) {// 从Session中获取当前登录的用户名return session.getAttribute("username").toString();}}
3.2 规划并实现请求
/*** 增加购物车商品数量* @param cid 购物车id* @param session 登录用户* @return 修改数量*/@RequestMapping("/num/add/{cid}")public JsonResult<Integer> addNum(@PathVariable("cid") Integer cid, HttpSession session) {Integer uid = getUidFromSession(session);String username = getUsernameFromSession(session);Integer data = cartService.addNum(cid, uid, username);return new JsonResult<>(OK, data);}/*** 减少购物车商品数量* @param cid 购物车id* @param session 登录用户* @return 修改数量*/@RequestMapping("/num/cut/{cid}")public JsonResult<Integer> cutNum(@PathVariable("cid") Integer cid, HttpSession session) {Integer uid = getUidFromSession(session);String username = getUsernameFromSession(session);Integer data = cartService.cutNum(cid, uid, username);return new JsonResult<>(OK, data);}
3.3 测试
启动项目,先登录,再通过访问url地址进行测试
4. 前端代码
增加减少购物车商品数量的逻辑基本上是一样的
<script type="text/javascript">
<!-- 当页面加载时发送获取购物车列表的请求 -->$(document).ready(function() {showCartList();});//展示购物车列表数据function showCartList() {// 清空数据区$("#cart-list").empty();$.ajax({url: "/carts",type: "GET",dataType: "JSON",success: function(json) {var list = json.data;// 遍历后端响应过来的数据for (var i = 0; i < list.length; i++) {// 给数据进行占位var tr = '<tr>\n' +'<td>\n' +'<input name="cids" value="#{cid}" type="checkbox" class="ckitem" />\n' +'</td>\n' +'<td><img src="..#{image}collect.png" class="img-responsive" /></td>\n' +'<td>#{title}#{msg}</td>\n' +'<td>¥<span id="goodsPrice#{cid}">#{singlePrice}</span></td>\n' +'<td>\n' +'<input type="button" value="-" class="num-btn" onclick="reduceNum(#{cid})" />\n' +'<input id="goodsCount#{cid}" type="text" size="2" readonly="readonly" class="num-text" value="#{num}">\n' +'<input class="num-btn" type="button" value="+" onclick="addNum(#{cid})" />\n' +'</td>\n' +'<td><span id="goodsCast#{cid}">#{totalPrice}</span></td>\n' +'<td>\n' +'<input type="button" onclick="delCartItem(this)" class="cart-del btn btn-default btn-xs" value="删除" />\n' +'</td>\n' +'</tr>';// 赋值tr = tr.replaceAll(/#{cid}/g, list[i].cid);tr = tr.replaceAll(/#{image}/g, list[i].image);tr = tr.replaceAll(/#{title}/g, list[i].title);tr = tr.replaceAll(/#{singlePrice}/g, list[i].realPrice);tr = tr.replaceAll(/#{num}/g, list[i].num);tr = tr.replaceAll(/#{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);}},error: function (xhr) {alert("加载购物车列表数据时产生未知的异常"+xhr.status);}});}function addNum(cid) {$.ajax({url: "/carts/num/add/"+cid,type: "POST",dataType: "JSON",success: function (json) {if (json.state == 200) {$("#goodsCount"+cid).val(json.data);// .html() 修改某个标签的内容var price = $("#goodsPrice"+cid).html();var totalPrice = price * json.data;//将商品总价更新到标签中$("#goodsCast"+cid).html(totalPrice);} else {alert("增加购物车商品数量失败"+json.message);}},error: function (xhr) {alert("增加购物车商品数量时产生未知的异常!"+xhr.message);}});}// 减少购物车商品数量function reduceNum(cid) {$.ajax({url: "/carts/num/cut/"+cid,type: "POST",dataType: "JSON",success: function (json) {if (json.state == 200) {$("#goodsCount"+cid).val(json.data);// .html() 修改某个标签的内容var price = $("#goodsPrice"+cid).html();var totalPrice = price * json.data;//将商品总价更新到标签中$("#goodsCast"+cid).html(totalPrice);} else {alert("增加购物车商品数量失败"+json.message);}},error: function (xhr) {alert("增加购物车商品数量时产生未知的异常!"+xhr.message);}});}// $(function() {// //返回链接// $(".link-account").click(function() {// location.href = "orderConfirm.html";// })// })</script>