性生活时间-最新地址dto!*-性生活时间本月更新~~~~~dto

您的访问出错了(404错误)
很抱歉,您要访问的页面不存在。
1、请检查您输入的地址是否正确。
进行查找。
3、感谢您使用本站,1秒后自动跳转  本文将介绍DDD分层架构中广泛使用的数据传输对象Dto,并且与领域实体Entity,查询实体QueryObject,视图实体ViewModel等几种实体进行比较。
领域实体为何不能一统江湖?
  当你阅读我或其它博主提供的示例代码时,会发现几种类型的实体,这几种实体初步看上去区别不大,只是名称不同,特别在这些示例非常简单的情况下更是如此。你可能会疑惑为何要搞得这么复杂,采用一种实体不是更好?
  在最理想的情况下,我们只想采用领域实体Entity进行所有的操作。
  领域实体是领域层的核心,是业务逻辑的主要放置场所。换句话说,领域实体中包含了大量业务逻辑方法。
领域实体在表现层进行模型绑定时可能遇到障碍
  如果领域实体中的属性都包含getter和setter,并且所有属性都是public的,那么,使用这个Entity的程序员可能会绕过业务方法,直接操作属性进行赋值。
  为属性直接赋值,是面向数据的过程式思维,而调用方法是面向对象的方式,这也是领域模型的核心所在。
  所以为了强制实施业务规则,必须把业务方法操作过的属性的setter访问器隐藏起来,否则这个方法不会有人调用。
  当领域实体某些属性的setter被隐藏后,直接在表现层操作领域实体将变得困难,因为Mvc或Wpf的模型绑定只能操作public的属性。
序列化领域实体可能遇到障碍
  哪怕你的系统没有使用分布式,比如只是一个Mvc网站,但由于前端要求越来越高,客户端很多时候需要通过ajax与服务端进行交流,一般采用json格式传递数据,这就要求你的实体能够序列化。
  对领域实体进行序列化,首先需要考虑的问题是,可能序列化一个较大的对象图,从而导致不必要的开销。
  领域实体一般包含导航属性指向其它领域实体,其它的领域实体可能包含更多导航属性,从而组成一个对象图。如果采用Serializable特性进行序列化,并且没有指定其它序列化选项,可能导致把一个庞大的对象图序列化并进行网络传输。
  另一个问题是,复杂的领域实体可能包含循环引用,从而导致序列化失败。
  对于序列化,一个更好的选择是采用DataContract特性,被DataContract修饰过的类成员,不会被自动序列化,必须在成员上明确指定DataMember特性。
  DataMember在一定程度上可以缓解上述问题,比如减少需要序列化的数据,不序列化循环引用的对象等,但无法从根本上解决问题。
领域实体无法应对多客户端应用需求
  对于不同的客户端,可能需要的数据和格式不同,这属于应用层需求,而领域实体只有一个,在领域实体上通过标记DataMember进行序列化费力不讨好,无法满足复杂的应用需求。
  哪怕你只有一个Mvc网站,如果页面上需要显示一些领域实体不存在的数据,你根据这个需求,直接在领域实体上增加属性是非常糟糕的做法,会严重污染你的领域模型,将大大降低领域实体的复用能力。
  从以上可以看出,对于一个比较复杂的系统,单凭领域实体很难完成任务,将太多的职责强加到领域实体上,会导致领域实体严重变形。
