SpringBoot项目--电脑商城【增加/减少购物车商品数量】

news2024/11/25 13:40:17

1.持久层[Mapper]

1.1规划需要执行的SQL语句

1.更新该商品的数量.此SQL语句无需重复开发

update t_cart set num=?,modified_user=?,modified_time=? where cid=?

2.首先进行查询需要操作的购物车数据信息【查看该条数据是否存在】

SELECT * FROM t_cart WHERE cid=?

2.接口和抽象方法

在CartMapper接口中添加抽象方法

Cart findByCid(Integer cid);

3 编写映射

在CartMapper文件中添加findByCid(Integer cid)方法的映射

    <select id="findByCid" resultMap="CartEntityMap">
        select *
        from t_cart
        where cid=#{cid};
    </select>

4 单元测试

在CartMapperTests测试类中添加findByCid()测试方法

@Test
public void findByCid() {
    System.out.println(cartMapper.findByCid(1));
}

2.业务层[service]

1规划异常

  • 在更新时产生UpdateException未知异常,此异常类无需再次创建
  • 可能该购物车列表数据归属不是登录的用户,抛AccessDeniedException异常,此异常类无需再次创建
  • 要查询的数据不存在.抛出CartNotFoundException异常,创建该异常类并使其继承ServiceException
/** 购物车数据不存在的异常 */
public class CartNotFoundException extends ServiceException {
    /**重写ServiceException的所有构造方法*/
}

2设计接口和抽象方法及实现

在业务层ICartService接口中添加addNum()抽象方法

1.先判断需要哪些参数,该抽象方法的实现依赖于CartMapper接口的两个方法:

updateNumByCid方法.参数是cid,num,String modifiedUser,Date modifiedTime

findByCid方法.参数是cid

在业务层中从购物车表查询到该商品的数量,然后再和前端传过来的增加的数量进行求和得到num

所以该方法的参数是cid,uid,username

2.判断一下该方法的返回值:

  • 该方法返回值void.这样的话就需要在前端页面加location.href使该页面自己跳转到自己,实现刷新页面(不建议,每次都加载整个页面,数据量太大了)
  • 返回值是Integer类型.这样的话就把数据库中更新后的数量层层传给前端,前端接收后填充到控件中就可以了
/**
* 增加用户的购物车中某商品的数量
* @param cid
* @param uid
* @param username
* @return 增加成功后新的数量
*/
Integer addNum(Integer cid,Integer uid, String username);

3.在CartServiceImpl类中实现接口中的抽象方法

    /**
     *  更新用户的购物车数量的数据
     *
     * 调用了updateNumByCid(cid,num,modifiedUser,modifiedTime)
     *      和findByCid(cid)
     *  Integer:返回的是最新的购物车数量
     */
    @Override
    public Integer addNum(Integer cid, Integer uid, String username) {
        Cart result = cartMapper.findByCid(cid);
        if(result == null) {
            throw new CartNotFoundException("购物车数据不存在");
        } else if(! result.getUid().equals(uid)) {
            throw new AccessDeniedException("数据非法访问");
        }

        Integer num = result.getNum() + 1;
        Integer rows = cartMapper.updateNumByCid(cid, num, username, new Date());

        if(rows != 1) {
            throw new UpdateException("更新数据失败");
        }

        return num;
    }

3单元测试

就接收个参数,然后业务层将其加一后返回,不需要再测了

3.控制层[Controller]

1处理异常

在BaseController类中添加CartNotFoundException异常类的统一管理

else if (e instanceof CartNotFoundException) {
    result.setState(4007);
    result.setMessage("购物车表不存在该商品的异常");
}

2设计请求

  • /carts/{cid}/num/add
  • post
  • @PathVariable(“cid”) Integer cid, HttpSession session
  • JsonResult<Integer>

3处理请求

在CartController类中添加处理请求的addNum()方法

    @PostMapping("/{cid}/add_num")
    public JsonResult<Integer> addNum(@PathVariable("cid") Integer cid,
                                      HttpSession session){
        Integer data = cartService.addNum(cid,
                getuidFromSession(session),
                getUsernameFromSession(session));
        return new JsonResult<>(OK,data);
    }

4.前端页面

1.首先确定在showCartList()函数中动态拼接的增加购物车按钮是绑定了addNum()事件,如果已经添加无需重复添加

<input class="num-btn" type="button" value="+" onclick="addNum(#{cid})" />

2.在script标签中定义addNum()函数并编写增加购物车数量的逻辑代码

