SpringBoot 微信点餐开源系统

SpringBoot 微信点餐开源系统,值得一看 今天跟大家分享SpringBoot 微信点餐开源系统的知识。 1 架构 前后端分离: Nginx 与 Tomcat 的关系在这篇文章,几分钟可以快速了解: https://www.jianshu.com/p/22dcb7ef9172 补充: setting.xml 文件的作用:settings.xml 是 maven 的全局配置文件。而 pom.xml 文件是所在项目的局部配置。Settin... 阅读详情
  • 作者:Tommmmm

  • www.jianshu.com/p/ae14101989f2

架构

前后端分离:

Nginx 与 Tomcat 的关系在这篇文章,几分钟可以快速了解:

https://www.jianshu.com/p/22dcb7ef9172

补充:

  • setting.xml 文件的作用:settings.xml 是 maven 的全局配置文件。而 pom.xml 文件是所在项目的局部配置。Settings.xml 中包含类似本地仓储位置、修改远程仓储服务器、认证信息等配置。

  • maven 的作用:借助 Maven,可将 jar 包仅仅保存在 “仓库” 中,有需要该文件时,就引用该文件接口,不需要复制文件过来占用空间。

注:这个 “仓库” 应该就是本地安装 maven 的目录下的 Repository 的文件夹

分布式锁

线程锁:当某个方法或代码使用锁,在同一时刻仅有一个线程执行该方法或该代码段。线程锁只在同一 JVM 中有效,因为线程锁的实现在根本上是依靠线程之间共享内存实现的。如 synchronized

进程锁:为了控制同一操作系统中多个进程访问某个共享资源。

分布式锁:当多个进程不在同一个系统中,用分布式锁控制多个进程对资源的访问。

分布式锁一般有三种实现方式:

  1. 数据库乐观锁;

  2. 基于 Redis 的分布式锁;

  3. 基于 ZooKeeper 的分布式锁。

乐观锁的实现:使用版本标识来确定读到的数据与提交时的数据是否一致。提交后修改版本标识,不一致时可以采取丢弃和再次尝试的策略。

CAS:可以阅读这篇文章:

https://www.jianshu.com/p/456bb1ea9627

分布式锁基于 Redis 的实现:(本系统锁才用的)

基本命令:

  • SETNX(SET if Not exist):当且仅当 key 不存在,将 key 的值设为 value ,并返回 1;若给定的 key 已经存在,则 SETNX 不做任何动作,并返回 0。

  • GETSET:将给定 key 的值设为 value ,并返回 key 的旧值。先根据 key 获取到旧的 value,再 set 新的 value。

  • EXPIRE 为给定 key 设置生存时间, 当 key 过期时,它会被自动删除。

加锁方式:

这里的 jedis 是 Java 对 Redis 的集成

jedis.set(String key, String value, String nxxx, String expx, int time)

错误的加锁方式 1:

如果程序在执行完 setnx() 之后突然崩溃,导致锁没有设置过期时间。那么将会发生死锁。

Long result = jedis.setnx(Key, value);
    if (result == 1) {
        // 若在这里程序突然崩溃,则无法设置过期时间,将发生死锁
        jedis.expire(Key, expireTime);
    }

错误的加锁方式 2:

分布式锁才用(Key,过期时间)的方式,如果锁存在,那么获取它的过期时间,如果锁的确已经过期了,那么获得锁,并且设置新的过期时间

错误分析:不同的客户端之间需要同步好时间。

 long expires = System.currentTimeMillis() + expireTime;
    String expiresStr = String.valueOf(expires);
    // 如果当前锁不存在,返回加锁成功
    if (jedis.setnx(lockKey, expiresStr) == 1) {
        return true;
    }
    // 如果锁存在,获取锁的过期时间
    String currentValueStr = jedis.get(lockKey);
    if (currentValueStr != null && Long.parseLong(currentValueStr) < System.currentTimeMillis()) {
        // 锁已过期,获取上一个锁的过期时间,并设置现在锁的过期时间
        String oldValueStr = jedis.getSet(lockKey, expiresStr);
        if (oldValueStr != null && oldValueStr.equals(currentValueStr)) {
            // 考虑多线程并发的情况,只有一个线程的设置值和当前值相同,它才有权利加锁
            return true;
        }
    }
    // 其他情况,一律返回加锁失败
    return false;