数据传输对象介绍
  数据传输对象,即Data Transfer Object,简称DTO。
  一个为了减少方法调用次数而在进程间传输数据的对象,《企业应用架构模式》如是说。
  可以看出,DTO用于分布式环境,主要用来解决分布式调用的性能问题。同一进程内的对象调用,速度是非常快的,但跨进程调用,甚至跨网络调用,性能下降N个数量级。为了提升性能,需要减少调用次数,这就要求把多次调用的结果打包成一个对象,在一次调用中返回尽量多的数据。
  上面是DTO的原始含义,下面来看看我的山寨用法。
  虽然我也取名为DTO,但我的动机并不完全是一次打包更多数据来提升性能,而是解决上面提到的几个问题,当然它们之间有一定关系,可以看作一种变种用法。
  DTO是一个贫血对象,也就是它里面基本没有方法,只有一堆属性,并且所有属性都具有public的getter和setter访问器。
  DTO拥有public的setter访问器,方便的解决了表现层的模型绑定问题。
  由于DTO不执行业务操作,仅用于传递数据,所以不应该定义非常复杂的对象引用关系,这样就避免了循环引用,解决了对象序列化的问题。
  DTO可以根据应用需求定义成不同的粒度,在一般情况下,DTO是聚合粒度,也就是说,一个领域层的聚合对应一个DTO,这样做的一个好处是方便对CRUD操作进行抽象以及代码生成。
  界面如果想保持简单,应该尽量一个界面操作一个聚合,将聚合的数据映射到DTO后,传给视图展示。
  对于更加复杂的界面,需要在一个界面操作多个聚合,这种情况下,把需要的全部数据打包到DTO进行操作。
  从以上介绍中,你应该了解DTO不能理解为单表操作,它可以包含你需要的全部数据。
  DTO处于应用层,在表现层与领域层之间传递数据。
  DTO由应用层服务使用,应用层服务从仓储中获得聚合,并调用DTO转换器将聚合映射为DTO,再将DTO传递给表现层。
  关于应用层服务,后续再专门介绍。
  聚合与DTO的转换,看上去是一个简单问题,在聚合与DTO几乎完全一致的情况下,采用映射组件将非常省力。很多人采用AutoMapper,但它的性能稍微差了点,EmitMapper是更好的选择,性能接近硬编码。
  当DTO与聚合显著不同时,我发现手工编码更加清晰高效。我采用代码生成器创建出一个代码基础,在有个性化需求时,手工修改映射代码。
  我总是采用一个静态类来扩展DTO和聚合,为它们添加相关的转换方法。
