当前位置: 首页 > news >正文

最近在写的支付模块

最近再写支付模块就到处借鉴 旨在回顾一下。

1.确认订单功能

使用场景是:用户在选择好购物车后,或者是直接选择商品后(选择商品封装为购物车)

这样做是根据尚硅谷来学习的 目前需要这些属性,原因是在确认订单页面后 展现一个最优惠的状态 

1.1实体类

    /*** 用户id*/@ApiModelProperty("用户id")private Integer userId;/*** 购物车列表*/@ApiModelProperty("购物车中已选中商品")private List<CartInfo> cartItemsList;@ApiModelProperty("最优惠的优惠券id")private Integer userCouponsId;/*** 总金额*/@ApiModelProperty("总金额")private Double totalAmount;/*** 优惠金额*/@ApiModelProperty("优惠金额")private Double discount;/*** 实付金额*/@ApiModelProperty("实付金额")private Double actuallyPay;

1.2确认订单实现类

期间做了一些修改 之前是设置的有购物车状态 这些步骤都是在后端处理 

后来又采用了前端传递购物车属性 美其名曰叫 减少io次数 缓解数据库压力

通过传入的userId 查找 订单列表 购物车列表

期间有个redis操作 是根据时间 来生成 后续在生成订单时会用到

 public OrderConfirmVo confirmOrder(CartConfirmDto cartConfirmDto) {//获取用户id参数 以方便后续使用//获取用户地址列表Integer userId = cartConfirmDto.getUserId();List<Addresses> addressesList = addressesDao.getByUserId(userId);//获取购物车中已经选中的商品List<CartInfo> cartItemsList = cartConfirmDto.getCartItemsList();
//        List<CartItems> cartItemsList = cartItemsDao.querySelectedCartItems(userId);if (cartItemsList.isEmpty()){throw new PorkException("您购物车中未选中商品",500);}for (CartInfo cartInfo : cartItemsList) {Integer productId = cartInfo.getProductId();Products products = productsDao.queryById(productId);cartInfo.setMainPhoto(products.getMainPhoto());cartInfo.setName(products.getName());Integer flavorId = cartInfo.getFlavorId();String flavorDescription = flavorsService.queryNameById(flavorId);cartInfo.setFlavorDescription(flavorDescription);}//生成订单唯一标示String orderNo = System.currentTimeMillis()+"";redisTemplate.opsForValue().set(RedisConst.ORDER_REPEAT+orderNo,orderNo,24, TimeUnit.HOURS);//1.获取最优惠优惠券//2.先获取订单价格//3.找到实付金额
//        Double totalPrice = cartItemsDao.getActuallyPay(userId);
//        UserCoupons userCoupon = userCouponsDao.queryOptimalUserCoupon(totalPrice, userId);
//        Double discount = userCoupon.getCoupons().getDiscount();
//        Double actuallyPay = totalPrice - discount;Double totalPrice = cartConfirmDto.getTotalAmount();Integer userCouponId = cartConfirmDto.getUserCouponsId();Double discount = cartConfirmDto.getDiscount();Double actuallyPay = cartConfirmDto.getActuallyPay();UserCoupons userCoupon = userCouponsDao.queryById(userCouponId);//查询可用优惠券List<UserCoupons> userCoupons = userCouponsDao.queryAvailableUserCoupons(totalPrice, userId);//进行封装OrderConfirmVo orderConfirmVo = new OrderConfirmVo(userId,totalPrice,userCoupon,discount,actuallyPay,orderNo,userCoupons,addressesList,cartItemsList);return orderConfirmVo;}

1.3返回类

    */@ApiModelProperty("用户id")private Integer userId;/*** 总金额*/@ApiModelProperty("总金额")private Double totalAmount;@ApiModelProperty("最优惠的优惠券")private UserCoupons userCoupons;/*** 优惠金额*/@ApiModelProperty("优惠金额")private Double discount;/*** 实付金额*/@ApiModelProperty("实付金额")private Double actuallyPay;/*** 订单号*/@ApiModelProperty("订单号")private String orderNo;/*** 用户所有优惠券*/@ApiModelProperty("用户优惠券")private List<UserCoupons> userCouponsList;/*** 用户地址*/@ApiModelProperty("用户地址列表")private List<Addresses> addressesList;/*** 购物车列表*/@ApiModelProperty("购物车列表")private List<CartInfo> cartItemsList;

2.生成订单

2.1请求实体类

生成订单后里面的属性

 @ApiModelProperty(value = "使用预生产订单号防重")private String orderNo;@ApiModelProperty(value = "用户id")private Integer userId;@ApiModelProperty(value = "下单时所使用的地址信息")private Integer addressesId;@ApiModelProperty(value = "下单选中的优惠券id")private Integer userCouponId;@ApiModelProperty(value = "订单备注")private String comment;@ApiModelProperty(value = "所选中商品")private List<CartInfo> cartItemsList;@ApiModelProperty(value = "最后订单总价")private Double totalPrice;@ApiModelProperty(value = "优惠金额")private Double discount;@ApiModelProperty("订单实付金额")private Double ActuallyPay;

2.2生成订单方法实体类

使用lua脚本来保证原子性 

如果redis中有相同orderNo 则说明正常提交订单 然后把redis删除

期间也有锁单 

2.2.1检查锁

    @Overridepublic Boolean checkAndLock(List<ProductStockVo> productStockVoList, String orderNo) {//1.判断productStockVoList是否为空if (CollectionUtils.isEmpty(productStockVoList)){throw new PorkException(ResultCodeEnum.DATA_ERROR);}//2.遍历productStockVoList得到每个商品,验证库存并锁定库存,具备原子性productStockVoList.stream().forEach(productStockVo -> {this.checkLock(productStockVo);});//3.只要有一个商品锁定失败,所有锁定成功的商品都解锁 用于检查流中是否至少有一个元素满足指定的条件boolean flag = productStockVoList.stream().anyMatch(productStockVo -> !productStockVo.getIsLock());if (flag){//所有锁定成功的商品都解锁productStockVoList.stream().filter(ProductStockVo::getIsLock).forEach(productStockVo -> {flavorsDao.unlockStock(productStockVo.getFlavorId(),productStockVo.getSkuNum());});return false;}
//4 如果所有商品都锁定成功了,redis缓存相关数据,为了方便后面解锁和减库存redisTemplate.opsForValue().set(RedisConst.SROCK_INFO+orderNo,productStockVoList,33, TimeUnit.MINUTES);return true;}

2.2.2获得公平锁

    private void checkLock(ProductStockVo productStockVo) {//获取锁 公平锁:谁等待时间长给谁发锁RLock rLock = this.redissonClient.getFairLock(RedisConst.SKUKEY_PREFIX+productStockVo.getFlavorId());rLock.lock();try {//验证库存Flavors flavors = flavorsDao.checkStock(productStockVo.getFlavorId(),productStockVo.getSkuNum());//判断没有满足条件商品,设置isLock值为false,返回if (flavors == null){productStockVo.setIsLock(false);return;}//又满足条件商品,锁定库存 update rows 影响行数Integer rows =  flavorsDao.lockStock(productStockVo.getFlavorId(),productStockVo.getSkuNum());if (rows == 1) {productStockVo.setIsLock(true);}}finally {//解锁rLock.unlock();}}

2.2.3提交订单 

  public OrderGenerateInfo submitOrder(OrderSubmitVo orderSubmitVo) {//第一步拿出userId确定给那个用户设置订单Integer userId = orderSubmitVo.getUserId();//第二步 订单不能重复提交,重复提交验证//通过redis + lua 脚本实现  //lua脚本保证原子性//1.获取传递过来的orderNoString orderNo = orderSubmitVo.getOrderNo();if (orderNo.isEmpty()){throw new PorkException(ResultCodeEnum.ILLEGAL_REQUEST);}//2.拿着orderNo到redis中查询   此lua脚本解析 如果redis中存在的值 = 这一个值 那么 这个值 , 不过没有存在 就返回0 然后结束String script = "if(redis.call('get', KEYS[1]) == ARGV[1]) then return redis.call('del', KEYS[1]) else return 0 end";//3.如果redis有相同orderNo,表示正常提交订单 ,把redis的orderNo删除Boolean flag = (Boolean) redisTemplate.execute(new DefaultRedisScript(script, Boolean.class),Arrays.asList(RedisConst.ORDER_REPEAT + orderNo),orderNo);//4.如果redis没有相同orderNo,表示重复提交了,不能再往后进行if (!flag){throw new PorkException(ResultCodeEnum.REPEAT_SUBMIT);}//第三步 验证库存 并且 锁定库存(订单在30分钟内锁定库存 没有真正减库存)//获取当前购物车商品List<CartInfo> cartItemsList = orderSubmitVo.getCartItemsList();//新建一个锁单Vo 然后把商品信息封装到 Vo里面if (!CollectionUtils.isEmpty(cartItemsList)){List<ProductStockVo> productStockVoList =cartItemsList.stream().map(item ->{ProductStockVo productStockVo = new ProductStockVo();productStockVo.setFlavorId(item.getFlavorId());productStockVo.setSkuNum(item.getQuantity());return productStockVo;}).collect(Collectors.toList());//验证库存,保证具备原子性 解决超卖问题Boolean isLockSuccess = flavorsService.checkAndLock(productStockVoList, orderNo);if (!isLockSuccess){throw new PorkException(ResultCodeEnum.ORDER_STOCK_FALL);}}//第四步 下单过程OrderGenerateInfo orderGenerateInfo = this.saveOrder(orderSubmitVo);//对已生成订单的购物车进行删除List<Integer> cartIdList = cartItemsList.stream().map(CartInfo::getId).collect(Collectors.toList());cartItemsDao.deleteBatchIds(cartIdList);//1.向两张表中添加数据 order_info order_item//返回订单id
return orderGenerateInfo;}

2.2.4保存订单

  @Transactional(rollbackFor = {Exception.class})public OrderGenerateInfo saveOrder(OrderSubmitVo orderSubmitVo) {Integer userId = orderSubmitVo.getUserId();List<CartInfo> cartItemsList = orderSubmitVo.getCartItemsList();if (CollectionUtils.isEmpty(cartItemsList)){throw new PorkException(ResultCodeEnum.DATA_ERROR);}List<String> goodInfoList = new ArrayList<String>();String goodInfo = "";for (CartInfo cartInfo : cartItemsList) {Integer flavorId = cartInfo.getFlavorId();Integer productId = cartInfo.getProductId();Integer quantity = cartInfo.getQuantity();String productName = productsService.queryNameById(productId);String flavorName = flavorsService.queryNameById(flavorId);goodInfo = productName+":"+flavorName+"*"+quantity;goodInfoList.add(goodInfo);}//查数据 顾客收货地址Integer addressesId = orderSubmitVo.getAddressesId();Addresses addresses = addressesDao.queryById(addressesId);if (addresses == null){throw new PorkException(ResultCodeEnum.DATA_ERROR);}String recipientName = addresses.getRecipientName();String recipientPhone = addresses.getRecipientPhone();String province = addresses.getProvince();String city = addresses.getCity();String district = addresses.getDistrict();String detail = addresses.getDetail();String orderAddress = province + city + district + detail;//计算金额Double totalPrice = orderSubmitVo.getTotalPrice();Double discount = orderSubmitVo.getDiscount();Double actuallyPay = orderSubmitVo.getActuallyPay();//原金额
//        Double totalAmount = cartItemsDao.getActuallyPay(userId);
//        Double discount = 0.00;
//        Double actuallyPay = totalAmount;
//        Integer couponId = 0;Integer userCouponId = orderSubmitVo.getUserCouponId();
//        UserCoupons userCoupons = userCouponsDao.queryById(userCouponId);//把优惠券设置为已使用userCouponsDao.update(userCouponId);
//        if (userCoupons!=null){
//            couponId = userCoupons.getCouponId();
//        }//优惠券金额
//        if (userCouponId != null){
//            UserCoupons userCoupons = userCouponsDao.queryById(userCouponId);
//          couponId = userCoupons.getCouponId();
//             discount = couponsDao.queryById(couponId).getDiscount();
//        }
//        //实付金额
//        actuallyPay = totalPrice - discount;//封装订单项List<OrderItems> orderItemsList = new ArrayList<>();for (CartInfo cartItems : cartItemsList) {OrderItems orderItem = new OrderItems();orderItem.setProductId(cartItems.getProductId());orderItem.setFlavorId(cartItems.getFlavorId());orderItem.setQuantity(cartItems.getQuantity());orderItem.setPrice(cartItems.getPrice());orderItem.setStatus(0);orderItemsList.add(orderItem);}Orders order = new Orders();order.setUserId(userId);order.setTotalAmount(totalPrice);order.setStatus(0);order.setConsignee(recipientName);order.setPhone(recipientPhone);order.setAddress(orderAddress);order.setDiscount(discount);order.setOrderNo(orderSubmitVo.getOrderNo());order.setComment(orderSubmitVo.getComment());order.setActuallyPay(actuallyPay);order.setCouponId(userCouponId);order.setGoodInfo(String.join(", ", goodInfoList));//添加数据到订单基本表ordersDao.insert(order);//添加订单里面的订单项orderItemsList.forEach(orderItems -> {orderItems.setOrderId(order.getId());orderItemsDao.insert(orderItems);});//如果当前订单使用优惠券更新优惠券状态if (order.getCouponId()!= null){userCouponsDao.update(userCouponId);}//在redis中记录用户购物数量//hash类型   key(userId)  -  field(skuId)-value(skuNum)String orderSkuKey = RedisConst.ORDER_SKU_MAP + orderSubmitVo.getUserId();BoundHashOperations<String, String, Integer> hashOperations = redisTemplate.boundHashOps(orderSkuKey);cartItemsList.forEach(cartInfo -> {if(hashOperations.hasKey(cartInfo.getFlavorId().toString())) {Integer orderSkuNum = hashOperations.get(cartInfo.getFlavorId().toString()) + cartInfo.getQuantity();hashOperations.put(cartInfo.getFlavorId().toString(), orderSkuNum);}});redisTemplate.expire(orderSkuKey, DateUtil.getCurrentExpireTimes(), TimeUnit.SECONDS);//设置订单过期时间 30分钟后取消订单long orderTimeOut = 1;String keyRedis = String.valueOf(StrUtil.format("{}:{}",RedisConst.REDIS_ORDER_KEY_IS_PAY_0,order.getId()));//设置过期时间redisTemplate.opsForValue().set(keyRedis,order.getOrderNo(),orderTimeOut,TimeUnit.MINUTES);//订单idOrderGenerateInfo orderGenerateInfo  = new OrderGenerateInfo(order.getId(),orderTimeOut);return orderGenerateInfo;}

3.讲讲Redis过期键监听器

redis过期键监听器 实现对键的监听 

如果该键过期了,则进行注册过的操作

3.1配置监听器

像只注册了订单服务的话 你就只能使用订单服务 

若使用其他服务的话 也要进行集成

@Configuration
@AllArgsConstructor
public class RedisListenerConfig {private final RedisTemplate<String, String> redisTemplate;private final RedissonConfig redisConfigProperties;private final OrdersService ordersService;//	private final OrderItemsService orderItemsService;@BeanRedisMessageListenerContainer container(RedisConnectionFactory connectionFactory) {RedisMessageListenerContainer container = new RedisMessageListenerContainer();container.setConnectionFactory(connectionFactory);container.addMessageListener(new RedisKeyExpirationListener(redisTemplate, redisConfigProperties, ordersService), new PatternTopic(StrUtil.format("__keyevent@{}__:expired", redisConfigProperties.getDatabase())));return container;}
}

3.2配置redis 开启监听器

3.3写监听器

@Component
public class RedisKeyExpirationListener implements MessageListener {private RedisTemplate<String, String> redisTemplate;private RedissonConfig redisConfigProperties;private OrdersService ordersService;//    private OrderItemsService orderItemsService;public RedisKeyExpirationListener(RedisTemplate<String, String> redisTemplate,RedissonConfig redisConfigProperties,OrdersService orderInfoService){this.redisTemplate = redisTemplate;this.redisConfigProperties = redisConfigProperties;this.ordersService = orderInfoService;
//        this.orderItemsService = orderItemsService;}@Overridepublic void onMessage(Message message, byte[] bytes) {RedisSerializer<?> serializer = redisTemplate.getValueSerializer();String channel = String.valueOf(serializer.deserialize(message.getChannel()));String body = String.valueOf(serializer.deserialize(message.getBody()));//key过期监听if(StrUtil.format("__keyevent@{}__:expired", redisConfigProperties.getDatabase()).equals(channel)){//订单自动取消if(body.contains(RedisConst.REDIS_ORDER_KEY_IS_PAY_0)) {body = body.replace(RedisConst.REDIS_ORDER_KEY_IS_PAY_0, "");String[] str = body.split(":");String wxOrderId = str[1];System.out.println(wxOrderId);Orders orders = ordersService.queryById(Integer.valueOf(wxOrderId));if(orders != null && orders.getStatus() == 0){//只有待支付的订单能取消//TODO 订单取消 库存增加 减优惠券
//                    orderItemsService.toCancel(orders.getId());ordersService.cancelOrder(orders.getId());System.out.println("订单id:"+orders.getId()+"已删除");}}

相关文章:

最近在写的支付模块

最近再写支付模块就到处借鉴 旨在回顾一下。 1.确认订单功能 使用场景是&#xff1a;用户在选择好购物车后&#xff0c;或者是直接选择商品后&#xff08;选择商品封装为购物车&#xff09; 这样做是根据尚硅谷来学习的 目前需要这些属性&#xff0c;原因是在确认订单页面后…...

解决域名加别名后再代理或者映射到fastadmin项目

如果遇到微应用不想再添加或者不方便添加单独的二级域名时&#xff0c;就需要用到代理或者映射来进入到我们的微应用项目中。 可以修改route.php路由文件的下面这个参数 __alias__ > [别名 > 模块/控制器] 如图 然后再修改config.php文件里面的view_replace_str参数…...

Armv9.5架构新增的关键扩展--精简版

Armv9.5架构扩展是对Armv9.4的扩展。它增加了强制性和可选的架构特性。有些特性必须一起实现。实现是符合Armv9.5规范,需要满足以下条件: 符合/兼容Armv9.4规范包含所有Armv9.5架构的强制性特性。符合Armv9.5规范的实现还可以包括: Armv9.5的可选特性以下是arm9.5架构中关键…...

STM32 GPIO 模块

B站视频地址&#xff1a;芯片内部GPIO模块细节 引脚 将 STM32 芯片&#xff0c;类比为【大脑】 而旁边的引脚&#xff0c;类比为【神经】 通过引脚&#xff0c;使得&#xff0c;STM32&#xff0c;可以和外部世界&#xff0c;进行交流 比如&#xff0c;当我们和别人说话时&am…...

网络剪枝——network-slimming 项目复现

目录 文章目录 目录网络剪枝——network-slimming 项目复现clone 存储库Baselinevgg训练结果 resnet训练结果 densenet训练结果 Sparsityvgg训练结果 resnet训练结果 densenet训练结果 Prunevgg命令结果 resnet命令结果 densenet命令结果 Fine-tunevgg训练结果 resnet训练结果 …...

Spring 懒加载的实际应用

引言 在 Spring 框架中&#xff0c;懒加载机制允许你在应用程序运行时延迟加载 Bean。这意味着 Bean 只会在第一次被请求时才实例化&#xff0c;而不是在应用程序启动时就立即创建。这种机制可以提高应用程序的启动速度&#xff0c;并节省内存资源。 Spring 的懒加载机制 懒…...

PyQT 串口改动每次点开时更新串口信息

class MainWindow(QWidget, Ui_Form):def __init__(self):super().__init__(parentNone)self.setupUi(self)self.comboBox.installEventFilter(self) # 加载事件过滤器self.comboBox.addItems(get_ports())def eventFilter(self, obj, event): # 定义事件过滤器if isinstance(o…...

三级_网络技术_19_路由器的配置及使用

1.在Cisco路由器上配置DHCP服务&#xff0c;使得客户端可以分配到的地址范围是222.28.71.2-222.28.71.200地址租用时间是2小时30分钟&#xff0c;不记录地址冲突日志默认路由是222.28.71.1&#xff0c;分配的dns服务器地址是222.28126.27和222.28.126.26。以下配置完全正确的是…...

【STM32 Blue Pill编程】-STM32CubeIDE开发环境搭建与点亮LED

开发环境搭建与点亮LED 文章目录 开发环境搭建与点亮LED1、STM32F103C8T6及STM32 Blue Pill 介绍2、下载并安装STM32CubeIDE3、编程并点亮LED3.1 在Stm32CubeIDE中编写第一个STM32程序3.1.1 创建项目3.1.2 设备配置3.1.2.1 系统时钟配置3.1.2.2 系统调试配置3.1.2.3 GPIO配置3.…...

【数据结构】六、图:4.图的遍历(深度优先算法DFS、广度优先算法BFS)

三、基本操作 文章目录 三、基本操作1.图的遍历1.1 深度优先遍历DFS1.1.1 DFS算法1.1.2 DFS算法的性能分析1.1.3 深度优先的生成树和生成森林 1.2 广度优先遍历BFS1.2.1 BFS算法1.2.2 BFS算法性能分析1.2.3 广度优先的生成树和生成森林 1.3 图的遍历与图的连通性 1.图的遍历 图…...

29、号外!号外!ERA5再分析数据下载方式更新啦

文章目录 1. 前言2. 账号注册与协议签署2.1 账号注册2.2 签署CDS-Beta使用条款2.3 更新.cdsapi文件 3. 常见问题与解决方法&#xff08;持续更新中&#xff09;3.1 问题1&#xff1a;更新完.cdsapi文件之后&#xff0c;原有下载代码不可以使用3.2 问题2: RuntimeError: 403 Cli…...

智能识别,2024年SD卡数据恢复软件的智能进化

除了手机之外现在有不少的设备还是依靠SD卡来存储数据&#xff0c;比如相机、摄像头、无人机等。有的时候会因为一些意外的情况导致数据丢失&#xff0c;那是真的丢失了吗&#xff1f;大部分情况还是可以依靠sd卡数据恢复工具来找回这些“消失”的数据哦。 1.福昕数据恢复 链…...

浙大数据结构慕课课后题(04-树5 Root of AVL Tree)

题目要求&#xff1a; AVL 树是一种自平衡的二叉搜索树。在 AVL 树中&#xff0c;任何节点的两个子子树的高度最多相差一;如果在任何时候它们相差不止一&#xff0c;则进行重新平衡以恢复此属性。图 1-4 说明了旋转规则。 图1 图2 图3 图4 现在给定一系列插入&#xff0c;您应该…...

Golang | Leetcode Golang题解之第331题验证二叉树的前序序列化

题目&#xff1a; 题解&#xff1a; func isValidSerialization(preorder string) bool {n : len(preorder)slots : 1for i : 0; i < n; {if slots 0 {return false}if preorder[i] , {i} else if preorder[i] # {slots--i} else {// 读一个数字for i < n &&…...

zdppy+vue3+onlyoffice文档管理系统项目实战 20240812上课笔记

遗留问题 1、增加新建和导入按钮&#xff0c;有按钮了&#xff0c;但是还没有完善&#xff0c;图标还不对&#xff0c;需要解决 2、登录功能 3、用户管理 4、角色管理 5、权限管理 6、分享功能 解决新建和导入的图标问题 解决代码&#xff1a; <a-button type"prim…...

怎么将mov视频转换成mp4?将mov视频转换成mp4的方法

怎么将mov视频转换成mp4&#xff1f;由于mov格式通常与苹果设备兼容性较好&#xff0c;而mp4则更广泛地支持于各种播放器和设备中&#xff0c;因此将mov转换为mp4可以确保视频在更多场景下能够流畅播放。通过这种转换&#xff0c;你可以确保视频在各种平台和设备上的兼容性&…...

大数据技术——实战项目:广告数仓(第五部分)

目录 第9章 广告数仓DIM层 9.1 广告信息维度表 9.2 平台信息维度表 9.3 数据装载脚本 第10章 广告数仓DWD层 10.1 广告事件事实表 10.1.1 建表语句 10.1.2 数据装载 10.1.2.1 初步解析日志 10.1.2.2 解析IP和UA 10.1.2.3 标注无效流量 10.2 数据装载脚本 第9章 广…...

计算机毕业设计 家电销售展示平台 Java+SpringBoot+Vue 前后端分离 文档报告 代码讲解 安装调试

&#x1f34a;作者&#xff1a;计算机编程-吉哥 &#x1f34a;简介&#xff1a;专业从事JavaWeb程序开发&#xff0c;微信小程序开发&#xff0c;定制化项目、 源码、代码讲解、文档撰写、ppt制作。做自己喜欢的事&#xff0c;生活就是快乐的。 &#x1f34a;心愿&#xff1a;点…...

C# 根据MySQL数据库中数据,批量删除OSS上的垃圾文件

protected void btndeleteTask_Click(object sender, EventArgs e){//获取标识为已删除数据&#xff0c;一次加载500条int countlocks _goodsItemsApplication.CountAllNeedExecuteTask();int totalPagelocks (countlocks 500 - 1) / 500;//分批次处理for (int curentpage …...

Vue3+Element-plus+setup使用vuemap/vue-amap实现高德地图API相关操作

首先要下载依赖并且引入 npm安装 // 安装核心库 npm install vuemap/vue-amap --save// 安装loca库 npm install vuemap/vue-amap-loca --save// 安装扩展库 npm install vuemap/vue-amap-extra --save cdn <script src"https://cdn.jsdelivr.net/npm/vuemap/vue-a…...

Python爬虫实战:研究MechanicalSoup库相关技术

一、MechanicalSoup 库概述 1.1 库简介 MechanicalSoup 是一个 Python 库,专为自动化交互网站而设计。它结合了 requests 的 HTTP 请求能力和 BeautifulSoup 的 HTML 解析能力,提供了直观的 API,让我们可以像人类用户一样浏览网页、填写表单和提交请求。 1.2 主要功能特点…...

多云管理“拦路虎”:深入解析网络互联、身份同步与成本可视化的技术复杂度​

一、引言&#xff1a;多云环境的技术复杂性本质​​ 企业采用多云策略已从技术选型升维至生存刚需。当业务系统分散部署在多个云平台时&#xff0c;​​基础设施的技术债呈现指数级积累​​。网络连接、身份认证、成本管理这三大核心挑战相互嵌套&#xff1a;跨云网络构建数据…...

简易版抽奖活动的设计技术方案

1.前言 本技术方案旨在设计一套完整且可靠的抽奖活动逻辑,确保抽奖活动能够公平、公正、公开地进行,同时满足高并发访问、数据安全存储与高效处理等需求,为用户提供流畅的抽奖体验,助力业务顺利开展。本方案将涵盖抽奖活动的整体架构设计、核心流程逻辑、关键功能实现以及…...

【HarmonyOS 5.0】DevEco Testing:鸿蒙应用质量保障的终极武器

——全方位测试解决方案与代码实战 一、工具定位与核心能力 DevEco Testing是HarmonyOS官方推出的​​一体化测试平台​​&#xff0c;覆盖应用全生命周期测试需求&#xff0c;主要提供五大核心能力&#xff1a; ​​测试类型​​​​检测目标​​​​关键指标​​功能体验基…...

系统设计 --- MongoDB亿级数据查询优化策略

系统设计 --- MongoDB亿级数据查询分表策略 背景Solution --- 分表 背景 使用audit log实现Audi Trail功能 Audit Trail范围: 六个月数据量: 每秒5-7条audi log&#xff0c;共计7千万 – 1亿条数据需要实现全文检索按照时间倒序因为license问题&#xff0c;不能使用ELK只能使用…...

新能源汽车智慧充电桩管理方案:新能源充电桩散热问题及消防安全监管方案

随着新能源汽车的快速普及&#xff0c;充电桩作为核心配套设施&#xff0c;其安全性与可靠性备受关注。然而&#xff0c;在高温、高负荷运行环境下&#xff0c;充电桩的散热问题与消防安全隐患日益凸显&#xff0c;成为制约行业发展的关键瓶颈。 如何通过智慧化管理手段优化散…...

PL0语法,分析器实现!

简介 PL/0 是一种简单的编程语言,通常用于教学编译原理。它的语法结构清晰,功能包括常量定义、变量声明、过程(子程序)定义以及基本的控制结构(如条件语句和循环语句)。 PL/0 语法规范 PL/0 是一种教学用的小型编程语言,由 Niklaus Wirth 设计,用于展示编译原理的核…...

Springboot社区养老保险系统小程序

一、前言 随着我国经济迅速发展&#xff0c;人们对手机的需求越来越大&#xff0c;各种手机软件也都在被广泛应用&#xff0c;但是对于手机进行数据信息管理&#xff0c;对于手机的各种软件也是备受用户的喜爱&#xff0c;社区养老保险系统小程序被用户普遍使用&#xff0c;为方…...

SiFli 52把Imagie图片,Font字体资源放在指定位置,编译成指定img.bin和font.bin的问题

分区配置 (ptab.json) img 属性介绍&#xff1a; img 属性指定分区存放的 image 名称&#xff0c;指定的 image 名称必须是当前工程生成的 binary 。 如果 binary 有多个文件&#xff0c;则以 proj_name:binary_name 格式指定文件名&#xff0c; proj_name 为工程 名&…...

GruntJS-前端自动化任务运行器从入门到实战

Grunt 完全指南&#xff1a;从入门到实战 一、Grunt 是什么&#xff1f; Grunt是一个基于 Node.js 的前端自动化任务运行器&#xff0c;主要用于自动化执行项目开发中重复性高的任务&#xff0c;例如文件压缩、代码编译、语法检查、单元测试、文件合并等。通过配置简洁的任务…...