解锁:判断锁的拥有者后可以使用 jedis.del(lockKey) 来释放锁。

分布式锁基于 Zookeeper 的实现

Zookeeper 简介:Zookeeper 提供一个多层级的节点命名空间(节点称为 znode),每个节点都用一个以斜杠(/)分隔的路径表示,而且每个节点都有父节点(根节点除外)。

例如,/foo/doo 这个表示一个 znode,它的父节点为 / foo,父父节点为 /,而 / 为根节点没有父节点。

client 不论连接到哪个 Server,展示给它都是同一个视图,这是 zookeeper 最重要的性能。

Zookeeper 的核心是原子广播,这个机制保证了各个 Server 之间的同步。实现这个机制的协议叫做 Zab 协议。Zab 协议有两种模式,它们分别是恢复模式(选主)和广播模式(同步)。*当服务启动或者在领导者崩溃后,Zab 就进入了恢复模式*,当领导者被选举出来,且大多数 Server 完成了和 leader 的状态同步以后,恢复模式就结束了。状态同步保证了 leader 和 Server 具有相同的系统状态。

为了保证事务的顺序一致性,zookeeper 采用了递增的事务 id 号(zxid)来标识事务,实现中 zxid 是一个 64 位的数字。

Zookeeper 的分布式锁原理

获取分布式锁的流程:

  1. 在获取分布式锁的时候在 locker 节点 (locker 节点是 Zookeeper 的指定节点) 下创建临时顺序节点,释放锁的时候删除该临时节点。

  2. 客户端调用 createNode 方法在 locker 下创建临时顺序节点,然后调用 getChildren(“locker”) 来获取 locker 下面的所有子节点,注意此时不用设置任何 Watcher。

  3. 客户端获取到所有的子节点 path 之后,如果发现自己创建的子节点序号最小,那么就认为该客户端获取到了锁。

  4. 如果发现自己创建的节点并非 locker 所有子节点中最小的,说明自己还没有获取到锁,此时客户端需要找到比自己小的那个节点,然后对其调用 exist() 方法,同时对其注册事件监听器。

  5. 之后,让这个被关注的节点删除,则客户端的 Watcher 会收到相应通知,此时再次判断自己创建的节点是否是 locker 子节点中序号最小的,如果是则获取到了锁,如果不是则重复以上步骤继续获取到比自己小的一个节点并注册监听。

我的解释:

A 在 Locker 下创建了 Noden —> 循环 (每次获取 Locker 下的所有子节点 —> 对这些节点按节点自增号排序顺序 —> 判断自己创建的 Noden 是否是第一个节点 —> 如果是则获得了分布式锁 —> 如果不是监听上一个节点 Node_n-1 等它释放掉分布式锁。)

@ControllerAdvice 处理全局异常
Mybatis 注解方式的使用:
@insert 用注解方式写 SQL 语句

分布式系统的下的 Session

1、分布式系统:多节点,节点发送数据交互,不共享主内存,但通过网络发送消息合作。

分布式:不同功能模块的节点

集群:相同功能的节点

2、Session 与 token

服务端在 HTTP 头里设置 SessionID 而客户端将其保存在 cookie

而使用 Token 时需要手动在 HTTP 头里设置,服务器收到请求后取出 cookie 进行验证。

都是一个用户一个标志

3、分布式系统中的 Session 问题:

高并发:通过设计保证系统能够同时并行处理很多请求。

当高并发量的请求到达服务端的时候通过负载均衡的方式分发到集群中的某个服务器,这样就有可能导致同一个用户的多次请求被分发到集群的不同服务器上,就会出现取不到 session 数据的情况。

根据访问不同的 URL,负载到不同的服务器上去

三台机器,A1 部署类目,A2 部署商品,A3 部署单服务

通用方案:用 Redis 保存 Session 信息,服务器需要时都去找 Redis 要。登录时保存好 key-value,登出时让他失效

垂直扩展:IP 哈希 IP 的哈希值相同的访问同一台服务器

session 的一致性:只要用户不重启浏览器,每次 http 短连接请求,理论上服务端都能定位到 session,保持会话。

Redis 作为分布式锁

高并发:通过设计保证系统能够同时并行处理很多请求。

