亿级高并发电商项目-- 实战篇 --万达商城项目 十三(编写购物车、优化修改商品、下架商品方法、购物车模块监听修改商品、删除商品消息)
👏作者简介:大家好,我是小童,Java开发工程师,CSDN博客博主,Java领域新星创作者
📕系列专栏:前端、Java、Java中间件大全、微信小程序、微信支付、若依框架、Spring全家桶
📧如果文章知识点有错误的地方,请指正!和大家一起学习,一起进步👀
🔥如果感觉博主的文章还不错的话,请👍三连支持👍一下博主哦
🍂博主正在努力完成2023计划中:以梦为马,扬帆起航,2023追梦人
专栏:高并发项目
编写购物车服务接口
用户购买商品的流程为: 搜索商品 > 查看商品详情 > 添加到购物车 > 生成商品订单 > 支 付 ,搜索商品和查看商品详情功能已经完成,接下来我们编写购物 车服务。购物车数据属于临时数据,为了节约数据库开销,我们会 将其存放到redis中。
在通用模块编写购物车服务接口:
// 购物车服务
public interface CartService {// 新增商品到购物车void addCart(Long userId, CartGoods cartGoods);// 修改购物车商品数量void handleCart(Long userId, Long goodId, Integer num);// 删除购物车商品void deleteCartOption(Long userId, Long goodId);// 获取用户购物车List<CartGoods> findCartList(Long userId);// 更新redis中的商品数据,在管理员更新商品后执行void refreshCartGoods(CartGoods cartGoods);// 删除redis中的商品数据,在管理员下架商品后执行void deleteCartGoods(CartGoods cartGoods);
}
创建购物车服务模块
1、创建名为 shopping_cart_service 的SpringBoot工程,添加相关依赖。
<dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter</artifactId></dependency><dependency><groupId>com.itbaizhan</groupId><artifactId>shopping_common</artifactId><version>0.0.1-SNAPSHOT</version></dependency><!-- dubbo --><dependency><groupId>org.apache.dubbo</groupId><artifactId>dubbo-spring-boot-starter</artifactId><version>2.7.8</version></dependency><!-- 操作zookeeper --><dependency><groupId>org.apache.curator</groupId><artifactId>curator-recipes</artifactId><version>4.2.0</version></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency><!-- redis --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId></dependency>
</dependencies>
2、设置该工程的父工程为 shopping 。
<parent><groupId>com.ittxc</groupId><artifactId>shopping</artifactId><version>1.0-SNAPSHOT</version>
</parent>
3、给 shopping 工程设置子模块
<!-- 子模块 -->
<modules><!-- 购物车服务 --><module>shopping_cart_service</module>
</modules>
4、编写配置文件 application.yml
# 端口号
server:port: 9009
# 日志格式
logging:pattern:console: '%d{HH:mm:ss.SSS} %clr(%-5level) --- [%-15thread] %cyan(%-50logger{50}):%msg%n'
spring:# redisredis:host: 192.168.0.159port: 6379timeout: 30000jedis:pool:max-active: 8max-wait: -1max-idle: 8min-idle: 0
dubbo:application:name: shopping_cart_service # 项目名registry:address: zookeeper://192.168.0.159 #注册中心地址port: 2181 # 注册中心的端口timeout: 10000 # 注册到zk上超时时间,msprotocol:name: dubbo # dubbo使用的协议port: -1 # dubbo自动分配端口scan:base-packages: com.itbaizhan.shopping_cart_service.service # 包扫描
5、启动类忽略数据源自动配置
@SpringBootApplication(exclude= {DataSourceAutoConfiguration.class})
public class ShoppingCartServiceApplication {public static void main(String[] args)
{SpringApplication.run(ShoppingCartServiceApplication.class, args);}
}
创建购物车Api模块
1、创建名为 shopping_cart_customer_api 的SpringBoot工程,添加相关依赖。
<dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><!-- dubbo --><dependency><groupId>org.apache.dubbo</groupId><artifactId>dubbo-spring-boot-starter</artifactId><version>2.7.8</version></dependency><!-- 操作zookeeper --><dependency><groupId>org.apache.curator</groupId><artifactId>curator-recipes</artifactId><version>4.2.0</version></dependency><dependency><groupId>com.itbaizhan</groupId><artifactId>shopping_common</artifactId><version>0.0.1-SNAPSHOT</version></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-startertest</artifactId><scope>test</scope></dependency>
</dependencies>
2、设置该工程的父工程为 shopping 。
<parent><groupId>com.ittxc</groupId><artifactId>shopping</artifactId><version>1.0-SNAPSHOT</version>
</parent>
3、给 shopping 工程设置子模块
<!-- 子模块 -->
<modules><!-- 购物车api --><module>shopping_cart_customer_api</module>
</modules>
4、编写配置文件 application.yml
# 端口号
server:port: 8005
# 日志格式
logging:pattern:console: '%d{HH:mm:ss.SSS} %clr(%-5level) --- [%-15thread] %cyan(%-50logger{50}):%msg%n'
dubbo:application:name: shopping_cart_customer_api # 项目名registry:address: zookeeper://192.168.0.159 #注册中心地址port: 2181 # 注册中心的端口timeout: 10000 # 注册到zk上超时时间,msprotocol:name: dubbo # dubbo使用的协议port: -1 # dubbo自动分配端口
5、启动类忽略数据源自动配置
@SpringBootApplication(exclude= {DataSourceAutoConfiguration.class})
public class ShoppingUserCustomerApiApplication {public static void main(String[] args)
{SpringApplication.run(ShoppingUserCustomerApiApplication.class, args);}
}
编写查询用户购物车功能
我们将用户的购物车信息保存到redis当中,所有用户的购物车作为 一个hash类型的数据保存,hash的键是用户id,hash的值是购物车商品列表。
在购物车服务模块创建购物车服务接口的实现类,重写查询用户购物车功能
@DubboService
public class CartServiceImpl implements CartService {@Autowiredprivate RedisTemplate redisTemplate;@Overridepublic List<CartGoods> findCartList(Long userId) {Object cartList = redisTemplate.boundHashOps("cartList").get(userId);if (cartList == null) {return new ArrayList<CartGoods>();} else {return (List<CartGoods>)cartList;}}
}
编写添加商品到购物车方法
@Override
public void addCart(Long userId, CartGoods cartGoods) {// 1.根据用户id获取用户购物车列表List<CartGoods> cartList = findCartList(userId);// 2.查询购物车是否有该商品,如果有商品,添加商品数量for (CartGoods cartGoods1 : cartList) {if(cartGoods.getGoodId().equals(cartGoods1.getGoodId())){int newNum = cartGoods1.getNum() + cartGoods.getNum();cartGoods1.setNum(newNum);redisTemplate.boundHashOps("cartList").put(userId,cartList);return;}}// 3.如果购物车没有该商品,将商品添加到购物车列表cartList.add(cartGoods);redisTemplate.boundHashOps("cartList").put(userId,cartList);
}
编写修改购物车商品数量方法
@Override
public void handleCart(Long userId, Long goodId, Integer num) {// 获取用户购物车列表List<CartGoods> cartList = findCartList(userId);// 遍历列表找到对应商品for (CartGoods cartGoods : cartList) {if(goodId.equals(cartGoods.getGoodId())) {// 改变商品数量cartGoods.setNum(num);break;}}// 将新的购物车列表保存到redis中redisTemplate.boundHashOps("cartList").put(userId, cartList);
}
编写删除购物车商品方法
@Override
public void deleteCartOption(Long userId,Long goodId) {// 获取用户购物车列表List<CartGoods> cartList = findCartList(userId);// 将商品移出列表for (CartGoods cartGoods : cartList) {if (goodId.equals(cartGoods.getGoodId())) {cartList.remove(cartGoods);break;}}// 将新的购物车列表保存到redis中redisTemplate.boundHashOps("cartList").put(userId, cartList);
}
编写购物车控制器
在进行购物车操作之前,要先获取用户的Id,而用户的令牌中只保存了用户名,所以我们要修改JWT工具类,让令牌中也保存用户的 Id:
1、修改JWT工具类
public class JWTUtil {//token过期时间,一天private static final Long EXPIRE_DATE = 1000*60*60*24L;// 秘钥private static final String SECRET = "xiaotong";// 签发者private static final String ISSUER = "XIAOTONG";/*** 签名生成* @param shoppingUser* @return*/public static String sign(ShoppingUser shoppingUser){String token = JWT.create().withIssuer(ISSUER) // 签发者.withIssuedAt(new Date())// 签发时间.withExpiresAt(new Date(new Date().getTime() + EXPIRE_DATE))// 过期时间.withSubject(shoppingUser.getUsername())// 保存用户名.withClaim("userId",shoppingUser.getId())// 保存用户id.sign(Algorithm.HMAC256(SECRET)); // 秘钥return token;}/*** 签名解析* @param token 签名字符串* @return 解析得出的用户名*/public static String verify(String token){try {String username = JWT.require(Algorithm.HMAC256(SECRET)).withIssuer(ISSUER).build().verify(token).getSubject();return username;} catch (Exception e){throw new BusException(CodeEnum.VERIFY_TOKEN_ERROR);}}/*** 签名解析,获取用户id* @param token 签名字符串* @return 用户id*/public static Long getId(String token){try {Long userId = JWT.require(Algorithm.HMAC256(SECRET)).withIssuer(ISSUER).build().verify(token).getClaim("userId").asLong();return userId;} catch (Exception e){throw new BusException(CodeEnum.VERIFY_TOKEN_ERROR);}}
}
2、在购物车Api模块编写购物车控制器
/**
* 购物车
*/
@RestController
@RequestMapping("/user/cart")
public class CartController {@DubboReferenceprivate CartService cartService;/*** 查询用户购物车* @param token 用户令牌* @return 用户购物车列表*/@GetMapping("/findCartList")public BaseResult<List<CartGoods>> findCartList(@RequestHeader String token){Long userId = JWTUtil.getId(token); // 获取用户idList<CartGoods> cartList = cartService.findCartList(userId);return BaseResult.ok(cartList);}/*** 新增商品到购物车* @param cartGoods 购物车商品* @param token 用户令牌* @return 操作结果*/@PostMapping("/addCart")public BaseResult addCart(@RequestBody CartGoods cartGoods,@RequestHeader String token){Long userId = JWTUtil.getId(token); // 获取用户idcartService.addCart(userId,cartGoods);return BaseResult.ok();}/*** 修改购物车商品数量* @param token 用户令牌* @param goodId 商品id* @param num 修改后的数量* @return 操作结果*/@GetMapping("/handleCart")public BaseResult addCart(@RequestHeader String token,Long goodId,Integer num){Long userId = JWTUtil.getId(token); // 获取用户idcartService.handleCart(userId,goodId,num);return BaseResult.ok();}/*** 删除购物车商品* @param token 用户令牌* @param goodId 商品id* @return 操作结果*/@DeleteMapping("/deleteCart")public BaseResult addCart(@RequestHeader String token,Long goodId){Long userId = JWTUtil.getId(token); // 获取用户idcartService.deleteCartOption(userId,goodId);return BaseResult.ok();}
}
编写修改所有用户购物车商品方法
当管理员修改了商品的价格等数据后,需要将数据同步到用户购物车中,所以我们要编写给所有用户的购物车中修改某件商品的方法。
@Override
public void refreshCartGoods(CartGoods
cartGoods) {// 获取所有用户购物车商品BoundHashOperations cartList = redisTemplate.boundHashOps("cartList");Map<Long,List<CartGoods>> allCartGoods = cartList.entries();Set<Map.Entry<Long, List<CartGoods>>> entries = allCartGoods.entrySet();// 遍历所有用户的购物车for (Map.Entry<Long, List<CartGoods>> entry : entries) {List<CartGoods> goodsList = entry.getValue();// 遍历一个用户购物车的所有商品for (CartGoods goods : goodsList) {// 如果该商品是被更新的商品,修改商品数据if(cartGoods.getGoodId().equals(goods.getGoodId())){goods.setGoodsName(cartGoods.getGoodsName());goods.setHeaderPic(cartGoods.getHeaderPic());goods.setPrice(cartGoods.getPrice());}}}// 将改变后所有用户购物车重新放入redisredisTemplate.delete("cartList");redisTemplate.boundHashOps("cartList").putAll(allCartGoods);
}
编写删除所有用户购物车商品方法
当管理员下架某件商品后,所有用户的购物车中该商品也应该被删除,所以我们要编写给所有用户的购物车中删除某件商品的方法。
@Override
public void deleteCartGoods(CartGoods cartGoods) {BoundHashOperations cartList = redisTemplate.boundHashOps("cartList");// 所有用户的购物车Map<String,List<CartGoods>> allCartGoods = cartList.entries();Set<Map.Entry<String, List<CartGoods>>> entries = allCartGoods.entrySet();// 遍历所有用户的购物车for (Map.Entry<String, List<CartGoods>> entry : entries) {List<CartGoods> goodsList = entry.getValue();// 遍历一个用户购物车的所有商品for (CartGoods goods : goodsList) {// 如果该商品是被删除的商品if (cartGoods.getGoodId().equals(goods.getGoodId())){goodsList.remove(goods);break;}}}// 将改变后的map重新放入redisredisTemplate.delete("cartList");redisTemplate.boundHashOps("cartList").putAll(allCartGoods);
}
优化修改商品、下架商品方法
接下来我们修改商品服务模块代码,在修改商品后发送消息同步修 改购物车数据;在下架商品后发送消息同步删除购物车数据:
1、在MQ配置文件创建队列,绑定队列到交换机:
@Configuration
public class RabbitConfig {// 交换机private final String GOODS_EXCHANGE = "goods_exchange";// 同步商品数据队列private final String SYNC_GOODS_QUEUE = "sync_goods_queue";// 删除商品数据队列private final String DEL_GOODS_QUEUE = "del_goods_queue";// 向购物车同步商品队列private final String SYNC_CART_QUEUE = "sync_cart_queue";// 向购物车删除商品队列private final String DEL_CART_QUEUE = "del_cart_queue";// 创建交换机@Bean(GOODS_EXCHANGE)public Exchange getExchange() {return ExchangeBuilder.topicExchange(GOODS_EXCHANGE) // 交换机类型.durable(true) // 是否持久化.build();}// 创建队列@Bean(SYNC_GOODS_QUEUE)public Queue getQueue1() {return new Queue(SYNC_GOODS_QUEUE); // 队列名}@Bean(DEL_GOODS_QUEUE)public Queue getQueue2() {return new Queue(DEL_GOODS_QUEUE);// 队列名}@Bean(SYNC_CART_QUEUE)public Queue getQueue3() {return new Queue(SYNC_CART_QUEUE);// 队列名}@Bean(DEL_CART_QUEUE)public Queue getQueue4() {return new Queue(DEL_CART_QUEUE);
// 队列名}// 交换机绑定队列@Beanpublic Binding bindQueue1(@Qualifier(GOODS_EXCHANGE) Exchange exchange,@Qualifier(SYNC_GOODS_QUEUE) Queue queue){return BindingBuilder.bind(queue).to(exchange).with("#.sync_goods.#").noargs();}@Beanpublic Binding bindQueue2(@Qualifier(GOODS_EXCHANGE) Exchange exchange,@Qualifier(DEL_GOODS_QUEUE) Queue queue) {return BindingBuilder.bind(queue).to(exchange).with("#.del_goods.#").noargs();}@Beanpublic Binding
bindQueue3(@Qualifier(GOODS_EXCHANGE)
Exchange exchange,@Qualifier(SYNC_CART_QUEUE) Queue queue)
{return BindingBuilder.bind(queue).to(exchange).with("#.sync_cart.#").noargs();}@Beanpublic Binding bindQueue4(@Qualifier(GOODS_EXCHANGE) Exchange exchange,@Qualifier(DEL_CART_QUEUE) Queue queue) {return BindingBuilder.bind(queue).to(exchange).with("#.del_cart.#").noargs();}
}
@DubboService
public class GoodsServiceImpl implements
GoodsService {@Autowiredprivate GoodsMapper goodsMapper;@Autowiredprivate GoodsImageMapper goodsImageMapper;@Autowiredprivate RabbitTemplate rabbitTemplate;@Overridepublic void update(Goods goods) {// 删除旧图片数据Long goodsId = goods.getId(); //商品idQueryWrapper<GoodsImage> queryWrapper = new QueryWrapper();queryWrapper.eq("goodsId",goodsId);goodsImageMapper.delete(queryWrapper);// 删除旧规格项数据goodsMapper.deleteGoodsSpecificationOption(goodsId);// 插入商品数据goodsMapper.updateById(goods);// 插入图片数据List<GoodsImage> images = goods.getImages(); // 商品图片for (GoodsImage image : images) {image.setGoodsId(goodsId); // 给图片设置商品idgoodsImageMapper.insert(image); // 插入图片}// 插入商品_规格项数据List<Specification> specifications = goods.getSpecifications(); // 获取规格List<SpecificationOption> options = new ArrayList(); // 规格项集合// 遍历规格,获取规格中的所有规格项for (Specification specification : specifications) {options.addAll(specification.getSpecificationOptions());}// 遍历规格项,插入商品_规格项数据for (SpecificationOption option : options) {goodsMapper.addGoodsSpecificationOption(goodsId,option.getId());}rabbitTemplate.convertAndSend("goods_exchange","sync_goods",findById(goodsId));// 将商品修改数据同步到用户购物车CartGoods cartGoods = new CartGoods();cartGoods.setGoodId(goods.getId());cartGoods.setGoodsName(goods.getGoodsName());cartGoods.setHeaderPic(goods.getHeaderPic());cartGoods.setPrice(goods.getPrice());rabbitTemplate.convertAndSend("goods_exchange","sync_cart",cartGoods);}@Overridepublic void putAway(Long id, Boolean isMarketable) {goodsMapper.putAway(id,isMarketable);if (isMarketable){// 上架时同步到ESrabbitTemplate.convertAndSend("goods_exchange","sync_goods",findById(id));}else{// 下架删除ES数据rabbitTemplate.convertAndSend("goods_exchange","del_goods",id);// 商品下架删除用户购物车CartGoods cartGoods = new CartGoods();cartGoods.setGoodId(id);rabbitTemplate.convertAndSend("goods_exchange","del_cart",cartGoods);}}
}
购物车模块监听修改商品、删除商品消息
1、在购物车服务模块添加RabbitMQ依赖
<!-- RabbitMQ -->
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-amqp</artifactId>
</dependency>
2、添加RabbitMQ配置
spring:# redisredis:host: 192.168.0.159port: 6379timeout: 30000jedis:pool:max-active: 8max-wait: -1max-idle: 8min-idle: 0# rabbitmqrabbitmq:host: 192.168.0.159port: 5672username: guestpassword: guestvirtual-host: /
3、修改购物车服务接口实现类,监听队列
@DubboService
@Service
public class CartServiceImpl implements CartService {@Autowiredprivate RedisTemplate redisTemplate;// 监听修改购物车商品队列@RabbitListener(queues = "sync_cart_queue")public void listenSyncQueue(CartGoods cartGoods){refreshCartGoods(cartGoods);}// 监听删除购物车商品队列@RabbitListener(queues = "del_cart_queue")public void listenDelQueue(CartGoods cartGoods){deleteCartGoods(cartGoods);}
}
4、测试管理员修改商品、下架商品,看用户购物车是否发生改变。
相关文章:

亿级高并发电商项目-- 实战篇 --万达商城项目 十三(编写购物车、优化修改商品、下架商品方法、购物车模块监听修改商品、删除商品消息)
👏作者简介:大家好,我是小童,Java开发工程师,CSDN博客博主,Java领域新星创作者 📕系列专栏:前端、Java、Java中间件大全、微信小程序、微信支付、若依框架、Spring全家桶 Ǵ…...

springboot 虚拟线程demo
jd19支持虚拟线程,虚拟线程是轻量级的线程,它们不与操作系统线程绑定,而是由 JVM 来管理。它们适用于“每个请求一个线程”的编程风格,同时没有操作系统线程的限制。我们能够创建数以百万计的虚拟线程而不会影响吞吐。 做个 spri…...

CTFer成长之路之逻辑漏洞
逻辑漏洞CTF 访问url: http://1b43ac78-61f7-4b3c-9ab7-d7e131e7da80.node3.buuoj.cn/ 登录页面用随意用户名密码登录 访问url: http://1b43ac78-61f7-4b3c-9ab7-d7e131e7da80.node3.buuoj.cn/user.php 登陆后有商品列表,共三个商品,点击购买flag 钱…...
入门力扣自学笔记238 C++ (题目编号:1144)
1144. 递减元素使数组呈锯齿状 题目: 给你一个整数数组 nums,每次 操作 会从中选择一个元素并 将该元素的值减少 1。 如果符合下列情况之一,则数组 A 就是 锯齿数组: 每个偶数索引对应的元素都大于相邻的元素,即 A…...
蓝桥杯-寒假作业
没有白走的路,每一步都算数🎈🎈🎈 题目描述: 有四个等式,每个等式的运算规则已经定好了,也就是我们常见的小学的四则运算,但是能够用来四则运算的数字非常有限,包括1~13…...

测试用例篇
1.测试用例的意义 测试用例(Test Case)是为了实施测试而向被测试的系统提供的一组集合,这组集合包含:测试环境、操作步骤、测试数据、预期结果等要素。 测试用例的意义是为了帮助测试人员了解测什么,怎么测 eg&#x…...

自动驾驶自主避障概况
文章目录前言1. 自主避障在自动驾驶系统架构中的位置2. 自主避障算法分类2.1 人工势场法(APF)2.1.1引力势场的构建2.1.2斥力势场的构建2.1.3人工势场法的改进2.2 TEB(Timed-Eastic-Band, 定时弹性带)2.3 栅格法2.4 向量场直方图(V…...
Python实用的库排名…
Python 是一个功能强大的编程语言,有着丰富的第三方库和模块,可以帮助你解决各种各样的问题。以下是一些比较厉害的 Python 库: NumPy:一个强大的数值计算库,提供了高效的数组和矩阵操作功能。 Pandas:提供…...

【YOLO系列】YOLOv4论文超详细解读1(翻译 +学习笔记)
前言 经过上一期的开篇介绍,我们知道YOLO之父Redmon在twitter正式宣布退出cv界,大家都以为YOLO系列就此终结的时候,天空一声巨响,YOLOv4闪亮登场!v4作者是AlexeyAB大神,虽然换人了,但论文中给出…...

【神经网络】Transformer基础问答
1.Transforme与LSTM的区别 transformer和LSTM最大的区别就是LSTM的训练是迭代的,无法并行训练,LSTM单元计算完T时刻信息后,才会处理T1时刻的信息,T 1时刻的计算依赖 T-时刻的隐层计算结果。而transformer的训练是并行了࿰…...
制定防火墙策略的步骤和建议
制定防火墙策略是保护企业网络环境安全的关键一步。下面是一些制定防火墙策略的步骤和建议,供参考: 识别网络资产:确定企业网络环境中所有的网络资产,包括服务器、应用程序、数据库、移动设备和终端用户设备等,并进行…...

新必应(New Bing)国内申请与使用教程
微软的新必应(New Bing)基于GPT4模型,比ChatGPT的GPT3.5模型领先半个世代。并且集成了Edge浏览器的数据资源,功能更加强大。经过不断的踩坑,终于申请到了New Bing的使用权限,且国内网络也能够正常使用&…...

博客系统——项目测试报告
目录 前言 博客系统——项目介绍 1、测试计划 1.1、功能测试 1.1.1、编写测试用例 1.1.2、实际执行步骤 1.2、使用Selenium进行Web自动化测试 1.2.1、引入依赖 1.2.2、提取共性,实现代码复用 1.2.3、创建测试套件类 1.2.4、博客登录页自动化测试 1.2.5、…...

Macbook M1 安装PDI(Kettle) 9.3
Macbook M1 安装PDI(Kettle) 9.3 当前 PDI(Kettle)最新版为9.3,依赖Java JDK 11。因为没有专门用于 M1的程序,需要下载并安装x86_64架构的JDK及依赖软件,并 “强制在Intel模式下运行shell” 的方式来实现 Kettle 的正…...

机器学习——模型评估
在学习得到的模型投放使用之前,通常需要对其进行性能评估。为此,需使用一个“测试集”(testing set)来测试模型对新样本的泛化能力,然后以测试集上的“测试误差( tootino error)作为泛化误差的近似。我们假设测试集是从样本真实分…...

react react-redux学习记录
react react-redux学习记录1.原理2.怎么用呢2.1 容器组件2.2UI组件2.3 App.jsx3.简化3.1简写mapDispatch3.2 Provider组件的使用3.3整合UI组件和容器组件1.原理 UI组件:不能使用任何redux的api,只负责页面的呈现、交互等。 容器组件:负责和redux通信&…...

nodejs环境配置
啥是node.js 简单理解就是js运行环境 啥是npm 简单理解就是nodejs包管理工具,全称Node Package Manager 啥是cnpm npm的开源镜像,在国内使用cnpm替代npm可以起到加速的效果 https://npmmirror.com/ ①安装node.js https://nodejs.org/en/download/ 下载…...

数据治理之元数据管理Atlas
数据治理之元数据管理的利器——Atlas 一、数据治理与元数据管理 1.1 背景 为什么要做数据治理? 业务繁多,数据繁多,业务数据不断迭代。人员流动,文档不全,逻辑不清楚,对于数据很难直观理解,…...

15 Nacos客户端实例注册源码分析
Nacos客户端实例注册源码分析 实例客户端注册入口 流程图: 实际上我们在真实的生产环境中,我们要让某一个服务注册到Nacos中,我们首先要引入一个依赖: <dependency><groupId>com.alibaba.cloud</groupId>&l…...

C++将派生类赋值给基类(向上转型)
1.将派生类对象赋值给基类对象 #include <iostream> using namespace std;//基类 class A{ public:A(int a); public:void display(); public:int m_a; }; A::A(int a): m_a(a){ } void A::display(){cout<<"Class A: m_a"<<m_a<<endl; }//…...
QMC5883L的驱动
简介 本篇文章的代码已经上传到了github上面,开源代码 作为一个电子罗盘模块,我们可以通过I2C从中获取偏航角yaw,相对于六轴陀螺仪的yaw,qmc5883l几乎不会零飘并且成本较低。 参考资料 QMC5883L磁场传感器驱动 QMC5883L磁力计…...

基于uniapp+WebSocket实现聊天对话、消息监听、消息推送、聊天室等功能,多端兼容
基于 UniApp + WebSocket实现多端兼容的实时通讯系统,涵盖WebSocket连接建立、消息收发机制、多端兼容性配置、消息实时监听等功能,适配微信小程序、H5、Android、iOS等终端 目录 技术选型分析WebSocket协议优势UniApp跨平台特性WebSocket 基础实现连接管理消息收发连接…...

Nuxt.js 中的路由配置详解
Nuxt.js 通过其内置的路由系统简化了应用的路由配置,使得开发者可以轻松地管理页面导航和 URL 结构。路由配置主要涉及页面组件的组织、动态路由的设置以及路由元信息的配置。 自动路由生成 Nuxt.js 会根据 pages 目录下的文件结构自动生成路由配置。每个文件都会对…...

DBAPI如何优雅的获取单条数据
API如何优雅的获取单条数据 案例一 对于查询类API,查询的是单条数据,比如根据主键ID查询用户信息,sql如下: select id, name, age from user where id #{id}API默认返回的数据格式是多条的,如下: {&qu…...
鸿蒙DevEco Studio HarmonyOS 5跑酷小游戏实现指南
1. 项目概述 本跑酷小游戏基于鸿蒙HarmonyOS 5开发,使用DevEco Studio作为开发工具,采用Java语言实现,包含角色控制、障碍物生成和分数计算系统。 2. 项目结构 /src/main/java/com/example/runner/├── MainAbilitySlice.java // 主界…...
在web-view 加载的本地及远程HTML中调用uniapp的API及网页和vue页面是如何通讯的?
uni-app 中 Web-view 与 Vue 页面的通讯机制详解 一、Web-view 简介 Web-view 是 uni-app 提供的一个重要组件,用于在原生应用中加载 HTML 页面: 支持加载本地 HTML 文件支持加载远程 HTML 页面实现 Web 与原生的双向通讯可用于嵌入第三方网页或 H5 应…...

力扣热题100 k个一组反转链表题解
题目: 代码: func reverseKGroup(head *ListNode, k int) *ListNode {cur : headfor i : 0; i < k; i {if cur nil {return head}cur cur.Next}newHead : reverse(head, cur)head.Next reverseKGroup(cur, k)return newHead }func reverse(start, end *ListNode) *ListN…...

打手机检测算法AI智能分析网关V4守护公共/工业/医疗等多场景安全应用
一、方案背景 在现代生产与生活场景中,如工厂高危作业区、医院手术室、公共场景等,人员违规打手机的行为潜藏着巨大风险。传统依靠人工巡查的监管方式,存在效率低、覆盖面不足、判断主观性强等问题,难以满足对人员打手机行为精…...

TSN交换机正在重构工业网络,PROFINET和EtherCAT会被取代吗?
在工业自动化持续演进的今天,通信网络的角色正变得愈发关键。 2025年6月6日,为期三天的华南国际工业博览会在深圳国际会展中心(宝安)圆满落幕。作为国内工业通信领域的技术型企业,光路科技(Fiberroad&…...
「全栈技术解析」推客小程序系统开发:从架构设计到裂变增长的完整解决方案
在移动互联网营销竞争白热化的当下,推客小程序系统凭借其裂变传播、精准营销等特性,成为企业抢占市场的利器。本文将深度解析推客小程序系统开发的核心技术与实现路径,助力开发者打造具有市场竞争力的营销工具。 一、系统核心功能架构&…...