//添加商品按钮
			function addNum(cid){
				$.ajax({
					url:"/cart/"+cid+"/add_num",
					type: "POST",
					dataType:"JSON",
					success(e){
						console.log(e.state)
						if (e.state==200){
							//<input id="goodsCount#{cid}" type="text" size="2" readonly="readonly" class="num-text" value="#{num}">
							//修改商品数量,
							// val(): 因为这里使用val,是为了修改value的值
							$("#goodsCount" + cid).val(e.data);
							//<td>¥<span id="goodsPrice#{cid}">#{singlePrice}</span></td>
							//商品单价
							//html():选中所选元素的html,可能有html元素
							let singlePrice=$("#goodsPrice"+cid).html();
							let totalPrice=singlePrice*e.data;
							//表示将总数加入页面中
							//<td><span id="goodsCast#{cid}">#{totalPrice}</span></td>
							$("#goodsCast"+cid).html(totalPrice);
						}else{
							alert("增加购物车数据失败"+e.message)
						}
					},
					error(xhr){
						alert("增加购物车商品数据加载产生未知的异常"+xhr.status)
					}
				})
			}

1.持久层[Mapper]

1.规划需要执行的SQL语句

1.判断当前要删除的商品是否还存在[原来的findById]

selct * from t_cart where uid=? and cid=?

2.如果该商品在该用户的购物车中本来就有,则对其的操作是进行数据更新[原来的updateNumByCid]

2.接口和抽象方法

1.在CartMapper.java

    /**
     * 修改购物车数据中商品的数量
     * @param cid 购物车数据的id
     * @param num 新的数量
     * @param modifiedUser 修改执行人
     * @param modifiedTime 修改时间
     * @return 受影响的行数
     */
    Integer updateNumByCid(
            @Param("cid") Integer cid,
            @Param("num") Integer num,
            @Param("modifiedUser") String modifiedUser,
            @Param("modifiedTime") Date modifiedTime);

    /**
     * 根据用户id和商品id查询购物车中的数据
     * @param uid 用户id
     * @param pid 商品id
     * @return 匹配的购物车数据,如果该用户的购物车中并没有该商品,则返回null
     */
    Cart findByUidAndPid(
            @Param("uid") Integer uid,
            @Param("pid") Integer pid);

3.编写映射

    <!-- 修改购物车数据中商品的数量-->
    <update id="updateNumByCid">
        update t_cart set
                          num=#{num},
                          modified_user=#{modifiedUser},
                          modified_time=#{modifiedTime}
        where cid=#{cid}
    </update>
    <!-- 根据用户id和商品id查询购物车中的数据-->
    <select id="findByUidAndPid" resultMap="CartEntityMap">
        select * from t_cart where uid=#{uid} AND pid=#{pid}
    </select>

4.测试代码

此测试代码可以省略

2.业务层[Service]

1.规划异常

  • 在删除的时候,可能该数据被删除,造成删除异常
  • 在更新时产生UpdateException未知异常,此异常类无需再次创建
  • 可能该购物车列表数据归属不是登录的用户,抛AccessDeniedException异常,此异常类无需再次创建
  • 要查询的数据不存在.抛出CartNotFoundException异常,创建该异常类并使其继承ServiceException

2.设计接口和抽象方法的实现

1.ICartService

    /**
     * 更新用户的购物车数据--减少
     * @param cid
     * @param uid
     * @param username
     * @return
     */
    Integer subNum(Integer cid,Integer uid,String username);

2.ICartServiceImpl

    /**
     * 更新用户的购物车数据--减少
     * @param cid
     * @param uid
     * @param username
     * @return
     */
    @Override
    public Integer subNum(Integer cid, Integer uid, String username) {
        Cart result = cartMapper.findByCid(cid);
        if(result==null){
            throw new CartNotFoundException("购物车数据不存在");
        }
        if(!result.getUid().equals(uid)){
            throw new AccessDeniedException("数据非法访问");
        }
        Integer num=result.getNum()-1;
        Integer rows = cartMapper.updateNumByCid(cid, num, username, new Date());
        
        if(rows!=1){
            throw new UpdateException("更新数据失败");
        }
        return num;
    }

3.单元测试

    @Test
    public void subNum(){
        cartService.subNum(3,7,"管理员");
    }

3.控制层[Controller]

1.处理异常

前面增加功能已经实现,不用重复执行

2.设计请求

  • /cart/sub_num/{cid}
  • post
  • @PathVariable("cid") Integer cid,HttpSession session
  • JsonResult<Integer>

3.处理请求

    /**
     * 在购物车列表中减少商品数量
     * @param cid
     * @param session
     * @return
     */
    @PostMapping("/sub_num/{cid}")
    public JsonResult<Integer> subNum(@PathVariable("cid") Integer cid,
                                      HttpSession session){
        Integer data = cartService.subNum(cid,
                getuidFromSession(session),
                getUsernameFromSession(session));
        return new JsonResult<>(OK,data);
    }