同步:Java 中的同步指的是通过人为的控制和调度,保证共享资源的多线程访问成为线程安全。

线程的 Block 状态:

a. 调用 join() 和 sleep() 方法,sleep() 时间结束或被打断

b.wait(),使该线程处于等待池, 直到 notify()/notifyAll():不释放资源

此外,在 runnable 状态的线程是处于被调度的线程,Thread 类中的 yield 方法可以让一个 running 状态的线程转入 runnable。

Q:为什么 wait,notify 和 notifyAll 必须与 synchronized 一起使用?Obj.wait()、Obj.notify 必须在 synchronized(Obj){…} 语句块内。

A:wait 就是说线程在获取对象锁后,主动释放对象锁,同时本线程休眠。

Q:Synchronized:

A:Synchronized 就是非公平锁,它无法保证等待的线程获取锁的顺序。

公平和非公平锁的队列都基于锁内部维护的一个双向链表,表结点 Node 的值就是每一个请求当前锁的线程。公平锁则在于每次都是依次从队首取值。

ReentrantLock 重入性:

重入锁可以看这两篇文章,都比较简单

https://www.jianshu.com/p/587a4559442b
https://www.jianshu.com/p/1c52f17efaab

Spring + Redis 缓存的两个重要注解:

  • @cacheable 只会执行一次,当标记在一个方法上时表示该方法是支持缓存的,Spring 会在其被调用后将其返回值缓存起来,以保证下次利用同样的参数来执行该方法时可以直接从缓存中获取结果。

  • @cacheput:与 @Cacheable 不同的是使用 @CachePut 标注的方法在执行前不会去检查缓存中是否存在之前执行过的结果,而是每次都会执行该方法,并将执行结果以键值对的形式存入指定的缓存中。

对数据库加锁(乐观锁 与 悲观锁)

悲观锁依赖数据库实现:

select * from account where name=”Erica” for update

这条 sql 语句锁定了 account 表中所有符合检索条件(name=”Erica”)的记录,使该记录在修改期间其它线程不得占有。

代码层加锁:

String hql ="from TUser as user where user.;
Query query = session.createQuery(hql);
query.setLockMode("user",LockMode.UPGRADE); //加锁
List userList = query.list();//执行查询,获取数据

其它

@Data 类似于自动生成了 Getter()、Setter()、ToString() 等方法。

JAVA1.8 的新特性 StreamAPI:Collectors 中提供了将流中的元素累积到汇聚结果的各种方式

List<Menu> menus=Menu.getMenus.stream().collect(Collectors.toList())

For - each 写法:

for each 语句是 java5 新增,在遍历数组、集合的时候,for each 拥有不错的性能。

public static void main(String[] args) {
        String[] names = {"beibei", "jingjing"};
        for (String name : names) {
            System.out.println(name);
        }
    }

for each 虽然能遍历数组或者集合,但是只能用来遍历,无法在遍历的过程中对数组或者集合进行修改。

BindingResult:一个 @Valid 的参数后必须紧挨着一个 BindingResult 参数,否则 spring 会在校验不通过时直接抛出异常。

@Data
public class OrderForm {
    @NotEmpty(message = "姓名必填")
    private String name;
}

后台:

@RequestMapping("save")  
    public String save( @Valid OrderForm order,BindingResult result) {  
        //  
        if(result.hasErrors()){  
            List<ObjectError> ls=result.getAllErrors();  
            for (int i = 0; i < ls.size(); i++) {  
                log.error("参数不正确,OrderForm={}", order);
                throw new SellException(
                 ………… ,
             result.getFeildError.getDefaultMessage()
              )
                System.out.println("error:"+ls.get(i));  
            }  
        }  
        return "adduser";  
    }

result.getFeildError.getDefaultMessage() 可抛出 “姓名必填” 的异常。

4、List 转为 Map

public class Apple {
    private Integer id;
    private String name;
    private BigDecimal money;
    private Integer num;
   /*构造函数*/
}
List<Apple> appleList = new ArrayList<>();//存放apple对象集合
Apple apple1 =  new Apple(1,"苹果1",new BigDecimal("3.25"),10);
Apple apple12 = new Apple(1,"苹果2",new BigDecimal("1.35"),20);
Apple apple2 =  new Apple(2,"香蕉",new BigDecimal("2.89"),30);
Apple apple3 =  new Apple(3,"荔枝",new BigDecimal("9.99"),40);
appleList.add(apple1);
appleList.add(apple12);
appleList.add(apple2);
appleList.add(apple3);
Map<Integer, Apple> appleMap = 
appleList.stream().collect(Collectors.toMap(Apple::getId, a -> a,(k1,k2)->k1));

