SpringBoot项目--电脑商城【增加/减少购物车商品数量】
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_cartwhere 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:返回的是最新的购物车数量*/@Overridepublic 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 setnum=#{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*/@Overridepublic 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.单元测试
@Testpublic 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";}});}

相关文章:
SpringBoot项目--电脑商城【增加/减少购物车商品数量】
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.接口…...
CSS元素浮动
概述 浮动简介 在最初,浮动是用来实现文字环绕图片效果的,现在浮动是主流的页面布局方式之一。 元素浮动后的特点 脱离文档流。不管浮动前是什么元素,浮动后,默认宽与高都是被内容撑开的(尽可能小)&am…...
MATLAB中islocalmin函数用法
目录 语法 说明 示例 向量中的局部最小值 矩阵行中的最小值 相隔最小值 最小值平台区 突出最小值 islocalmin函数的功能是计算局部最小值。 语法 TF islocalmin(A) TF islocalmin(A,dim) TF islocalmin(___,Name,Value) [TF,P] islocalmin(___) 说明 当在 A 的…...
Python+Requests+Pytest+YAML+Allure实现接口自动化
本项目实现接口自动化的技术选型:PythonRequestsPytestYAMLAllure ,主要是针对之前开发的一个接口项目来进行学习,通过 PythonRequests 来发送和处理HTTP协议的请求接口,使用 Pytest 作为测试执行器,使用 YAML 来管理测…...
双视觉Transformer(Dual Vision Transformer)
摘要 已经提出了几种策略来减轻具有高分辨率输入的自注意机制的计算:比如将图像补丁上的全局自注意过程分解成区域和局部特征提取过程,每个过程都招致较小的计算复杂度。尽管效率良好,这些方法很少探索所有补丁之间的整体交互,因…...
MES系统成为工业4.0首选,制造业真正数字化车间你看过吗?
在日益激烈的市场竞争中,MES管理系统已经成为企业提升生产效率、降低成本、提高竞争力的关键。通过MES管理系统实现数据集成和分析,能够对产品制造过程的各个环节进行可视化控制,从设计、制造、质量、物流等环节全面掌控信息,实现…...
Vuex有几种属性以及它们的意义
有五种,分别是 State、 Getter、Mutation 、Action、 Module。 一、State Vuex 使用单一状态树——是的,用一个对象就包含了全部的应用层级状态。至此它便作为一个“唯一数据源 (SSOT)”而存在。这也意味着,每个应用将仅仅包含一个 store 实…...
PRBP20P-10/250C-EB、PRDP6G-10/30-CB电液比例直动式先导减压阀放大板
PRDP6P-10/30-CB、PRDP6R-10/50-DC、PRDP6G-10/30-CC、PRDP6P-10/50-CB、PRDP6R-10/30-CC、PRDP6G-10/30-CB电液比例直动式先导减压阀 PRBP10P-10/50C-EB、PRBP20P-10/100C-EC、PRBP30P-10/150C-EB、PRBP20P-10/250C-EB、PRBP10P-10/315C-EC、PRBP30P-10/350C-EB电液比例柱塞平…...
GDB之常见缩写命令(十九)
简介: CSDN博客专家,专注Android/Linux系统,分享多mic语音方案、音视频、编解码等技术,与大家一起成长! 优质专栏:Audio工程师进阶系列【原创干货持续更新中……】🚀 人生格言: 人生…...
MarkText快捷键(随时补充中)
MarkText快捷键 ctrl1:一号标题 (需要手动在【左上角】-【file】-【preferences】-【Key Bindings】-【 Transform into Heading 1】手动调整,先将【Switch tab to the 1st】占用快捷键删除才能在下面添加) ctrlg:添加…...
每日一题 1601最多可达成的换楼请求数目(子集模版)
题目 1601 我们有 n 栋楼,编号从 0 到 n - 1 。每栋楼有若干员工。由于现在是换楼的季节,部分员工想要换一栋楼居住。 给你一个数组 requests ,其中 requests[i] [fromi, toi] ,表示一个员工请求从编号为 fromi 的楼搬到编号为…...
排序算法-归并排序
属性 归并排序(MERGE-SORT)是建立在归并操作上的一种有效的排序算法,该算法是采用分治法(Divide and Conquer)的一个非常典型的应用。将已有序的子序列合并,得到完全有序的序列;即先使每个子序列有序&#…...
vue3 整合 springboot 打完整jar包
前端 .env.developmen VITE_APP_BASE_URL/api.env.production VITE_APP_BASE_URL/axios 配置 axios.defaults.baseURL import.meta.env.VITE_APP_BASE_URLpackage.json "scripts": {"dev": "vite --mode development","build": &…...
依赖倒转原则是什么?
依赖倒转原则(Dependency Inversion Principle)是面向对象设计中的另一个基本原则,它是由Robert C. Martin提出的,它的中心思想是面向接口编程,该原则指出高层模块不应该依赖于低层模块,两者都应该依赖于抽…...
什么是GPT与MBR
GPT(GUID Partition Table)和MBR(Master Boot Record)是两种不同的磁盘分区表格式。 MBR是一种较早的磁盘分区表格式,它使用512字节的扇区作为存储空间。MBR分区表可以定义最多4个主分区,每个主分区都可以…...
前后端开发接口联调对接参数
前言 一个完整的互联网系统项目,需要前后端配合,进行上线,针对前端开发者,现在互联网主流的项目都是前后端分离 也就是后端负责提供数据接口,前端负责UI界面数据渲染 凡是在前台数据展示与用户交互的,都是由前端来实现的,而数据来源是由后台服务提供的 在浏览器c端能够发送后端…...
定时任务框架-xxljob
1.定时任务 spring传统的定时任务Scheduled,但是这样存在这一些问题 : 做集群任务的重复执行问题 cron表达式定义在代码之中,修改不方便 定时任务失败了,无法重试也没有统计 如果任务量过大,不能有效的分片执行 …...
idea项目配置三大步
场景: 使用 idea 打开一个新项目的时候,想让项目迅速跑起来, 其实只需要下面简单三步: 1. 首先,配maven 2. 其次,配置 jdk 这里配置 project 就行了,不用管Modules中的配置。 3. 最后&#…...
学会SpringMVC之自定义注解各种场景应用,提高开发效率及代码质量
目录 一、简介 ( 1 ) 是什么 ( 2 ) 分类 ( 3 ) 作用 二、自定义注解 ( 1 ) 如何自定义注解 ( 2 ) 场景演示 场景一(获取类与方法上的注解值) 场景二( 获取类属性上的注解属性值 ) 场景三( 获取参数修…...
步态识别常见模块解读及代码实现:基于OpenGait框架
步态识别常见模块解读及代码实现:基于OpenGait框架 最近在看步态识别相关论文,但是因为记忆力下降的原因,老是忘记一些内容。因此记录下来方便以后查阅,仅供自己学习参考,没有背景知识和论文介绍。 目录 步态识别常见…...
【力扣数据库知识手册笔记】索引
索引 索引的优缺点 优点1. 通过创建唯一性索引,可以保证数据库表中每一行数据的唯一性。2. 可以加快数据的检索速度(创建索引的主要原因)。3. 可以加速表和表之间的连接,实现数据的参考完整性。4. 可以在查询过程中,…...
Go 语言接口详解
Go 语言接口详解 核心概念 接口定义 在 Go 语言中,接口是一种抽象类型,它定义了一组方法的集合: // 定义接口 type Shape interface {Area() float64Perimeter() float64 } 接口实现 Go 接口的实现是隐式的: // 矩形结构体…...
高频面试之3Zookeeper
高频面试之3Zookeeper 文章目录 高频面试之3Zookeeper3.1 常用命令3.2 选举机制3.3 Zookeeper符合法则中哪两个?3.4 Zookeeper脑裂3.5 Zookeeper用来干嘛了 3.1 常用命令 ls、get、create、delete、deleteall3.2 选举机制 半数机制(过半机制࿰…...
抖音增长新引擎:品融电商,一站式全案代运营领跑者
抖音增长新引擎:品融电商,一站式全案代运营领跑者 在抖音这个日活超7亿的流量汪洋中,品牌如何破浪前行?自建团队成本高、效果难控;碎片化运营又难成合力——这正是许多企业面临的增长困局。品融电商以「抖音全案代运营…...
HashMap中的put方法执行流程(流程图)
1 put操作整体流程 HashMap 的 put 操作是其最核心的功能之一。在 JDK 1.8 及以后版本中,其主要逻辑封装在 putVal 这个内部方法中。整个过程大致如下: 初始判断与哈希计算: 首先,putVal 方法会检查当前的 table(也就…...
Aspose.PDF 限制绕过方案:Java 字节码技术实战分享(仅供学习)
Aspose.PDF 限制绕过方案:Java 字节码技术实战分享(仅供学习) 一、Aspose.PDF 简介二、说明(⚠️仅供学习与研究使用)三、技术流程总览四、准备工作1. 下载 Jar 包2. Maven 项目依赖配置 五、字节码修改实现代码&#…...
云原生安全实战:API网关Kong的鉴权与限流详解
🔥「炎码工坊」技术弹药已装填! 点击关注 → 解锁工业级干货【工具实测|项目避坑|源码燃烧指南】 一、基础概念 1. API网关(API Gateway) API网关是微服务架构中的核心组件,负责统一管理所有API的流量入口。它像一座…...
MacOS下Homebrew国内镜像加速指南(2025最新国内镜像加速)
macos brew国内镜像加速方法 brew install 加速formula.jws.json下载慢加速 🍺 最新版brew安装慢到怀疑人生?别怕,教你轻松起飞! 最近Homebrew更新至最新版,每次执行 brew 命令时都会自动从官方地址 https://formulae.…...
【多线程初阶】单例模式 指令重排序问题
文章目录 1.单例模式1)饿汉模式2)懒汉模式①.单线程版本②.多线程版本 2.分析单例模式里的线程安全问题1)饿汉模式2)懒汉模式懒汉模式是如何出现线程安全问题的 3.解决问题进一步优化加锁导致的执行效率优化预防内存可见性问题 4.解决指令重排序问题 1.单例模式 单例模式确保某…...
JS的传统写法 vs 简写形式
一、条件判断与逻辑操作 三元运算符简化条件判断 // 传统写法 let result; if (someCondition) {result yes; } else {result no; }// 简写方式 const result someCondition ? yes : no;短路求值 // 传统写法 if (condition) {doSomething(); }// 简写方式 condition &…...
