【基于SprintBoot+Mybatis+Mysql】电脑商城项目之加入购物车和显示购物车列表
🧸安清h:个人主页
🎥个人专栏:【Spring篇】【计算机网络】【Mybatis篇】
🚦作者简介:一个有趣爱睡觉的intp,期待和更多人分享自己所学知识的真诚大学生。
目录
🚀1.加入购物车-数据创建
🚀2.加入购物车-实体类
🚀3.加入购物车-持久层
✨3.1规划需要执行的SQL语句
✨3.2设计接口和抽象方法
✨3.3 SQL映射
🚀4.加入购物车-业务层
✨4.1规划异常
✨4.2接口和抽象方法的设计
✨4.3实现接口
🚀5.加入购物车-控制层
✨5.2设计请求
✨5.3处理请求
🚀6.加入购物车-前端页面
🎯1.显示购物车列表- 持久层
✨1.1规划SQL语句
✨1.2构建VO类
✨1.3设计接口和抽象方法
✨1.4配置SQL映射
🎯2.显示购物车列表- 业务层
🎯3.显示购物车列表- 控制层
✨3.1设计请求
✨3.2处理请求
🎯4.显示购物车列表- 前端页面
🎃1. 增加购物车商品数量-持久层
✨1.1规划需要执行的SQL语句
✨1.2设计接口和抽象方法
✨1.3配置SQL映射
🎃 2.增加购物车商品数量-业务层
✨2.1规划异常
✨2.2设计接口和抽象方法
✨ 2.3实现方法
🎃 3.增加购物车商品数量-控制层
✨3.1处理异常
✨3.2设计请求
✨3.3处理请求
🎃 4.增加购物车商品数量-前端页面
🚀1.加入购物车-数据创建
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;
num:当用户重复添加商品时,只修改num就可以了,无需再重复添加商品。
🚀2.加入购物车-实体类
public class Cart extends BaseEntity{private Integer cid;private Integer uid;private Integer pid;private Long price;private Integer num;
。。。。。。
}
🚀3.加入购物车-持久层
✨3.1规划需要执行的SQL语句
1.向购物车表中插入数据。
insert into t_cart values(值列表)
2.当当前的商品已经在购物车中存在,则直接更新num的数量即可。
update t_cart set num=? where cid=?
3.在插入或更新具体执行那个语句,取决于数据库中是否有当前的这个购物车商品的数据,得去查询才能查询。对当前的用户的pid进行查询,加上uid=?,而不是对当前的整张表进行查询。
select * from t_cart where pid=? and uid=?
✨3.2设计接口和抽象方法
创建一个CartMapper接口持久层的文件。
/*** 插入购物车数据* @param cart 购物车数据* @return 受影响的行数* 插入时最好放在一个对象中传递,所以用Cart参数列表* 插入后在业务层可能调用,需要有返回值判断能否插入成功*/Integer insert(Cart cart);/*** 更新购物车某件商品的数量* @param cid 购物数据id* @param num 更新的数量* @param modifiedUser 修改人* @param modifiedTime 修改时间* @return 受影响的行数* 更新时涉及到修改人和修改时间,除了cid外,还需要知道数量num*/Integer updateNumByCid(Integer cid, Integer num, String modifiedUser, Date modifiedTime);/*** 根据用户的id和商品的id来查询购物车中的数据* @param uid 用户id* @param pid 商品id*/Cart findByUidAndPid(Integer uid,Integer pid);
✨3.3 SQL映射
1.创建一个CartMapper.xml映射文件,添加以上三个抽象方法的SQL映射。
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.cy.store.mapper.CartMapper"><resultMap id="CartEntityMap" type="com.cy.store.entity.Cart"><id property="cid" column="cid"/><result column="created_user" property="createdUser"></result><result column="created_time" property="createdTime"></result><result column="modified_user" property="modifiedUser"></result><result column="modified_time" property="modifiedTime"></result></resultMap><insert id="insert" useGeneratedKeys="true" keyProperty="cid">insert into 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 t_cart set num=#{num},modified_user=#{modifiedUser},modified_time=#{modifiedTime}where cid=#{cid}</update><select id="findByUidAndPid" resultMap="CartEntityMap">select * from t_cart where pid=#{pid} and uid=#{uid}</select>
</mapper>
2.进行测试
@SpringBootTest
public class CartMapperTests {@Autowiredprivate CartMapper cartMapper;@Testpublic void insert(){Cart cart = new Cart();cart.setNum(3);cart.setPid(10000002);cart.setUid(6);cartMapper.insert(cart);}@Testpublic void updateNumByCid(){cartMapper.updateNumByCid(1,6,"小明",new Date());}@Testpublic void findByUidAndPid(){Cart cart = cartMapper.findByUidAndPid(6,10000002);System.err.println(cart);}
}
🚀4.加入购物车-业务层
✨4.1规划异常
1.插入数据时可能产生异常:InsertException。
2.更新数据时可能产生异常:UpdateException。
✨4.2接口和抽象方法的设计
分析:
1.首先要进行商品的查询,这里面通过findByUidAndPid方法必须要传递过来的是uid和pid的字段。
2.假设拿到后,就要对原有的数据进行更新,需要传递的字段有:cid,num,username。
/*** 将商品添加到购物车中* @param uid 用户id* @param pid 商品id* @param amount 新增数量* @param username 用户名(修改者)*/void addToCart(Integer uid,Integer pid,Integer amount,String username);
✨4.3实现接口
1.创建一个CartServiceImpl的实现类。
@Service
public class CartServiceImpl implements ICartService {
//购物车的业务层依赖于购物车的持久层和商品的持久层@Autowiredprivate CartMapper cartMapper;@Autowired//购物车中的一些定义的字段实际上是从商品表中分离出来的private ProductMapper productMapper;@Overridepublic void addToCart(Integer uid, Integer pid, Integer amount, String username) {//查询当前要添加的购物车是否在表中已存在Cart result = cartMapper.findByUidAndPid(uid,pid);Date date = new Date();if(result == null){ //表示这个商品从来没有被添加到购物车中,则进行新增操作//创建一个Cart对象Cart cart = new Cart();//补全数据:首先补全参数传递过来的数据cart.setPid(pid);cart.setUid(uid);//这里的amount暂且理解为在前端加好,把总数传递过来cart.setNum(amount);//补全价格:来自于商品中的数据Product product = productMapper.findById(pid);cart.setPrice(product.getPrice());//补全四日志cart.setCreatedUser(username);cart.setCreatedTime(date);cart.setModifiedUser(username);cart.setModifiedTime(date);//执行数据的插入操作Integer rows = cartMapper.insert(cart);if(rows != 1){throw new InsertException("插入数据时产生未知的异常");}}else{ //表示当前商品已经存在于购物车中,则更新这条数据的num值Integer num = result.getNum()+amount;Integer cid = result.getCid();Integer rows = cartMapper.updateNumByCid(cid,num,username,date);if(rows != 1){throw new UpdateException("更新时产生未知的异常");}}}
}
2. 再创建对应的测试类CartServiceTests。
@SpringBootTest
public class CartServiceTests {@Autowiredprivate ICartService cartService;@Testpublic void addToCart(){cartService.addToCart(6,10000013,2,"北伐不成功不改名");}
}
🚀5.加入购物车-控制层
1.没有需要处理的异常。
✨5.2设计请求
请求路径:/carts/add_to_cart
请求方式:POST
请求数据:Integer pid,Integer amount,HttpSession session
响应结果:JsonResult<Void>
✨5.3处理请求
1.创建一个CartController类,具体代码如下:
@RequestMapping("carts")
@RestController
public class CartController extends BaseController{@Autowiredprivate ICartService cartService;@RequestMapping("add_to_cart")public JsonResult<Void> addToCart(Integer pid, Integer amount, HttpSession session){cartService.addToCart(getuidFromSession(session),pid,amount,getUsernameFromSession(session));return new JsonResult<>(OK);}
}
2.登录后访问:http://localhost:8080/carts/add_to_cart?pid=10000003&amount=1
🚀6.加入购物车-前端页面
在product.html页面给【加入购物车】按钮添加点击事件,并发送ajax请求。
$("#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("加入购物车失败");}},error:function (xhr){alert("加入购物车时产生未知的异常"+xhr.message);}});});
在ajax函数中data参数的数据设置的方式:
- data:$("form表单选择").serialize()。适合要么就是可以全部选择的,或者手动输入的串的类型。当参数过多并且在同一个字符串中。
- data:new FormData($("form表单选择")[0])。只适用提交文件,其他形式提交不了。
- data:"username=Tom"。适合参数值固定并且参数值列表有限,可以进行手动拼接。
let user = "tom"; data:"username="+user
- 适用JSON格式提交数据:
data:{"username":"tom","age":18,"sex":0 }
🎯1.显示购物车列表- 持久层
✨1.1规划SQL语句
分析上图可知,红线框住的图片和商品标题来自于product表,而蓝线框住的应该属于 cart表,单价和数量应该是从购物车中传过来的,再根据两者计算总金额。由于数据来自于两张表中的部分字段,所以要用到关联查询。
#多表查询如果字段不重复则不需要显式声明字段属于哪张表
select cid,uid,pid,t_cart.price,t_cart.num,t_product.image,t_product.title,t_product.price as real
from t_cart left join t_product on t_cart.pid=t_product.id
where uid=#{uid}
order by t_cart.createdTime DESC;
✨1.2构建VO类
VO:Value Object,值对象。当进行select查询时,查询的结果属于多张表中的内容,此时发现结果集不能直接使用某个POJO实体类来接收,POJO实体类不能包含多表查询出来的结果。解决方案:重新构建一个新的对象,这个对象用于存储所查询出来的结果集对应的映射,所以把这样的对象称之为值对象。
在com.cy.store下新建一个包VO,在VO包里创建CartVO类。
//购物车数据的VO类(Value Object)值对象
public class CartVO implements Serializable {private Integer cid;private Integer uid;private Integer pid;private Long price;private Integer num;private String title;private String image;private Long realPrice;
......
}
✨1.3设计接口和抽象方法
在CartMapper中编写如下代码:
List<CartVO> findVOByUid(Integer uid);
✨1.4配置SQL映射
<select id="findVOByUid" resultType="com.cy.store.Vo.CartVO">select cid,uid,pid,t_cart.price,t_cart.num,t_product.image,t_product.title,t_product.price as realPricefrom t_cart left join t_product on t_cart.pid=t_product.idwhere uid=#{uid}order by t_cart.createdTime DESC</select>
单元测试
@Testpublic void findVOByUid(){System.out.println(cartMapper.findVOByUid(6));}
🎯2.显示购物车列表- 业务层
1.先编写业务层的接口方法。
List<CartVO> getVOByUid(Integer uid);
2.在实现类中实现方法。
@Overridepublic List<CartVO> getVOByUid(Integer uid) {List<CartVO> list = cartMapper.findVOByUid(uid);return list;}
🎯3.显示购物车列表- 控制层
✨3.1设计请求
请求路径:/carts/(只要发一个carts就可以把列表返回,不需要carts下的什么)
请求方式:GET
请求数据:HttpSession session
响应结果:JsonResult<List<CartVO>>
✨3.2处理请求
1.实现请求处理方法的代码编写。
@RequestMapping({"/",""})public JsonResult<List<CartVO>> getVOByUid(HttpSession session){List<CartVO> data = cartService.getVOByUid(getuidFromSession(session));return new JsonResult<>(OK,data);}
2.先登录再进行功能测试,访问http://localhost:8080/carts。
🎯4.显示购物车列表- 前端页面
要把cart.html页面通过向Controller层中的getVOByUid方法发送请求就可以返回所有的数据。
1.先注释掉以下代码:
<script src="../js/cart.js" type="text/javascript" charset="utf-8"></script>
2.用户一打开页面就自动发送请求,请求数据。读取form表单,对它的结构做一个了解,因为要把数据显示在form表单中。
- action="orderConfirm.html"
- tbody标签的id="cart-list"属性,自动加载的内容需要体现在tbody中。
- type="button":结算按钮的submit改成button,后续需要传数据。
3.ready()函数来完成自动的ajax请求的提交和处理。
<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 (var i = 0; i < list.length; i++) {//用户所拿到的是一个list集合,在这个list集合中封装的是cartVO对象,在这里先拿到这个list集合let tr = '<tr>\n' +'<td>\n' + //在这里给复选框一个cid值,在往后点击结算的时候会把这个cid值传递给下个页面//把这个数据提交给另一个页面是以参数的形式提交,所以这个表单一定要有内部属性'<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" οnclick="reduceNum(1)" />\n' +'<input id="goodsCount#{cid}" type="text" size="2" readonly="readonly" class="num-text" value="#{num}">\n' +'<input class="num-btn" type="button" value="+" οnclick="addNum(#{cid})" />\n' +'</td>\n' +'<td><span id="goodsCast#{cid}">#{totalPrice}</span></td>\n' +'<td>\n' +'<input type="button" οnclick="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);}});}</script>
🎃1. 增加购物车商品数量-持久层
✨1.1规划需要执行的SQL语句
1.执行更新t_cart表记录的num的值,无需重复开发。
update t_cart set num=#{num},modified_time={modifiedTime},modified_user=#{modifiedUser} where cid=#{cid}
2.根据cid查询购物车的这条记录是否存在。
select * from t_cart where cid=?
✨1.2设计接口和抽象方法
Cart findByCid(Integer cid);
✨1.3配置SQL映射
<select id="findByCid" resultMap="CartEntityMap">select * from t_cart where cid=#{cid}</select>
编写单元测试。
@Testpublic void findByCid(){System.out.println(cartMapper.findByCid(2));}
🎃 2.增加购物车商品数量-业务层
✨2.1规划异常
1.在更新时会产生更新异常。
2.查询到的数据是否有访问权限。
3.查询的数据不存在,抛出:CartNotFoundException异常。
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 * @param uid* @param username * @return 增加成功后新的数量*/Integer addNum(Integer cid,Integer uid,String username);
✨ 2.3实现方法
@Overridepublic Integer addNum(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.增加购物车商品数量-控制层
✨3.1处理异常
else if(e instanceof CartNotFoundException) {result.setState(4007);result.setMessage("购物车数据不存在的异常");}
✨3.2设计请求
请求路径:/carts/{cid}/num/add
请求方式:POST
请求数据:Integer cid,HttpSession session
响应结果:JsonResult<Integer>
✨3.3处理请求
@RequestMapping("{cid}/num/add")public JsonResult<Integer> addNum(Integer cid,HttpSession session){Integer data = cartService.addNum(cid,getuidFromSession(session),getUsernameFromSession(session));return new JsonResult<>(OK,data);}
先登录在访问url地址对应的地址。
🎃 4.增加购物车商品数量-前端页面
1.前面已经在onclick中改过里面的内容,所以无需重复修改了,但是需要重新编写addNum()以确保点击后能够增加数量。
<input class="num-btn" type="button" value="+" οnclick="addNum(#{cid})" />
function addNum(cid){$.ajax({url: "/carts/"+cid+"/num/add",type: "POST",dataType: "JSON",success: function (json) {if (json.state == 200) {//先拿到数量展示的id,$("#goodsCount"+cid).val(json.data)//由于price的值不是放在val控件上,也不是放在某一个属性上,通过html来拿,//html就是拿到它标签内部的这个东西,如果内部是个串拿到的就是个串//获取某个标签内部的内容:文本、标签//因为刚好这个内容即:singlePrice作为一个子内容放在了开始和结束的中间let price = $("#goodsPrice"+cid).html();let totalPrice = price * json.data;$("#goodsCast"+cid).html(totalPrice);} else {alert("增加购物车商品数量失败")}},error: function (xhr) {alert("增加购物车商品数量时产生未知的异常!"+xhr.message);}});}
相关文章:

【基于SprintBoot+Mybatis+Mysql】电脑商城项目之加入购物车和显示购物车列表
🧸安清h:个人主页 🎥个人专栏:【Spring篇】【计算机网络】【Mybatis篇】 🚦作者简介:一个有趣爱睡觉的intp,期待和更多人分享自己所学知识的真诚大学生。 目录 🚀1.加入购物车-数…...

再谈影刀RPA成长学习路线
近期,我将使用影刀RPA开发各电商平台移动端商品信息爬取,实战流程会在QQ群里分享,欢迎大家进群,一起探讨交流! 1. 影刀RPA学习路线概述 1.1 学习目标与意义 学习影刀RPA的目标在于掌握一种高效的工作自动化工具,以提…...

PHP-综合4
[题目信息]: 题目名称题目难度PHP-综合42 [题目考点]: PHP综合训练[Flag格式]: SangFor{Ouk3i63BuShgxqdRcn_9kMNqKFDe5j4f}[环境部署]: docker-compose.yml文件或者docker tar原始文件。 http://分配ip:2087[题目writeup]:…...
学习笔记-沁恒第五讲-米醋
一,设置音量 上次 这次 #include "uart.h" #include "debug.h" void audio_init() { Usart3_Init(); } void audio_play(u8 num) { u8 string[]{0x7e,0x05,0x41,0x00,num,0x05^0x41^0x00^num,0xef}; u8 i; for(i0;i<7;i) { USART_Se…...
【JavaScript】JavaScript 常见概念 - 变量与数据类型 - 运算符 - 条件语句 - 循环 - 函数 - 数组操作 - 对象
1. 变量与数据类型 变量声明 JavaScript 提供了三种方式来声明变量: var(全局或函数作用域,不推荐)let(块级作用域,推荐)const(常量,块级作用域,推荐&…...

Web自动化之Selenium添加网站Cookies实现免登录
在使用Selenium进行Web自动化时,添加网站Cookies是实现免登录的一种高效方法。通过模拟浏览器行为,我们可以将已登录状态的Cookies存储起来,并在下次自动化测试或爬虫任务中直接加载这些Cookies,从而跳过登录步骤。 Cookies简介 …...
AI手机的技术细节
前序:先说各个功能涉及到的技术,再说宏观系统架构。AI手机有这样几个做法,给手机侧边增加一个按键;把手机的语音助手做的很好,能够快速稳定的进行唤醒;通过特殊形式的触摸手机的曲面屏位置等来进行唤醒AI …...
10. 九转金丹炼矩阵 - 矩阵置零(标记优化)
哪吒在数据修仙界中继续他的修炼之旅。这一次,他来到了一片神秘的金丹谷,谷中有一座巨大的九转金丹炉,炉身闪烁着神秘的光芒。金丹炉的入口处有一块巨大的石碑,上面刻着一行文字:“欲破此炉,需以九转金丹之力,炼矩阵之零,标记优化定乾坤。” 哪吒定睛一看,石碑上还有…...

[实现Rpc] 客户端 | Requestor | RpcCaller的设计实现
目录 Requestor类的实现 框架 完善 onResponse处理回复 完整代码 RpcCaller类的实现 1. 同步调用 call 2. 异步调用 call 3. 回调调用 call Requestor类的实现 (1)主要功能: 客户端发送请求的功能,进行请求描述对服务器…...

Java 大视界 -- 深度洞察 Java 大数据安全多方计算的前沿趋势与应用革新(52)
💖💖💖亲爱的朋友们,热烈欢迎你们来到 青云交的博客!能与你们在此邂逅,我满心欢喜,深感无比荣幸。在这个瞬息万变的时代,我们每个人都在苦苦追寻一处能让心灵安然栖息的港湾。而 我的…...

山东大学软件学院nosql实验三
实验题目: 用Java做简单查询(2学时) 实验内容 用API方式,做简单查询。 实验要求 在以下要求中选择至少2个,使用Java语言实现数据查询,最终把数据输出到前端界面。 (1)找出年龄小于20岁的所有学生 &…...
正态分布的奇妙性质:为什么奇数阶中心矩(odd central moments)为零?
正态分布的奇妙性质:为什么奇数阶矩为零? 正态分布(Normal Distribution)是统计学中最常见的分布之一,它的钟形曲线几乎无处不在,从身高体重到测量误差,都能看到它的影子。除了均值和方差这两个…...

【入门音视频】音视频基础知识
🌈前言🌈 这个系列在我学习过程中,对音视频知识归纳总结的笔记。因为音视频相关讲解非常稀少,所以我希望通过这个音视频系列,跟大家一起学习音视频,希望减少初学者在学习上的压力。同时希望也欢迎指出文章的…...

游戏引擎学习第120天
仓库:https://gitee.com/mrxiao_com/2d_game_3 上次回顾:周期计数代码 我们正在进行一个项目的代码优化工作,目标是提高性能。当前正在优化某个特定的代码片段,已经将其执行周期减少到48个周期。为了实现这一目标,我们设计了一个…...

【Qt之QQuickWidget】QML嵌入QWidget中
由于我项目开始使用Widgets,换公司后直接使用QML开发,没有了解过如何实现widget到qml过渡,恰逢面试时遇到一家公司希望从widget迁移到qml开发,询问相关实现,一时语塞,很尴尬,粗略研究并总结下。 对qwidget嵌…...
Vue 3 + Vite 项目中配置代理解决开发环境中跨域请求问题
在 Vue 3 Vite 项目中,配置代理是解决开发环境中跨域请求问题的常见方法。通过在 Vite 的配置文件中设置代理,可以将前端请求转发到后端服务器,从而避免浏览器的同源策略限制。 1. 创建 Vue 3 Vite 项目 首先,确保你已经安装了…...
Eureka、ZooKeeper 和 Nacos 之间的对比
Eureka、ZooKeeper 和 Nacos 都是分布式系统中常用的服务注册与发现工具,但它们的定位、功能和适用场景有所不同。作为一名开发者,理解它们之间的对比有助于选择合适的技术栈。以下从多个维度进行详细比较: 1. 基本概述 Eureka 来源ÿ…...
CSS中padding和margin属性的使用
在 HTML 中,padding 和 margin 是用于控制元素布局和间距的重要属性。 一、Padding(内边距) 定义:Padding 是指元素内容与元素边框之间的距离。它可以在元素内部创造出空白区域,使得内容不会紧贴着边框。 作用 增加元…...
【Python爬虫(49)】分布式爬虫:在新兴技术浪潮下的蜕变与展望
【Python爬虫】专栏简介:本专栏是 Python 爬虫领域的集大成之作,共 100 章节。从 Python 基础语法、爬虫入门知识讲起,深入探讨反爬虫、多线程、分布式等进阶技术。以大量实例为支撑,覆盖网页、图片、音频等各类数据爬取ÿ…...
网络安全-系统层攻击流程及防御措施
系统层攻击流程涉及多个阶段,攻击者通过逐步渗透以获取控制权或窃取数据。以下是详细的流程及防御措施: 1. 侦察(Reconnaissance) 信息收集: 主动扫描:使用工具如Nmap、Masscan扫描目标IP、开放端口、服务…...

VB.net复制Ntag213卡写入UID
本示例使用的发卡器:https://item.taobao.com/item.htm?ftt&id615391857885 一、读取旧Ntag卡的UID和数据 Private Sub Button15_Click(sender As Object, e As EventArgs) Handles Button15.Click轻松读卡技术支持:网站:Dim i, j As IntegerDim cardidhex, …...

智慧工地云平台源码,基于微服务架构+Java+Spring Cloud +UniApp +MySql
智慧工地管理云平台系统,智慧工地全套源码,java版智慧工地源码,支持PC端、大屏端、移动端。 智慧工地聚焦建筑行业的市场需求,提供“平台网络终端”的整体解决方案,提供劳务管理、视频管理、智能监测、绿色施工、安全管…...

基于Docker Compose部署Java微服务项目
一. 创建根项目 根项目(父项目)主要用于依赖管理 一些需要注意的点: 打包方式需要为 pom<modules>里需要注册子模块不要引入maven的打包插件,否则打包时会出问题 <?xml version"1.0" encoding"UTF-8…...

在WSL2的Ubuntu镜像中安装Docker
Docker官网链接: https://docs.docker.com/engine/install/ubuntu/ 1、运行以下命令卸载所有冲突的软件包: for pkg in docker.io docker-doc docker-compose docker-compose-v2 podman-docker containerd runc; do sudo apt-get remove $pkg; done2、设置Docker…...

【笔记】WSL 中 Rust 安装与测试完整记录
#工作记录 WSL 中 Rust 安装与测试完整记录 1. 运行环境 系统:Ubuntu 24.04 LTS (WSL2)架构:x86_64 (GNU/Linux)Rust 版本:rustc 1.87.0 (2025-05-09)Cargo 版本:cargo 1.87.0 (2025-05-06) 2. 安装 Rust 2.1 使用 Rust 官方安…...
作为测试我们应该关注redis哪些方面
1、功能测试 数据结构操作:验证字符串、列表、哈希、集合和有序的基本操作是否正确 持久化:测试aof和aof持久化机制,确保数据在开启后正确恢复。 事务:检查事务的原子性和回滚机制。 发布订阅:确保消息正确传递。 2、性…...

Proxmox Mail Gateway安装指南:从零开始配置高效邮件过滤系统
💝💝💝欢迎莅临我的博客,很高兴能够在这里和您见面!希望您在这里可以感受到一份轻松愉快的氛围,不仅可以获得有趣的内容和知识,也可以畅所欲言、分享您的想法和见解。 推荐:「storms…...

Spring AOP代理对象生成原理
代理对象生成的关键类是【AnnotationAwareAspectJAutoProxyCreator】,这个类继承了【BeanPostProcessor】是一个后置处理器 在bean对象生命周期中初始化时执行【org.springframework.beans.factory.config.BeanPostProcessor#postProcessAfterInitialization】方法时…...

相关类相关的可视化图像总结
目录 一、散点图 二、气泡图 三、相关图 四、热力图 五、二维密度图 六、多模态二维密度图 七、雷达图 八、桑基图 九、总结 一、散点图 特点 通过点的位置展示两个连续变量之间的关系,可直观判断线性相关、非线性相关或无相关关系,点的分布密…...

高端性能封装正在突破性能壁垒,其芯片集成技术助力人工智能革命。
2024 年,高端封装市场规模为 80 亿美元,预计到 2030 年将超过 280 亿美元,2024-2030 年复合年增长率为 23%。 细分到各个终端市场,最大的高端性能封装市场是“电信和基础设施”,2024 年该市场创造了超过 67% 的收入。…...