5、Collection 的子类:List、Set

List:ArrayList、LinkedList 、Vector

List:有序容器,允许 null 元素,允许重复元素

Set:元素是无序的,不允许元素

最流行的是基于 HashMap 实现的 HashSet,由 [hashCode() 和 equals()]保证元素的唯一性。

可以用 set 帮助去掉 List 中的重复元素,set 的构造方法的参数可以是 List,构造后是一个去重的 set。

HashMap 的补充:它不是 Collection 下的

Map 可以使用 containsKey()/containsValue() 来检查其中是否含有某个 key/value。

HashMap 会利用对象的 hashCode 来快速找到 key。

插入过程:通过一个 hash 函数确定 Entry 的插入位置 index=hash(key),但是数组的长度有限,可能会发生 index 冲突,当发生了冲突时,会使用头插法,即为新来的 Entry 指向旧的 Entry,成为一个链表。

每次插入时依次遍历它的 index 下的单链表,如果存在 Key 一致的节点,那么直接替换,并且返回新的值。

但是单链表不会一直增加元素,当元素个数超过 8 个时,会尝试将单链表转化为红黑树存储。

为何加载因子默认为 0.75?*(0.75 开始扩容)*

答:通过源码里的 javadoc 注释看到,元素在哈希表中分布的桶频率服从参数为 0.5 的泊松分布。

源码地址:

https://github.com/923310233/wxOrder

(完)

【推荐阅读】

在 Spring Boot 中,如何干掉 if else

基于 token 的多平台身份认证架构设计

是时候扔掉Postman了,又一个被低估的IDEA插件出来了...

(java思维导图)

长按关注,每天java一下,成就架构师

好文!必须点赞

TC3xx芯片SPI多从机通信避坑指南:AUTOSAR框架下的DMA配置与片选切换 本文针对英飞凌TC3xx芯片在AUTOSAR框架下实现SPI多从机通信的实战难题,提供了详尽的避坑指南。重点解析了如何利用硬件支持的16路片选(SLSO)灵活切换,在AUTOSAR中正确配置不同时序的从设备,并深入探讨了异步模式下DMA的启用条件与关键配置细节,帮助开发者规避通信失败风险,提升系统可靠性。 阅读详情

相关推荐

pytorch中dataloader的num_workers参数

结论速递 在Windows系统中,num_workers参数建议设为0,在Linux系统则不需担心。 1 问题描述 在之前的任务超大图上的节点表征学习中,使用PyG库用于数据加载的DataLoader,ClusterLoader等类时,会涉及到参数num_workers。在不同系统环境试验该参数的设定值时,会出现不同的结果 colab(Linux),设为12 有warning message,提示num_workers参数设置不合理,不影响继续运行 /usr/local/lib/python3.7/di

qq_40990057的博客 1万+

likeshop外卖点餐系统开源啦100%开源无加密

外卖点餐系统适用于茶饮类的外卖点餐场景,搭建自己的一点点、奈雪、喜茶点餐系统。 系统基于总部+多门店的连锁模式,拥有门店独立管理后台,支持总部定价和门店定价。LBS定位点餐,可堂食可外卖。无论运营还是二开都是性价比极高的100%开源商城系统。...

u010971922的专栏 6645

VCS和UVM常用编译选项