using Biz.Security.Domains.M
namespace Biz.Security.Services.Dtos {
/// &summary&
/// 应用程序数据传输对象扩展
/// &/summary&
public static class ApplicationDtoExtension {
/// &summary&
/// 转换为应用程序实体
/// &/summary&
/// &param name="dto"&应用程序数据传输对象&/param&
public static Application ToEntity( this ApplicationDto dto ) {
return new Application( dto.Id.ToGuid() ) {
Code = dto.Code,
Name = dto.Name,
Note = dto.Note,
Enabled = dto.Enabled,
CreateTime = dto.CreateTime,
Version = dto.Version,
/// &summary&
/// 转换为应用程序数据传输对象
/// &/summary&
/// &param name="entity"&应用程序实体&/param&
public static ApplicationDto ToDto( this Application entity ) {
return new ApplicationDto {
Id = entity.Id.ToString(),
Code = entity.Code,
Name = entity.Name,
Note = entity.Note,
Enabled = entity.Enabled,
CreateTime = entity.CreateTime,
Version = entity.Version,
DTO 与 ViewModel比较
  ViewModel是为特定视图专门定义的实体对象,专为该视图服务。
  对于WPF,ViewModel是必须的,用来支持MVVM模式进行双向绑定。
  那么MVC呢,一定需要它吗?
  由于采用了DTO,在一般情况下,我都把这个DTO当作ViewModel来使用。如果界面上需要某个属性,我会直接添加到DTO上。
  一个例外是,如果MVC的界面非常复杂,我感觉把大量的垃圾属性加到DTO上不合适,就会创建专门的ViewModel。
查询实体介绍
  查询实体这个说法,是我乱取的,估计你在其它地方也没有听说过。使用它的原因,是用来配合我的查询组件一起工作。
  我前面已经介绍过查询相关的内容,核心思想是通过判断一个可空属性,自动完成空值判断,这是一个强大的特性,帮助你免于编写大量杂乱无章的判断。
  查询实体的基本特征就是所有属性必须可空,并且它足够简单,不会拥有集合那样的子对象,所有属性都是扁平化的。
  通过传递查询实体,表现层可以做到尽量简单,由于表现层支持模型绑定,甚至不需要代码,省力是我搭建框架的一个基本出发点。
  当然查询实体只支持简单查询,不支持灵活的动态查询,比如让客户设置查询运算符等,暂时没有这方面的需求,如果后续有需求,会扩展一个出来。
  查询实体示例:
using ponentModel.DataA
using Util.Domains.R
namespace Biz.Security.Domains.Queries {
/// &summary&
/// 应用程序查询实体
/// &/summary&
public class ApplicationQuery : Pager {
/// &summary&
/// 应用程序编号
/// &/summary&
[Display( Name = "应用程序编号" )]
public System.Guid? ApplicationId { get; set; }
private string _code = string.E
/// &summary&
/// 应用程序编码
/// &/summary&
[Display( Name = "应用程序编码" )]
public string Code {
get { return _code == null ? string.Empty : _code.Trim(); }
set { _code = }
private string _name = string.E
/// &summary&
/// 应用程序名称
/// &/summary&
[Display( Name = "应用程序名称" )]
public string Name {
get { return _name == null ? string.Empty : _name.Trim(); }
set { _name = }
private string _note = string.E
/// &summary&
/// &/summary&
[Display( Name = "备注" )]
public string Note {
get { return _note == null ? string.Empty : _note.Trim(); }
set { _note = }
/// &summary&
/// &/summary&
[Display( Name = "启用" )]
public bool? Enabled { get; set; }
/// &summary&
/// 起始创建时间
/// &/summary&
[Display( Name = "起始创建时间" )]
public System.DateTime? BeginCreateTime { get; set; }
/// &summary&
/// 结束创建时间
/// &/summary&
[Display( Name = "结束创建时间" )]
public System.DateTime? EndCreateTime { get; set; }
/// &summary&
/// 添加描述
/// &/summary&
protected override void AddDescriptions() {
base.AddDescriptions();
AddDescription( "应用程序编号", ApplicationId );
AddDescription( "应用程序编码", Code );
AddDescription( "应用程序名称", Name );
AddDescription( "备注", Note );
AddDescription( "启用", Enabled.Description() );
AddDescription( "起始创建时间", BeginCreateTime );
AddDescription( "结束创建时间", EndCreateTime );
最后来总结一下:
  1.&领域实体是系统的中心,是业务逻辑的主要放置场所,应该尽量关闭业务逻辑操作的属性,以避免有人能绕过你的方法直接操作数据。
  2.&DTO是数据传输对象,原义是用来在分布式系统中一次传输更多数据,以减少调用次数,提升性能。
  3.&我的DTO用法离原义相去甚远,只是借用了DTO的名词,属于变种。DTO为我解决了如下几个问题:
领域实体在表现层进行模型绑定时可能失败
序列化领域实体可能失败
领域实体无法应对多客户端应用需求,通过创建多套DTO甚至应用层,可以为不同的应用提供服务,而领域层不变,它是系统的中心。
  4.&DTO是包含大量属性,没有方法的贫血实体,所有属性都开放getter和setter,以方便模型绑定和序列化。
  5.&DTO一般情况下是聚合去除方法后的模样,主要好处是方便抽象CRUD及代码生成。
  6.&DTO位于应用层,由应用层服务操作它。
  7.&DTO的映射可以采用映射组件,也可以代码生成方便随时修改,以你觉得方便为主。
  8.&仅在WPF环境下才需要为每个视图创建一个对应的ViewModel,MVC一般使用DTO即可,仅为复杂界面创建ViewModel。
  9.&查询实体是为了配合查询组件引入的构造,目的是帮助查询组件完成空值判断,并且简化表现层的调用。
  本文分享了我在几个构造类型上的认识和经验,希望大家积极讨论,更希望高手能指正我的不足,帮助我与大家一起进步。
  .Net应用程序框架交流QQ群: ,欢迎有兴趣的朋友加入讨论。
  .Net Easyui开发交流QQ群(本群仅限Easyui开发者,非Easyui开发者勿进):
  谢谢大家的持续关注,我的博客地址:/xiadao521/
阅读(...) 评论()在分布式系统中,客户端和服务器端交互有两种情形:第一个是客户端从服务器端读取数据;第二个是客户端将本身的数据传递给服务器端。
&当有客户端要向服务器端传输大量数据的时候,可以通过一个包含要传输的所有数据的方法调用来完成。这在小数据量的时候缺点并不明显,但是如果要传递包含有大量信息的数据的时候,这将变得难以忍受。下面的方法是任何人看了都会害怕的:
public void save(String id,String number,String name,int type,int
height,int width,BigDecimal weight,BigDecimal price,String
description)
这种接口也是非常的脆弱,一旦需要添加或者删除某个属性,方法的签名就要改变。
当客户端要从服务器端取得大量数据的时候,可以使用多个细粒度的对服务器端的调用来获取数据。比如:
ISomeInterface intf = RemoteService.getSomeInterface();
System.out.println("您要查询的商品的资料为:");
System.out.println("编号:"+intf.getNumber(id));
System.out.println("姓名:"+intf.getName(id));
System.out.println("类型:"+intf.getType(id));
System.out.println("高度:"+intf.getHeight(id));
System.out.println("宽度:"+intf.getWidth(id));
System.out.println("价格:"+intf.getPrice(id));
System.out.println("描述信息:"+intf.getDescription(id));
这种方式中每一个getXxx方法都是一个对服务器的远程调用,都需要对参数和返回值进行序列化和反序列化,而且服务器进行这些调用的时候还需要进行事务、权限、日志的处理,这会造成性能的大幅下降。如果没有使用客户端事务的话还会导致这些调用不在一个事务中从而导致数据错误。
系统需要一种在客户端和服务器端之间高效、安全地进行数据传输的技术。DTO(Data Transfer
Object,数据传送对象)是解决这个问题的比较好的方式。DTO是一个普通的Java类,它封装了要传送的批量的数据。当客户端需要读取服务器端的数据的时候,服务器端将数据封装在DTO中,这样客户端就可以在一个网络调用中获得它需要的所有数据。
还是上面的例子,服务器端的服务将创建一个DTO并封装客户端所需要的属性,然后返回给客户端:
ISomeInterface intf = RemoteService.getSomeInterface();
SomeDTOInfo info = intf.getSomeData(id);
System.out.println("您要查询的商品的资料为:");
System.out.println("编号:"+info.getNumber());
System.out.println("姓名:"+info.getName());
System.out.println("类型:"+info.getType());
System.out.println("高度:"+info.getHeight());
System.out.println("宽度:"+info.getWidth());
System.out.println("价格:"+info.getPrice());
System.out.println("描述信息:"+info.getDescription());
使用DTO的时候,一个主要问题是选择什么样的DTO:这个DTO能够容纳哪些数据,DTO的结构是什么,这个DTO是如何产生的。DTO是服务器端和客户端进行通信的一个协议格式,合理的DTO设计将会使得服务器和客户端的通信更加顺畅。在水平开发模式(即每个开发人员负责系统的不同层,A专门负责Web表现层的开发,B专门负责服务层的开发)中,在项目初期合理的DTO设计会减少各层开发人员之间的纠纷;在垂直开发模式(即每个开发人员负责不同模块的所有层,A专门负责库存管理模块的开发,B专门负责固定资产模块的开发)中,虽然开发人员可以自由地调整DTO的结构,但是合理的DTO设计仍然会减少返工的可能性。
实现DTO最简单的方法是将服务端的域对象(比如Hibernate中的PO、EJB中的实体Bean)进行拷贝然后作为DTO传递。采用域对象做DTO比较简单和清晰,因为DTO与域模型一致,所以了解一个结构就够了。这样做也免去了DTO的设计,使得开发工作变得更快。这种做法的缺点是域DTO的粒度太大以至于难以满足客户端的细粒度的要求,客户端可能不需要访问那些域中的所有属性,也可能需要不是简单地被封装在域中的数据,当域DTO不能满足要求的时候就需要更加细粒度的DTO方案。目前主流的DTO解决方案有定制DTO、数据传送哈希表、数据传送行集。
域模型是指从业务模型中抽取出来的对象模型,比如商品、仓库。在J2EE中,最常见的域模型就是可持久化对象,比如Hibernate中的PO、EJB中的实体Bean。
在分布式系统中,域模型完全位于服务器端。根据持久化对象可否直接传递到客户端,域对象可以分为两种类型:一种是服务器端的持久化对象不可以直接传递到客户端,比如EJB中的实体Bean是不能被传递到客户端的;一种是持久化对象可以直接传递到客户端,比如Hibernate中的PO变为detached
object以后就可以传递到客户端。
EJB中的实体Bean不能直接传递到客户端,而且实体Bean不是一个简单的JavaBean,所以也不能通过深度克隆(deep
clone)创造一个新的可传递Bean的方式产生DTO。针对这种情况,必须编写一个简单的JavaBean来作为DTO。
下面是一个系统用户的实体Bean的代码:
abstract public class SystemUserBean implements EntityBean
EntityContext entityC
&&& public
java.lang.String ejbCreate(java.lang.String userId)
&&&&&&&&&&&
throws CreateException
setUserId(userId);
&&& public void
ejbPostCreate(java.lang.String userId)
&&&&&&&&&&&
throws CreateException
&&& public void
ejbRemove() throws RemoveException
&&& public
abstract void setUserId(java.lang.String userId);
&&& public
abstract void setName(java.lang.String name);
&&& public
abstract void setPassword(java.lang.String password);
&&& public
abstract void setRole(java.lang.Integer role);
&&& public
abstract java.lang.String getUserId();
&&& public
abstract java.lang.String getName();
&&& public
abstract java.lang.String getPassword();
&&& public
abstract java.lang.Integer getRole();
&&& public void
&&& public void
ejbStore()
&&& public void
ejbActivate()
&&& public void
ejbPassivate()
&&& public void
unsetEntityContext()
this.entityContext =
&&& public void
setEntityContext(EntityContext entityContext)
this.entityContext = entityC
根据需要我们设计了如下的DTO:
public class SystemUserDto implements Serializable
&&& private
String userId;
&&& private
&&& private
&&& private
&&& public void
setUserId(String userId)
this.userId = userId;
&&& public
String getUserId()
return userId;
&&& public void
setName(String name)
this.name =
&&& public
String getName()
&&& public void
setPassword(String password)
this.password =
&&& public
String getPassword()
&&& public void
setRole(Integer role)
this.role =
&&& public
Integer getRole()
为了实现DTO的生成,这里还需要一个将实体Bean转换为一个DTO的工具,我们称其为DTOAssembler:
public class SystemUserDtoAssembler
&&& public
static SystemUserDto createDto(SystemUser systemUser)
SystemUserDto systemUserDto = new SystemUserDto();
if (systemUser != null)
&&&&&&&&&&&
systemUserDto.setUserId(systemUser.getUserId());
&&&&&&&&&&&
systemUserDto.setName(systemUser.getName());
&&&&&&&&&&&
systemUserDto.setPassword(systemUser.getPassword());
&&&&&&&&&&&
systemUserDto.setRole(systemUser.getRole());
return systemUserD
&&& public
static SystemUserDto[] createDtos(Collection systemUsers)
List list = new ArrayList();
if (systemUsers != null)
&&&&&&&&&&&
Iterator iterator = systemUsers.iterator();
&&&&&&&&&&&
while (iterator.hasNext())
&&&&&&&&&&&
&&&&&&&&&&&&&&&
list.add(createDto((SystemUser) iterator.next()));
&&&&&&&&&&&
SystemUserDto[] returnArray = new SystemUserDto[list.size()];
return (SystemUserDto[]) list.toArray(returnArray);
为一个实体Bean产生DTO是非常麻烦的事情,所以像JBuilder这样的IDE都提供了根据实体Bean直接生成DTO类和DTOAssembler的代码生成器。
相对于重量级的实体Bean来说,使用Hibernate的开发人员则轻松多了,因为Hibernate中的PO就是一个普通的JavaBean对象,而且PO可以随时脱离Hibernate被传递到客户端,不用进行复杂的DTO和DTOAssembler的开发。不过缺点也是有的,当一个PO脱离Hibernate以后如果客户端访问其并没有在服务器端加载的属性的时候就会抛出惰性加载的异常,而如果对PO不采用惰性加载的话则会导致Hibernate将此PO直接或者间接关联的对象都取出来的问题,在有的情况下这是灾难性的。在案例系统中是使用DTOGenerator的方式来解决这种问题的。
无论是哪种方式,客户端都不能直接访问服务器端的域模型,但是客户端却希望能和域模型进行协作,因此需要一种机制来允许客户端像操纵域模型一样操作DTO,这样客户端可以对DTO进行读取、更新的操作,就好像对域模型做了同样的操作一样。客户端对DTO进行新增、修改、删除等操作,然后将修改后的DTO传回服务器端由服务器对其进行处理。对于实体Bean来讲,如果要处理从客户端传递过来的DTO,就必须编写一个DTODisassembler来将DTO解析为实体Bean:
public class SystemUserDtoDisassembler
&&& public
static SystemUser fromDto(SystemUserDto aDto)
&&&&&&&&&&&
throws ServiceLocatorException, CreateException,
&&&&&&&&&&&
FinderException
SystemUser systemUser =
ServiceLocator serviceLoc = ServiceLocator.getInstance();
SystemUserHome systemUserHome = (SystemUserHome) serviceLoc
&&&&&&&&&&&&&&&
.getEjbLocalHome("SystemUserHome");
boolean bFind =
&&&&&&&&&&&
systemUser = systemUserHome.findByPrimaryKey(aDto.getPkId());
&&&&&&&&&&&
bFind = (systemUser != null);
} catch (FinderException fe)
&&&&&&&&&&&
if (bFind != true)
&&&&&&&&&&&
systemUser = systemUserHome.create(aDto.getPkId());
systemUser.setName(aDto.getName());
systemUser.setPassword(aDto.getPassword());
systemUser.setRole(aDto.getRole());
return systemU
Hibernate在这方面的处理就又比实体Bean简单了,主要把从客户端传来的DTO重新纳入Hibernate的管理即可,唯一需要注意的就是版本问题。
使用域DTO会有如下好处:
域模型结构可以在一次网络调用中复制到客户端,客户端可以读取、更新这个DTO而不需要额外的网络调用开销,而且客户端还可以通过将更新后的DTO回传到服务器端以更新数据。
易于实现快速开发。通过使用域DTO可以直接将域模型在层间传输,减少了工作量,可以快速地构建出一个应用。
但它也有如下的缺点:
将客户端和服务器端域对象耦合在一起。如果域模型变了,那么相应的DTO也会改变,即使对于Hibernate这种PO、DTO一体的系统来说也会同样导致客户端的代码要重新编译或者修改。
不能很好地满足客户端的要求。客户端可能只需要域对象的20个属性中的一两个,采用域DTO则会将20个属性都传递到客户端,浪费了网络资源。
更新域对象很烦琐。客户端对DTO可能做了很多更新或者很深层次的更新,要探查这些更新然后更新域对象是很麻烦的事情。
域DTO解决了在客户端和服务器端之间传递大量数据的问题,但是客户端往往需要更细粒度的数据访问。
例如,一件商品可能有很多属性:名称、编码、重量、型号、大小、颜色、生产日期、生产厂家、批次、保质期等。而客户端只对其中一部分属性有要求,如果将包含所有属性的商品对象到客户端的话,将会即浪费时间又浪费网络带宽,并对系统的性能有不同程度的影响。
我们需要一种可定制的DTO,使它仅封装客户端需要的数据的任意组合,完全与服务器端的域模型相分离。定制DTO与域DTO的区别就是它不映射到任何服务器端的域模型。
从上述的商品例子,设想客户端只需要一些与产品质量有关的属性,在这种情况下,应该创造一个封装了这些特定属性的DTO并传送给客户端。这个DTO是商品属性的一个子集:
public class GoodsCustomDTO implements
Serializable
&&& private Date
&&& private Date
&&& private
String batchN
&&& public
GoodsCustomDTO(Date productDate, Date expireDate, String
&&&&&&&&&&&
batchNumber)
this.productDate = productD
this.expireDate = expireD
this.batchNumber = batchN
&&& public
String getBatchNumber()
return batchN
&&& public Date
getExpireDate()
return expireD
&&& public Date
getProductDate()
return productD
一般来说,如果客户端需要n个属性,那么应该创造一个包含且仅包含这n个属性的DTO。使用这种方法,域模型的细节被隐藏在服务器中。这样开发人员把DTO仅当做普通的数据,而不是任何像PO那样的服务端的业务数据。当然采用定制DTO系统中会有越来越多的DTO,所以很多开发者情愿使用粗糙一些的DTO(即包含比需要的属性多的属性),而不是重新编写一个新的DTO,只要是返回的冗余数据不是太多,还是可以接受的。毕竟对于任何一种技术,都需要寻求一个兼顾方便和性能的折衷点。
定制DTO主要用于只读操作,也就是DTO只能用来显示,而不能接受改变。既然定制DTO对象仅仅是一个数据的集合,和任何服务端对象没有必然的关系,那么对定制DTO进行更新就是没有意义的了。
定制DTO的缺点如下:
&需要创建大量的DTO。使用定制DTO会爆炸式地产生大量的对象。
客户端DTO的版本必须和服务器端的版本一致。由于客户端和服务器端都通过定制DTO通信,所以一旦服务器端的DTO增加了字段,那么客户端的代码也必须重新编译,否则会产生类版本不一致的问题
已投稿到:
以上网友发言只代表其个人观点,不代表新浪网的观点或立场。

我要回帖

更多关于 性生活多长时间正常 的文章

 

随机推荐