4.前端页面

1.首先确定在showCartList()函数中动态拼接的增加购物车按钮是绑定了reduceNum()事件,如果已经添加无需重复添加

<input id="price-#{cid}"  type="button" value="-" class="num-btn" onclick="reduceNum(#{cid})" />

function reduceNum(cid) {
				$.ajax({
					url: "/cart/sub_num/"+cid,
					type: "POST",
					dataType: "JSON",
					success: function(json) {
						if (json.state == 200) {
							// showCartList();
							$("#goodsCount" + cid).val(json.data);
							let price = $("#goodsPrice" + cid).html();
							let totalPrice = price * json.data;
							$("#goodsCast" + cid).html(totalPrice);
						} else {
							alert("修改商品数量失败!" + json.message);
						}
					},
					error: function(xhr) {
						alert("您的登录信息已经过期,请重新登录!HTTP响应码:" + xhr.status);
						location.href = "login.html";
					}
				});
			}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1004042.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

如何解决实时语音通讯技术的延迟问题?

实时语音通讯技术的延迟问题一直是人们关注的焦点。在实时通讯中&#xff0c;延迟会影响到通话的质量和用户体验&#xff0c;因此如何解决实时语音通讯技术的延迟问题是一个重要的挑战。本文将探讨如何解决实时语音通讯技术的延迟问题。 一、延迟的定义和分类 延迟是指从说话…

C语言和汇编到底谁更厉害呢?

今日话题&#xff0c;C语言和汇编到底谁更厉害呢&#xff1f; 有位毕业生与我分享了他的经历。在学校&#xff0c;他学习了汇编和C语言。毕业后&#xff0c;他加入了一家嵌入式企业&#xff0c;发现C语言因其可移植性、开发效率和可读性而更为通用和适用。事实证明&#xff0c;…

排序算法-----冒泡排序与选择排序

目录 前言: 冒泡排序 原理图 代码实现 分析总结 选择排序 原理图 代码实现 分析总结 前言: 今天我们就开始学习排序算法&#xff0c;排序算法也是数据结构与算法在重要组成部分之一&#xff0c;排序算法是最经典的算法知识。因为其实现代码短&#xff0c;应该广&#x…

【设计模式】桥接模式在开发中的应用

1. 概述 桥接模式是一个非常简单的设计模式&#xff0c;可能大家在开发的过程中已经使用到了这种模式而不自知。总的来说&#xff0c;桥接模式最大的作用就是解耦&#xff0c;所谓的解耦&#xff0c;就是通过转换代码的设计&#xff0c;减少类与类&#xff0c;模块与模块之间的…

监听器,过滤器,拦截器

参考博文 文章目录 作用三者区别启动顺序拦截器简要说明实现接口HandlerInterceptor自定义拦截器配置拦截器 过滤器简要说明在springboot 启动类添加该注解ServletComponentScan写个过滤器类&#xff0c;实现Filter接口 监听器简要说明如何使用自定义事件自定义过滤器接口调用…

图片怎么转换成pdf格式?几种方法轻松转换

图片怎么转换成pdf格式&#xff1f;将图片转换成PDF格式的主要原因是方便共享和存储。PDF格式可以在不同的设备和操作系统上轻松打开和查看&#xff0c;而且可以保持原始图片的质量和分辨率。如果你需要将一些图片转换成PDF格式&#xff0c;你可能会问&#xff0c;“该如何做呢…

12个最受欢迎的3D打印机械臂【开源|DIY|套件】

推荐&#xff1a;用 NSDT编辑器 快速搭建可编程3D场景 机器人手臂的用途各不相同&#xff0c;但大多数都能够执行拾取和放置任务&#xff0c;而有些则配备用于 CNC 工作、激光雕刻&#xff0c;甚至 3D 打印。 机械臂具有广泛的应用和各个领域&#xff0c;从执行精密手术和进行工…

两行代码实现Redis消息队列,简单易用

Redis列表数据类型非常适合作为消息队列使用。将新的消息插入到列表尾部&#xff0c;然后从列表头部取出消息进行处理。该方案简单易用&#xff0c;并且支持多个消费者并行处理消息。 两行核心代码即可实现消息队列&#xff0c;如下&#xff1a; // 推送消息 redisTemplate.o…

Java中级编程大师班<第一篇:初识数据结构与算法-数组(2)>