VCS编译选项 -full64 在64bit模式下编译、仿真,用于64位操作系统 -j8 指定编译器可以并行编译的进程数为8 -timescale=1ns/1ps 指定仿真时间和精度 +libext+.v+.V+.sv+.svh 识别.v、.sv、.svh等多种格式文件 -sverilog 支持system verilog 编译 -f xxx.lisf 指定包含所有设计文件列表的文件名 -top test 设置顶层模块为test。(指包含.

qq_40571921的博客 9932

likeshop外卖点餐系统【100%开源无加密】

外卖点餐系统适用于茶饮类的外卖点餐场景, 系统基于总部+多门店的连锁模式,拥有门店独立管理后台,支持总部定价和门店定价。LBS定位点餐,可堂食可外卖

adminlikeshop的博客 1114

LabVIEW面向对象编程:操作者框架入门实战

本文是LabVIEW面向对象编程中操作者框架的入门实战指南。针对传统“面条式代码”在复杂项目中的维护难题,文章通过创建操作者、定义消息与处理函数、在主VI中调用等步骤,详细演示了如何利用操作者框架构建模块化、易扩展的应用程序架构,有效管理并行任务。

f0g1h2的博客 589

Unity安卓打包实战:SDK与JDK配置全攻略

本文详细介绍了Unity安卓打包过程中SDK与JDK的配置方法,包括工具下载、安装步骤、环境变量设置及常见错误排查。通过实战指南帮助开发者快速完成Unity安卓打包环境搭建,提升开发效率。

weixin_30338481的博客 415

外卖点餐系统源码开源解析:如何低成本打造餐饮APP+小程序生态

它打破了技术垄断的壁垒,让夫妻店也能拥有和连锁品牌同台竞技的数字化武器——通过APP沉淀核心用户,用小程序覆盖临时客源,形成“私域+公域”的双轮驱动。​当然,开源并非一劳永逸的“万能药”,它需要商家具备基础的技术甄别能力,也需要在安全维护、功能迭代上持续投入精力。此刻,那些躺在代码仓库里的开源项目,正等待着被赋予烟火气——毕竟,最好的点餐系统,永远是那个能让顾客快速吃到满意饭菜的系统。然而,对于中小餐饮商家而言,动辄几十万的定制开发费用、复杂的技术维护门槛,如同两座大山横亘在数字化转型的路口。

wetbaba的博客 1411

MaaS 商业模式全面分析报告:从技术赋能到商业变现的全链条探索

MaaS(模型即服务)商业模式正成为AI产业主流,2024年上半年中国市场规模达2.5亿元,预计2027年占比将提升至47%。该模式通过云服务提供预训练AI模型,大幅降低企业应用AI的技术门槛和成本。核心盈利方式包括按使用量计费、订阅制、定制化服务等,其中混合模式因灵活性成为趋势。MaaS产业链包含模型提供商、云平台、应用开发商和最终用户,重塑了AI产业格局。随着《数据法案》等监管加强,数据增值服务面临更严格合规要求。未来五年,中国MaaS市场增速预计超50%,用户规模将从2025年2.1亿增至2030年5

芯片行业20年 · 参与定义实现千万级量产出货 · AI芯片PM 2889

基于Android平台实现在线点餐管理系统【附项目源码】分享

通过客户端,顾客可以浏览菜单,选择心仪的菜品,对菜品进行评价,还可以使用优惠券和积分兑换等功能。基于Android平台实现的在线点餐管理系统,具有良好的用户界面和交互效果,可以方便快捷地进行点餐和支付。随着在线点餐系统的不断完善和普及,餐厅可以更好地适应消费者需求,提高管理效率,提升服务质量,实现可持续发展。餐饮行业一直是一个不断创新的领域,如今,随着科技的不断发展和普及,人们的生活方式也在逐渐改变。此外,系统还可以提供订单处理进度和时效性监控功能,帮助餐厅管理者更好地管理订单,提高服务质量。

ybigbear的博客 1234

2 海康视觉平台VisionMaster 上手系列:大纲及准备

海康视觉平台VisionMaster 大纲,课前准备 快速入门 工业机器视觉 机器视觉

HuangGong2022的博客 1万+

阿里云 Docker 镜像加速收费后:这些免费替代方案值得收藏

阿里云Docker镜像加速服务收费后,国内开发者急需免费替代方案。本文推荐2025年仍可用的7个免费镜像源,包括轩辕镜像、DaoCloud、网易云等,并提供多源配置方案以提高稳定性。建议开发者在CI/CD环境中配置多个镜像源,避免构建失败。文章还提供了详细的配置步骤和使用建议,适合个人和团队开发者参考。

sg_knight的专栏 1928

基于springboot+vue实现外卖点餐系统

关于本项目的技术选型, 我们将会从 用户层、网关层、应用层、数据层 这几个方面进行介绍,而对于我们服务端开发工程师来说,在项目开发过程中,我们主要关注应用层及数据层技术的应用。

BS009的博客 6217

PyCharm配置SSH远程解释器第3步时弹框报错:com.google.gson.stream.MalformedJsonException: Expected value at l...如何解决?

🏆本文收录于 《全栈 Bug 调优(实战版)》 专栏。专栏聚焦真实项目中的各类疑难 Bug,从成因剖析 → 排查路径 → 解决方案 → 预防优化全链路拆解,形成一套可复用、可沉淀的实战知识体系。无论你是初入职场的开发者,还是负责复杂项目的资深工程师,都可以在这里构建一套属于自己的「问题诊断与性能调优」方法论,助你稳步进阶、放大技术价值 。

**My Coding Family** 1928

SpringBoot微信点餐开源系统

架构 前后端分离: 部署架构: Nginx与Tomcat的关系在这篇文章,几分钟可以快速了解: https://www.jianshu.com/p/22dcb7ef9172 补充: setting.xml 文件的作用:settings.xml是maven的全局配置文件。而pom.xml文件是所在项目的局部配置。Settings.xml中包含类似本地仓储位置、修改远程...

543

SIMATIC S7-1200, S7-1500 PID 控制[手册]

SIMATIC S7-1200, S7-1500 PID 控制[手册]

Camera2Demo

在Camera2 的基础上进行封装,使得Camera2一堆初始化逻辑与Activity分离,降低耦合度,完成预览拍照并保存的操作

springboot session过期时间_Spring Boot 微信点餐开源系统

架构分布式锁分布式锁基于Redis的实现:(本系统锁才用的)分布式锁基于Zookeeper的实现Zookeeper的分布式锁原理分布式系统的下的SessionRedis作为分布式锁其它架构前后端分离:补充:setting.xml 文件的作用:settings.xml是maven的全局配置文件。 而pom.xml文件是所在项目的局部配置。Settings.xml中包含类似本地仓储位置、修改远程仓储服...

weixin_39585886的博客 245

怀旧版电脑GBC模拟器

再现原版GBC掌机的界面,电脑运行连游戏界面都一样大小,很怀旧,很真实,(英文版)强烈推荐,很小的文件,很难才找到的。

Spring Boot 微信点餐开源系统!

Zookeeper提供一个多层级的节点命名空间(节点称为znode),每个节点都用一个以斜杠(/)分隔的路径表示,而且每个节点都有父节点(根节点除外)。例如,/foo/doo这个表示一个znode,它的父节点为/foo,父父节点为/,而/为根节点没有父节点。

m0_71777195的博客 268

RU DOS版、EFI版32bit/64bit BIOS常用工具

DOS版、EFI版的RU工具,可用来查看IO、MEM、PCI、SMBIOS等资源。亲测在EFI SHELL下可用。

Spring Boot 微信点餐开源系统

点击上方“芋道源码”,选择“设为星标”管她前浪,还是后浪?能浪的浪,才是好浪!每天 8:55 更新文章,每天掉亿点点头发...源码精品专栏原创 | Java 2020 超神之路,很肝~...

芋艿V 515

如何利用Spring Boot 微信点餐开源系统

由于细节内容实在太多啦,所以只把部分知识点整理出来粗略的介绍,每个小节点里面都有更细化的内容! 接下来开始分享啦 架构 前后端分离: 补充: setting.xml 文件的作用:settings.xml是maven的全局配置文件。而pom.xml文件是所在项目的局部配置。Settings.xml中包含类似本地仓储位置、修改远程仓储服务器、认证信息等配置。 maven的作用:借助Maven,可将jar包仅仅保存在“仓库”中,有需要该文件时,就引用该文件接口,不需要复制文件过来占用空间..

JGJJZLP的博客 273

收藏!开源项目SpringBoot 微信点餐开源系统

点击上方“码农进阶之路”,选择“设为星标”回复“面经”获取面试资料作者:Tommmmmwww.jianshu.com/p/ae14101989f2文章编辑:Java知音架构前后端分离:...

二师兄撒欢之地 1万+
上一篇: 在 Spring Boot 中,如何干掉 if else
下一篇: 优秀!高级Java都这样优雅处理空值
Java思维导图
博客等级 码龄10年 306粉丝 71原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值