阿里规范持续更新中
总结一下阿里编程规范中的文档
1、代码命名。不能够以下划线或者美元符号开始或结尾
错误示例:
_name
$name
name_
name$
2、禁止使用中文拼音。但是除了国际通用的中文拼音除外。
正确示例:
hangzhou、beijing、renmingbi
错误示例:
DaZhePromotion 打折促销
ZhuanHuan 转换
3、类名使用驼峰命名法,也就是每个单词的首字母大写,其他小写。
但是除了后缀名为:DO、BO、AO、DTO、VO、PO、PID等等
既然都是pojo,那么定义出来这么多的规范干嘛?又是怎么来进行使用的?
引入一片博客说明:
https://www.cnblogs.com/yueguanguanyun/p/9355746.html
https://www.cnblogs.com/optblogs/p/8398813.html // 给出了个人解读,这里可以拿过来参考一下
https://www.cnblogs.com/qixuejia/p/4390086.html // 详细说明了里面的使用分层
http://www.blogjava.net/johnnylzb/archive/2015/07/09/321968.html#426132 // 原生态的文章
在日常的项目开发中,VO
对应于页面上需要显示的数据(表单),DO
对应于数据库中存储的数据(数据表),DTO
对应于除二者之外需要进行传递的数据。
为什么不能只用一个DO
我们来看这样一个例子。假如我们的项目中由User这样一个实体。我们在创建User表的时候一般包含一下属性:
public class UserDO {
private Integer id; //唯一主键
private Date createdTime; //创建时间
private Date updatedTime; //最后更新时间
private String name; //姓名
private Integer age; //年龄
private String gender; //性别
private String address; //住址
private String password; //密码
private String nickName; //昵称
private Date birthday; //生日
private String politicalStatus; //政治面貌,1表示群众,2表示团员,3表示党员,4表示其他,100表示未知
private Integer companyId; //公司的ID
private Integer status; //数据状态,1表示可用,0表示不可用
//setter and getter
}
然后,在代码中,从DAO一直到前端展示,我们都通过这个UserDO类的对象来进行数据传输。这样做会有什么问题嘛?
- 不需要的字段也会传递到前端页面。
- 如password、createdTime、updatedTime和status这几个字段我们可能在前端根本不需要展示,但是这些字段有可能也会被传递到前端(除非我们在SQL查询的时候没有查询出对应的字段)。这不仅使数据的传输量增大,还可能有安全性问题。
- 某些字段需要转换,但是无法支持。
- 对于上面例子中的政治面貌字段,我们在数据库中存储的是数字,但是在前端页面我要展示的是中文描述。这种情况只能在前端通过
if/else
的方式来分情况展示。
- 对于上面例子中的政治面貌字段,我们在数据库中存储的是数字,但是在前端页面我要展示的是中文描述。这种情况只能在前端通过
- 某些字段要展示,但是并不希望出现在数据库中
- 在User表中我们只保存了这个用户的companyId,需要同时查询company表来查询出该公司的更多详细信息。对于User对象,如果我们想在前端同时展示他所属的公司,希望通过一次查询全都查出来怎么办?有几个简单的方案,第一个是让UserDO中包含一个Company类的属性,通过这个属性来传递。另外一种是把我们希望传到前端的Company的属性也写到UserDO中。但是,如果真的这么做了,那UserDO还能被称作DO了吗?
还有很多问题,这这里就不详细介绍了。
可见,使用一个DO从头用到尾(从数据库到前端页面)并不是一种好的设计。
如何正确的使用DO、DTO、VO
对于上面的例子,我们可以将他设计成以下类。由于模型并不复杂,这里只需要再引入VO就可以了。
UserDO已经和数据库字段一一对应了,这里不需要修改。
public class UserDO {
private Integer id; //唯一主键
private Date createdTime; //创建时间
private Date updatedTime; //最后更新时间
private String name; //姓名
private Integer age; //年龄
private String gender; //性别
private String address; //住址
private String password; //密码
private String nickName; //昵称
private Date birthday; //生日
private String education; //学历
private String politicalStatus; //政治面貌,1表示群众,2表示团员,3表示党员,4表示其他,100表示未知
private Integer companyId; //公司的ID
private Integer status; //数据状态,1表示可用,0表示不可用
//setter and getter
}
引入UserVO,用于封装传递到前端需要展示的字段。
public class UserVO {
private Integer id; //唯一主键
private String name; //姓名
private Integer age; //年龄
private String gender; //性别
private String address; //住址
private String nickName; //昵称
private Date birthday; //生日
private String education; //学历
private String politicalStatus; //政治面貌,群众、团员、党员等
private Company company; //公司
//setter and getter
}
UserVO中只包含了展示所需要的字段,并不需要展示的字段在这里不需要包含。
在引入了这个类之后,我们就可在进行数据库查询的时候使用UserDO,然后再需要传递到前端的时候把DO转换成VO。
总结
看到这里,你可能已经发现,UserDO和UserVO中包含了大量的相同字段。难道真的有必要再单独设计个VO嘛?我可以明确告诉你的是,当你的系统越来越大,表中的字段越来越多的时候,使用DO\DTO\VO等概念进行分层处理是绝对有好处的。至于如何进行有效的在不同的实体类间进行转换是我接下来要介绍的。
优雅的将DO转换成VO
使用mapstruct来进行映射这里的关系,这里需要更加小心的来进行注意。后面会出一个教程
所以以后使用VO、DO以及DTO来进行操作即可!
模型分类
1.分层领域模型规约:
- DO( Data Object):与数据库表结构一一对应,通过DAO层向上传输数据源对象。
- DTO( Data Transfer Object):数据传输对象,Service或Manager向外传输的对象。
- BO( Business Object):业务对象。 由Service层输出的封装业务逻辑的对象。
- AO( Application Object):应用对象。 在Web层与Service层之间抽象的复用对象模型,极为贴近展示层,复用度不高。
- VO( View Object):显示层对象,通常是Web向模板渲染引擎层传输的对象。
- POJO( Plain Ordinary Java Object):在本手册中, POJO专指只有setter/getter/toString的简单类,包括DO/DTO/BO/VO等。
- Query:数据查询对象,各层接收上层的查询请求。 注意超过2个参数的查询封装,禁止使用Map类来传输。
2.领域模型命名规约:
- 数据对象:xxxDO,xxx即为数据表名。
- 数据传输对象:xxxDTO,xxx为业务领域相关的名称。
- 展示对象:xxxVO,xxx一般为网页名称。
- POJO是DO/DTO/BO/VO的统称,禁止命名成xxxPOJO。
出一个解读方案:
1.如果你写的web应用是一个CRUD的demo,那么一个DO就完全够用。
例如,写一个用户的增删改查,数据库中有一个user表,你建立一个UserDO,类中的字段和数据库中一致,当你需要对User操作时,就用UserDO进行数据存取。
那么问题来啦:
首先,例如user表中有一个叫做passWord的字段,保存了登录密码,这个字段肯定是不需要返回到页面上的,但是如果像上面的操作,直接把UserDO的对象返回给前台,必然会带来安全隐患;
其次,如果User中有些字段需要转换后才能正确显示(例如显示中文,保存的是英文,或者保存的是关联表中的id),直接返回UserDO就只能在页面上用js写if...else...来区分值,很繁琐;
最后,如果你的页面上显示的数据是一个很大的结果集(调用了好几个接口的返回结果),例如除了User信息还有Account信息,一个UserDO显然就不够用了;
VO的概念应运而生。
2.VO中我们写的字段都是前台所需要的,而不是对象的所有字段值;
VO中的字段格式都是符合前台页面显示所需的,需要中文就显示中文;
对于调用了好几个接口返回的结果集,可以封装一个VO,将所有结果整合后再返回给前端页面。
3.有些人肯定在想,我的DO和VO中字段大多数都是相同的,有必要再写这样一个类吗?
答案是有的!如果写的是比较小的web应用,字段不多,你觉得没有这个必要。但是如果写的是大一些的系统,字段越多,分层的优势就会越明显。(博主写的web不大,但是拿出一个类也是一百多个字段,深感头疼)
这里需要来进行整理一下