VO、DTO、DO、PO 的概念、区别和用处

ROS智能车定位导航仿真+功能包自带的地图实现+自己建立的地图实现 ROS智能车定位导航仿真一、前言二、效果图三、准备工作[1.在Ubuntu上安装ROS Kinetic](https://blog.youkuaiyun.com/qq_42585108/article/details/104327661)2.创建ROS工作区间①1创建racecar_ws和src文件夹②初始化工作空间③下载racecar源代码包,并编译工程四、启动仿真1.设置环境变量2.启动地图五、建图1.启动slam和rviz2 控制车辆(左侧有个控制窗口),WASD控制前左后右的运动就可以建图了:3.新建终端保存地 阅读详情

本篇文章主要讨论一下我们经常会用到的一些对象:VO、DTO、DO和PO。

由于不同的项目和开发人员有不同的命名习惯,这里我首先对上述的概念进行一个简单描述,名字只是个标识,我们重点关注其概念: 

概念 

  • VO(View Object):视图对象,用于展示层,它的作用是把某个指定页面(或组件)的所有数据封装起来。
  • DTO(Data Transfer Object):数据传输对象,这个概念来源于J2EE的设计模式,原来的目的是为了EJB的分布式应用提供粗粒度的数据实体,以减少分布式调用的次数,从而提高分布式调用的性能和降低网络负载,但在这里,我泛指用于展示层与服务层之间的数据传输对象。
  • DO(Domain Object):领域对象,就是从现实世界中抽象出来的有形或无形的业务实体。
  • PO(Persistent Object):持久化对象,它跟持久层(通常是关系型数据库)的数据结构形成一一对应的映射关系,如果持久层是关系型数据库,那么,数据表中的每个字段(或若干个)就对应PO的一个(或若干个)属性。 

模型 

下面以一个时序图建立简单模型来描述上述对象在三层架构应用中的位置 

 

  • 用户发出请求(可能是填写表单),表单的数据在展示层被匹配为VO。
  • 展示层把VO转换为服务层对应方法所要求的DTO,传送给服务层。
  • 服务层首先根据DTO的数据构造(或重建)一个DO,调用DO的业务方法完成具体业务。
  • 服务层把DO转换为持久层对应的PO(可以使用ORM工具,也可以不用),调用持久层的持久化方法,把PO传递给它,完成持久化操作。
  • 对于一个逆向操作,如读取数据,也是用类似的方式转换和传递。 

VO与DTO的区别

这里可能会有个疑问:既然DTO是展示层与服务层之间传递数据的对象,为什么还需要一个VO呢?


对!对于绝大部分的应用场景来说,DTO和VO的属性值基本是一致的,而且他们通常都是POJO,因此没必要多此一举,但不要忘记这是实现层面的思维,对于设计层面来说,概念上还是应该存在VO和DTO,因为两者有着本质的区别,DTO代表服务层需要接收的数据和返回的数据,而VO代表展示层需要显示的数据。


用一个例子来说明可能会比较容易理解:例如服务层有一个getUser的方法返回一个系统用户,其中有一个属性是gender(性别),对于服务层来说,它只从语义上定义:1-男性,2-女性,0-未指定,而对于展示层来说,它可能需要用“帅哥”代表男性,用“美女”代表女性,用“秘密”代表未指定。说到这里,可能你还会反驳,在服务层直接就返回“帅哥美女”不就行了吗?


对于大部分应用来说,这不是问题,但设想一下,如果需求允许客户可以定制风格,而不同风格对于“性别”的表现方式不一样,又或者这个服务同时供多个客户端使用(不同门户),而不同的客户端对于表现层的要求有所不同,那么,问题就来了。再者,回到设计层面上分析,从职责单一原则来看,服务层只负责业务,与具体的表现形式无关,因此,它返回的DTO,不应该出现与表现形式的耦合。


理论归理论,这到底还是分析设计层面的思维,是否在实现层面必须这样做呢?一刀切的做法往往会得不偿失,下面我马上会分析应用中如何做出正确的选择。

VO与DTO的应用

 上面只是用了一个简单的例子来说明VO与DTO在概念上的区别,本节将会告诉你如何在应用中做出正确的选择。


在以下才场景中,我们可以考虑把VO与DTO二合为一(注意:是实现层面):

  • 需求非常清晰稳定,而且客户端很明确只有一个的时候,没有必要把VO和DTO区分开来,这时候VO可以退隐,用一个DTO即可,为什么是VO退隐而不是DTO?回到设计层面,服务层的职责依然不应该与展示层耦合,所以,对于前面的例子,你很容易理解,DTO对于“性别”来说,依然不能用“帅哥美女”,这个转换应该依赖于页面的脚本(如JavaScript)或其他机制(JSTL、EL、CSS)
  • 即使客户端可以进行定制,或者存在多个不同的客户端,如果客户端能够用某种技术(脚本或其他机制)实现转换,同样可以让VO退隐

以下场景需要优先考虑VO、DTO并存:

  • 上述场景的反面场景
  • 因为某种技术原因,比如某个框架(如Flex)提供自动把POJO转换为UI中某些Field时,可以考虑在实现层面定义出VO,这个权衡完全取决于使用框架的自动转换能力带来的开发和维护效率提升与设计多一个VO所多做的事情带来的开发和维护效率的下降之间的比对。
  • 如果页面出现一个“大视图”,而组成这个大视图的所有数据需要调用多个服务,返回多个DTO来组装(当然,这同样可以通过服务层提供一次性返回一个大视图的DTO来取代,但在服务层提供一个这样的方法是否合适,需要在设计层面进行权衡)。

DTO与DO的区别

首先是概念上的区别,DTO是展示层和服务层之间的数据传输对象(可以认为是两者之间的协议),而DO是对现实世界各种业务角色的抽象,这就引出了两者在数据上的区别,例如UserInfo和User,对于一个getUser方法来说,本质上它永远不应该返回用户的密码,因此UserInfo至少比User少一个password的数据。而在领域驱动设计中,DO不是简单的POJO,它具有领域业务逻辑。

DTO与DO的应用

从上一个的例子中,会发现问题:既然getUser方法返回的UserInfo不应该包含password,那么就不应该存在password这个属性定义,但如果同时有一个createUser的方法,传入的UserInfo需要包含用户的password,怎么办? 

在设计层面,展示层向服务层传递的DTO与服务层返回给展示层的DTO在概念上是不同的,但在实现层面,我们通常很少会这样做(定义两个UserInfo,甚至更多),因为这样做并不见得很明智,我们完全可以设计一个完全兼容的DTO,在服务层接收数据的时候,不该由展示层设置的属性(如订单的总价应该由其单价、数量、折扣等决定),无论展示层是否设置,服务层都一概忽略,而在服务层返回数据时,不该返回的数据(如用户密码),就不设置对应的属性。


对于DO来说,还有一点需要说明:为什么不在服务层中直接返回DO呢?这样可以省去DTO的编码和转换工作,原因如下: 

  • 两者在本质上的区别可能导致彼此并不一一对应,一个DTO可能对应多个DO,反之亦然,甚至两者存在多对多的关系。
  • DO具有一些不应该让展示层知道的数据
  • DO具有业务方法,如果直接把DO传递给展示层,展示层的代码就可以绕过服务层直接调用它不应该访问的操作,对于基于AOP拦截服务层来进行访问控制的机制来说,这问题尤为突出,而在展示层调用DO的业务方法也会因为事务的问题,让事务难以控制。
  • 对于某些ORM框架(如Hibernate)来说,通常会使用“延迟加载”技术,如果直接把DO暴露给展示层,对于大部分情况,展示层不在事务范围之内(Open session in view在大部分情况下不是一种值得推崇的设计),如果其尝试在Session关闭的情况下获取一个未加载的关联对象,会出现运行时异常(对于Hibernate来说,就是LazyInitiliaztionException)。
  • 从设计层面来说,展示层依赖于服务层,服务层依赖于领域层,如果把DO暴露出去,就会导致展示层直接依赖于领域层,这虽然依然是单向依赖,但这种跨层依赖会导致不必要的耦合。

对于DTO来说,也有一点必须进行说明,就是DTO应该是一个“扁平的二维对象”,举个例子来说明:如果User会关联若干个其他实体(例如Address、Account、Region等),那么getUser()返回的UserInfo,是否就需要把其关联的对象的DTO都一并返回呢?

如果这样的话,必然导致数据传输量的大增,对于分布式应用来说,由于涉及数据在网络上的传输、序列化和反序列化,这种设计更不可接受。如果getUser除了要返回User的基本信息外,还需要返回一个AccountId、AccountName、RegionId、RegionName,那么,请把这些属性定义到UserInfo中,把一个“立体”的对象树“压扁”成一个“扁平的二维对象”,笔者目前参与的项目是一个分布式系统,该系统不管三七二十一,把一个对象的所有关联对象都转换为相同结构的DTO对象树并返回,导致性能非常的慢。

DO与PO的区别

DO和PO在绝大部分情况下是一一对应的,PO是只含有get/set方法的POJO,但某些场景还是能反映出两者在概念上存在本质的区别: 

  • DO在某些场景下不需要进行显式的持久化,例如利用策略模式设计的商品折扣策略,会衍生出折扣策略的接口和不同折扣策略实现类,这些折扣策略实现类可以算是DO,但它们只驻留在静态内存,不需要持久化到持久层,因此,这类DO是不存在对应的PO的。
  • 同样的道理,某些场景下,PO也没有对应的DO,例如老师Teacher和学生Student存在多对多的关系,在关系数据库中,这种关系需要表现为一个中间表,也就对应有一个TeacherAndStudentPO的PO,但这个PO在业务领域没有任何现实的意义,它完全不能与任何DO对应上。这里要特别声明,并不是所有多对多关系都没有业务含义,这跟具体业务场景有关,例如:两个PO之间的关系会影响具体业务,并且这种关系存在多种类型,那么这种多对多关系也应该表现为一个DO,又如:“角色”与“资源”之间存在多对多关系,而这种关系很明显会表现为一个DO——“权限”。
  • 某些情况下,为了某种持久化策略或者性能的考虑,一个PO可能对应多个DO,反之亦然。例如客户Customer有其联系信息Contacts,这里是两个一对一关系的DO,但可能出于性能的考虑(极端情况,权作举例),为了减少数据库的连接查询操作,把Customer和Contacts两个DO数据合并到一张数据表中。反过来,如果一本图书Book,有一个属性是封面cover,但该属性是一副图片的二进制数据,而某些查询操作不希望把cover一并加载,从而减轻磁盘IO开销,同时假设ORM框架不支持属性级别的延迟加载,那么就需要考虑把cover独立到一张数据表中去,这样就形成一个DO对应对个PO的情况。
  • PO的某些属性值对于DO没有任何意义,这些属性值可能是为了解决某些持久化策略而存在的数据,例如为了实现“乐观锁”,PO存在一个version的属性,这个version对于DO来说是没有任何业务意义的,它不应该在DO中存在。同理,DO中也可能存在不需要持久化的属性。

DO与PO的应用 

  • 由于ORM框架的功能非常强大而大行其道,而且JavaEE也推出了JPA规范,现在的业务应用开发,基本上不需要区分DO与PO,PO完全可以通过JPA,Hibernate Annotations/hbm隐藏在DO之中。虽然如此,但有些问题我们还必须注意:
  • 对于DO中不需要持久化的属性,需要通过ORM显式的声明,如:在JPA中,可以利用@Transient声明。
  • 对于PO中为了某种持久化策略而存在的属性,例如version,由于DO、PO合并了,必须在DO中声明,但由于这个属性对DO是没有任何业务意义的,需要让该属性对外隐藏起来,最常见的做法是把该属性的get/set方法私有化,甚至不提供get/set方法,但对于Hibernate来说,这需要特别注意,由于Hibernate从数据库读取数据转换为DO时,是利用反射机制先调用DO的空参数构造函数构造DO实例,然后再利用JavaBean的规范反射出set方法来为每个属性设值,如果不显式声明set方法,或把set方法设置为private,都会导致Hibernate无法初始化DO,从而出现运行时异常,可行的做法是把属性的set方法设置为protected。
  • 对于一个DO对应多个PO,或者一个PO对应多个DO的场景,以及属性级别的延迟加载,Hibernate都提供了很好的支持,请参考Hibnate的相关资料。

到目前为止,已经比较清晰的了解VO、DTO、DO、PO的概念、区别和实际应用了。通过上面的详细分析,我们还可以总结出一个原则 

分析设计层面和实现层面完全是两个独立的层面,即使实现层面通过某种技术手段可以把两个完全独立的概念合二为一,在分析设计层面,我们仍然(至少在头脑中)需要把概念上独立的东西清晰的区分开来,这个原则对于做好分析设计非常重要(工具越先进,往往会让我们越麻木)。 

PHP服务端 苹果支付(IAP)处理 公司做的app需要做IAP订阅支付,开始觉得和微信的支付流程差不多,做起来还是有点麻烦,主要是网上的文章很少,不能拿来主义。自己做完总结一下,希望对小伙伴们有帮助我就很欣慰了。代码写的不好 不要喷我。。。 首先讲一下我的业务逻辑,也就是php服务端需要做什么事情。 先上图: 下面我详细的讲一下每... 阅读详情

相关推荐

Flightmare实战:从零搭建强化学习无人机控制环境

本文详细介绍了从零开始搭建Flightmare强化学习无人机控制环境的完整流程。内容包括环境准备、核心库安装、依赖冲突解决,以及如何运行PPO算法示例进行训练与可视化测试。文章还提供了环境配置、自定义任务修改及常见问题的避坑指南,帮助开发者快速上手这一模块化的无人机RL仿真平台。

weixin_29081101的博客 356

DTO、DAO、VO、BO、DO、PO、POJO的区别

在Java开发中,正确地使用这些不同类型的实体对象,有助于清晰地划分系统的各个层次,提高代码的模块化和可维护性。例如,VO专注于视图表示,DTO用于服务间的数据传输,而PO则直接与数据库交互。通过这种方式,开发者可以构建出更加灵活和可扩展的应用程序。

后端小知识呀 1829

瑞芯微RK3568开发板实战:Android11系统parameter.txt文件配置全解析(附常见问题排查)

本文深入解析了瑞芯微RK3568开发板在Android 11系统下parameter.txt文件的配置要点与实战技巧。作为BootLoader启动阶段的核心蓝图,该文件决定了硬件初始化、分区布局及电源管理。文章详细拆解了身份标识、GPIO控制(PWR_HLD)、命令行参数及分区表等关键字段的配置逻辑,并针对RK3568平台与Android 11特性提供了专项适配策略,最后附带了启动失败、分区异常等常见问题的深度排查方法。

php55的博客 895

浅析VO、DTO、DO、PO的概念、区别和用处

概念: VO(View Object):视图对象,用于展示层,它的作用是把某个指定页面(或组件)的所有数据封装起来。 DTO(Data Transfer Object):数据传输对象,这个概念来源于J2EE的设计模式,原来的目的是为了EJB的分布式应用提供粗粒度的数据实体,以减少分布式调用的次数,从而提高分布式调用的性能和降低网络负载,但在这里,我泛指用于展示层与服务层之间的数据传输对象。 DO(Domain Object):领域对象,就是从现实世界中抽象出来的有形或无形的业务实体。 PO(Persiste

YHJ 3万+

激光SLAM算法性能对比:在Ubuntu20.04上实测Point-LIO/FAST_LIO2/Faster-LIO的运行效果

本文在Ubuntu 20.04平台上对Point-LIO、FAST-LIO2和Faster-LIO三款激光SLAM算法进行了深度实测与性能对比。通过量化分析绝对轨迹误差、CPU/内存占用及单帧处理延迟等核心指标,结合室内外场景数据,为高精度测绘、服务机器人及自动驾驶等不同应用场景提供了清晰的选型指南和实战调优建议。

weixin_28335283的博客 368

Agent 长期记忆三代演进:从 RAG 到 Memory Graph,mem0 / Zep / LangMem / Letta 深度横评

文章摘要 2026年,Agent长期记忆技术迎来关键突破,OpenAI、Anthropic等厂商通过扩大上下文窗口和推出记忆工具,推动长期记忆从工程补丁发展为独立技术层。本文通过分析三代记忆架构演进(RAG→结构化Fact→MemoryGraph)和四大方案(mem0/Zep/LangMem/Letta)的8维度横评,揭示以下核心观点: 长上下文≠长期记忆:128K上下文如同RAM,仍需硬盘式记忆层筛选和结构化存储,避免“Context Rot”导致的准确率下降。 三代架构演进: Gen1(RAG):向量检

LDZKKJ的博客 1404

简单说下VO、PO、DO、DTO的主要区别及应用场景

  好久没有更新文章了,最近刚入职熟悉了几个项目,因此看了很多代码,发现里面有很多实体采用了VO、DO、DTO这样的名称结尾,之前大致了解过他们的含义以及他们的使用场景,今天特地整理一下记录下来。

黄勇的博客 5213

Bash Shell 系统巡检脚本

部分安全相关检查需要root权限,建议通过sudo运行完整检查。

老韩的Linux云计算架构师进阶之路 94

DO、DTO和VO分别是什么?

1. DO(数据对象):是持久性对象,也就是与数据库表对应的实体类,用于对数据进行持久化,一般包括了对应表的所有字段,并且一一对应,不添加额外的业务称之为Entity。2. DTO(数据传输对象):是用于数据传输的对象,通常包含需要传输的数据属性,可以用来封装多个DO的属性,在服务之间进行数据传输,以降低网络传输量的开销。在实际的开发中,常常使用DTO来解决数据传输的问题,而VO一般用作承载表示层的数据,如前端的展示数据,而DO一般用作持久层,用于数据库操作。

java小白翻身 4525

第 13 章:Spring AI Alibaba MCP 与 Nacos3 — 企业级MCP服务

理解Spring AI Alibaba 框架下的MCP服务与Nacos注册中心整合的必要性,学会Spring AI Alibaba-基于Nacos的MCP实现方法

paopao_wu的专栏 788

1、JMP脚本编程全面指南:从基础到高级应用

本博客全面介绍了JMP脚本编程的各个方面,从JMP基础和JSL入门,到数据类型、数据结构、编程方法、数据表操作、图形与三维场景脚本,再到应用程序创建与扩展功能。内容涵盖脚本工具使用、常见任务实现、兼容性说明及未来发展趋势,旨在帮助用户掌握JMP脚本语言的强大功能,提升数据分析的自动化与定制化能力。适合从初学者到高级用户的深入学习与实践参考。

flink9streamer的博客 266

DO、VO、DTO

DTO – 服务实现中的核心数据 浅析VO、DTO、DO、PO的概念、区别和用处DO、DTO和VO分层设计的好处实体类(VO,DO,DTO)的划分

菜鸡程序猿的博客 1639

Microsemi Libero系列教程(全网首发)

关于Libero IDE和Libero SoC Libero分为Libero IDE和Libero SoC,Libero IDE最新版本是v9.2 SP3(2016年4月4日)已经不再更新维护了,而Libero SoC是Libero IDE的升级版,官方推荐的开发工具,文中的Libero指的是Libero SoC。 Libero SoC Libero® SoC是Microsemi(美高森美)官方...

whik1194的博客 2万+

VO,DTO,DO,PO的概念、区别和用处

1、概念 VO(View Object):视图层,用于展示层,它的作用是把某个指定页面(或组件)的所有数据封装起来。 DTO(Data Transfer Object):数据传输对象,这个概念来源于J2EE的设计模式,原来的目的是为了EJB的分布式应用提供粗粒度的数据实体,以减少分布式调用的次数,从而提高分布式调用的性能和降低网络负载,但在这里,我泛指用于展示层与服务层之间的数据传输对象。 DO(Domain Object):领域对象,就是从现实世界中抽象出来的有形或无形的业务实体。 PO(Pers

。 6万+

LinePhone3.2.7(android端最新版本) sip客户端

SIP客户端For android:LinePhone3.2.7(最新版本),官网地址:http://www.linphone.org/

TMS_WebGMaps_1.9.8.0_Full_Source

TMS_WebGMaps_1.9.8.0_Full_Source 全源码 delphi cbuilder

VO、DTO、DO、PO的概念、区别和用处

在设计层面,展示层向服务层传递的DTO与服务层返回给展示层的DTO在概念上是不同的,但在实现层面,我们通常很少会这样做(定义两个UserInfo,甚至更多),因为这样做并不见得很明智,我们完全可以设计一个完全兼容的DTO,在服务层接收数据的时候,不该由展示层设置的属性(如订单的总价应该由其单价、数量、折扣等决定),无论展示层是否设置,服务层都一概忽略,而在服务层返回数据时,不该返回的数据(如用户密码),就不设置对应的属性。

Nothing is impossible to a willing heart. 3389

android 蓝牙通讯demo

android 下蓝牙通讯demo,实现了发现蓝牙,使能蓝牙,通过蓝牙发送消息。

SpringBoot中VO,DTO,DO,PO的概念、区别和用处

VO(View Object):视图层,用于展示层,它的作用是把某个指定页面(或组件)的所有数据封装起来。 DTO(Data Transfer Object):数据传输对象,这个概念来源于J2EE的设计模式,原来的目的时为了EJB的分布式应用提供粗粒度的数据实体,以减少分布式条用的次数,从而提高分布式调用的性能和降低网络负载,但在这里,我泛指用于展示层与服务层之间的数据传输对象。 DO(Domain Object):领域对象,就是从现实世界中抽象出来的有形或无形的业务实体。 PO(Persistent Ob

乐昊的博客 3471

关于VO、DTO、DO、PO的概念、区别和用处

不该由展示层设置的属性(如订单的总价应该由其单价、数量、折扣等决定),无论展示层是否设置,服务层都一概忽略,而在服务层返回数据时,不该返回的数据(如用户密码),就不设置对应的属性。服务层有一个getUser的方法返回一个系统用户,其中有一个属性是gender(性别),对于服务层来说,它只从语义上定义:1-男性,2-女性,0-未指定,而对于展示层来说,但在实现层面,我们通常很少会这样做(定义两个UserInfo,甚至更多),因为这样做并不见得很明智,完全可以设计一个完全兼容的DTO,在服务层接收数据的时候,

qq_41834086的博客 2156

简述VO、DTO、DO、PO的概念、区别和用处

在软件开发中,尤其是在使用分层架构的企业应用中,常常会听到VO、DTO、DO、PO这些术语。这些都是数据对象(Data Object),但它们在应用中扮演着不同的角色。理解这些概念并在适当的场景中使用它们,可以帮助开发者更好地组织代码和架构,提高软件的可维护性和可扩展性。在实际开发中,根据项目的具体需求和设计,这些对象的定义和使用可能会有所不同。

m0_48205251的博客 1731

VO、DTO、DO、PO的概念、区别与用处

本文解析了软件开发中常见的四种对象模型:VO(值对象)、DTO(数据传输对象)、DO(领域对象)和PO(持久化对象)。VO用于展示层数据封装,不可变;DTO负责跨层/跨系统数据传输;DO包含业务逻辑,代表领域概念;PO则与数据库表一一映射。四者在用途、可变性、逻辑包含等方面存在显著差异:VO面向展示,DTO专注传输,DO处理业务,PO实现持久化。文章通过典型场景和代码示例说明其协同工作流程,并给出选择策略,强调合理区分这些对象可提升系统可维护性、安全性和性能。核心在于根据需求稳定性、数据安全和架构分层原则灵

1308

JAVA VO、DTO、DO、PO的概念、区别和用处

概念VO(View Object):视图对象,用于展示层,它的作用是把某个指定页面(或组件)的所有数据封装起来。 DTO(Data Transfer Object):数据传输对象,这个概念来源于J2EE的设计模式,原来的目的是为了EJB的分布式应用提供粗粒度的数据实体,以减少分布式调用的次数,从而提高分布式调用的性能和降低网络负载,但在这里,我泛指用于展示层与服务层之间的数据传输对象。 DO(D

Heqianqian的博客 9112

VO,DTO,DO,PO的概念、区别和用处

一、概念 VO(View Object):视图层,用于展示层,它的作用是把某个指定页面(或组件)的所有数据封装起来。 DTO(Data Transfer Object):数据传输对象,这个概念来源于J2EE的设计模式,原来的目的是为了EJB的分布式应用提供粗粒度的数据实体,以减少分布式调用的次数,从而提高分布式调用的性能和降低网络负载,但在这里,我泛指用于展示层与服务层之间的数据传输对象。 ...

fox_bert的博客 2527
上一篇: MySQL 索引
下一篇: POI导出 Excel 加水印支持 SXSSFWorkbook 和 XSSFWorkbook 模式
bbccloud
博客等级 码龄11年 23粉丝 25原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值