数组&#xff08;Array&#xff09; 数组是计算机编程中最基本的数据结构之一。它是一个有序的元素集合&#xff0c;每个元素都可以通过索引进行访问。本文将详细介绍数组的特性、用法和注意事项。 数组的基本特性 数组具有以下基本特性&#xff1a; 有序性&#xff1a; 数…

初探词法分析实验

本次实验使用C对编译过程中的分词进行初步探究&#xff0c;以下是实验代码&#xff0c;输入文件需要在main函数中自己填写文本所在地址 #include <iostream> #include <stdlib.h> #include <stdio.h> #include<string> #define M 20 using namespace…

核心实验15_端口安全_ENSP

项目场景&#xff1a; 核心实验15_端口安全_ENSP 可指定该接口下最多接入几个设备&#xff08;通过mac绑定实现&#xff09;&#xff0c;人为增加设备时可设置接口自动down掉等&#xff0c;详见补充 实搭拓扑图&#xff1a; 具体操作&#xff1a; sw1: [Huawei]int g0/0/1 [H…

编辑视频无需第三方软件,在iPhone上也可以轻松编辑视频

如果你学会了如何在iPhone上编辑视频,你可以在很大程度上把匆忙拍摄的视频变成适合好莱坞的视频。好吧,也许这有点夸张了,但至少,你可以通过使用照片应用程序中的编辑工具,让你的视频看起来更令人印象深刻。 虽然它不一定能与最好的视频编辑软件相匹配,但它仍然非常适合…

MySQL 8.0 新密码策略的细节补充

前情提要 MySQL 8.0 截⽌到⽬前已经发布到了 8.0.34 版本&#xff0c;经过一系列的版本更新&#xff0c;对于密码方面也做了较多的加强⼯作&#xff0c;这⾥我们不再过多介绍 MySQL 8.0 对于密码功能的加强&#xff0c;相关的介绍可以移步先前公众号的⽂章&#xff0c;这⾥给到…

Pytorch 多卡并行(3)—— 使用 DDP 加速 minGPT 训练

前文 并行原理简介和 DDP 并行实践 和 使用 torchrun 进行容错处理 在简单的随机数据上演示了使用 DDP 并行加速训练的方法&#xff0c;本文考虑一个更加复杂的 GPT 类模型&#xff0c;说明如何进行 DDP 并行实战MinGPT 是 GPT 模型的一个流行的开源 PyTorch 复现项目&#xff…

paddleocr关闭log日志打印输出

问题背景 问题分析 可以看到paddleocr输出logging主要有两种&#xff0c;DEBUG和WARNING&#xff0c;因此关闭这两种打印日志即可。 解决方法 import logginglogging.disable(logging.DEBUG) # 关闭DEBUG日志的打印 logging.disable(logging.WARNING) # 关闭WARNING日志的…

Python二分查找详解

在计算机科学中&#xff0c;二分查找算法&#xff08;英语&#xff1a;binary search algorithm&#xff09;&#xff0c;也称折半搜索算法&#xff08;英语&#xff1a;half-interval search algorithm&#xff09;、对数搜索算法&#xff08;英语&#xff1a;logarithmic sea…

Pyinstaller打包EXE时添加版本信息、作者信息并在运行时读取外部配置文件

&#x1f9d1;‍&#x1f4bb;作者名称&#xff1a;DaenCode &#x1f3a4;作者简介&#xff1a;CSDN实力新星&#xff0c;后端开发两年经验&#xff0c;曾担任甲方技术代表&#xff0c;业余独自创办智源恩创网络科技工作室。会点点Java相关技术栈、帆软报表、低代码平台快速开…

亚马逊气候友好认证

“气候友好承诺认证”是亚马逊推出的Climate Pledge Friendly新环保计划。目的是帮助有环境意识、注重绿能的买家更好地找到带认证产品&#xff0c;品牌可以通过确保在亚马逊上销售的产品至少在可持续发展的一个方面得到认证&#xff0c;来参与并为他们的产品获得一个气候友好承…

ORA-32771 cannot add file to bigfile tablespace

ORA-32771 cannot add file to bigfile tablespace 扩容表空间报错 原因 oracle中有两种表空间类型BIGFILE 大文件表空间&#xff1a;只能包含1个大文件(最大尺寸为128 TB) SMALLFILE 小文件表空间&#xff1a;可包含多个数据文件(默认)表空间在创建的时候就会确定好&#xf…

OpenCV(三十八):二维码检测

1.二维码识别原理 功能图形&#xff1a; 位置探测图形&#xff1a;通常&#xff0c;二维码中有三个位置探测图形&#xff0c;呈现L型或大角度十字架形状&#xff0c;分布在二维码的三个角上&#xff0c;用于帮助扫描设备定位二维码的位置和方向。 位置探测图形分隔符&#xf…