前语
最近review公司的代码,发现现在整个代码层级十分混乱,一个service类的长度甚至达到了5000多行。并且各种分层模型DTO、VO乱用, 终究呈现逻辑不明晰、各模块相互依赖、代码扩展性差、改动一处就牵一发而动全身等问题。
咱们在吸取了阿里巴巴的分层标准以及网上的一些经历后,重新整理总结了属于咱们项目的分层标准。
欢迎重视个人公众号『JAVA旭阳』交流交流
三层架构VS四层架构
咱们公司原来的分层采用的是传统的三层架构,比方在构建项目的时分,咱们一般会建立三个目录:Web、Service 和 Dao,它们别离对应了体现层、逻辑层还有数据拜访层。
这样导致一个很大的问题,跟着事务越来越复杂,逻辑层也就是service层越来越巨大,所以呈现了前面说的5000多行的类,可想而知保护成本有多大。
参照阿里发布的《阿里巴巴 Java 开发手册 v1.4.0(详尽版)》,咱们能够将原先的三层架构细化成下面的姿态:
- 终端显现层:各端模板烘托并执行显现的层。当时首要是 Velocity 烘托,JS 烘托, JSP 烘托,移动端展现等。
- 敞开接口层:将
Service
层办法封装成敞开接口,一起进行网关安全操控和流量操控等。 -
Web
层:首要是对拜访操控进行转发,各类基本参数校验,或许不复用的事务简略处理等。 -
Service
层:事务逻辑层。 -
Manager
层:通用事务处理层。首要完成下面的功用,1) 对第三方渠道封装的层,预处理回来成果及转化反常信息,适配上层接口。2) 对 Service 层通用能力的下沉,如缓存方案、中间件通用处理。3) 与 DAO 层交互,对多个 DAO 的组合复用。 -
DAO
层:数据拜访层,与底层MySQL
、Oracle
、Hbase
等进行数据交互。 - 外部接口或第三方渠道:包含其它部分
RPC
敞开接口,基础渠道,其它公司的HTTP
接口。
在这个分层架构中首要增加了 Manager
层,它能够将Service
层中的一些通用能力比方操作缓存、消息队列的操作下沉,也能够将经过feign
调用其他服务的接口进行一层包装,再供给给Service
调用,这也就是所谓的防腐层。
VO、DTO、BO、DO区别
前面讲解了全体的一个分层架构,那么在不同的层级之间必定需求一些模型目标进行流通传递,VO,BO,DO,DTO, 那么他们之间有什么区别呢?
-
VO(View Object)
:视图目标,用于展现层,它的作用是把某个指定页面(或组件)的一切数据封装起来。 -
DTO(Data Transfer Object)
:数据传输目标,用于展现层与服务层之间的数据传输目标。 -
BO(Business Object)
:事务目标,把事务逻辑封装为一个目标,这个目标能够包含一个或多个其它的目标。 -
DO(Domain Object)
:范畴目标,阿里巴巴标准中引入,此目标与数据库表结构一一对应,经过DAO
层向上传输数据源目标。
- VO和DTO什么区别?
VO
比较简单混杂的是DTO
,DTO
是展现层与服务层之间传递数据的目标,能够这样说,关于绝大部分的运用场景来说,DTO
和VO
的特点值基本是共同的,并且他们一般都是POJO
,那么已然有了VO
,为什么还需求DTO
呢?
例如服务层有一个getUser
的办法回来一个系统用户,其中有一个特点是gender
(性别),关于服务层来说,它只从语义上界说:1-男性,2-女人,0-未指定,而关于展现层来说,它或许需求用“帅哥”代表男性,用“美人”代表女人,用“隐秘”代表未指定。说到这里,或许你还会反驳,在服务层直接就回来“帅哥美人”不就行了吗?关于大部分运用来说,这不是问题,但想象一下,如果需求答应客户能够定制风格,而不同风格关于“性别”的体现方式不一样,又或许这个服务一起供多个客户端运用(不同门户),而不同的客户端关于体现层的要求有所不同,那么,问题就来了。再者,回到规划层面上分析,从职责单一原则来看,服务层只担任事务,与详细的体现形式无关,因此,它回来的DTO,不应该呈现与体现形式的耦合。
- BO和DTO的区别?
从用处上进行根本的区别,BO是事务目标,DTO是数据传输目标,尽管BO也能够排列组合数据,但它的功用是对内的,但在供给对外接口时,BO目标中的某些特点目标或许用不到或许不方便对外暴露,那么此时DTO只需求在BO的基础上,抽取自己需求的数据,然后对外供给。在这个关系上,一般不会有数据内容的变化,内容变化要么在BO内部事务计算的时分完结,要么在解说VO的时分完结。
咱们项目根据实际情况总结了分层范畴模型的标准:
- 前端传入的参数一致运用DTO接纳
- 因为公司是TO B项目,只有一个电脑web端,所以回来给展现层或许Feign回来的目标建议直接用DTO回来,特殊情况采用VO回来
- 因为前史原因,和数据库模型对应的不采用DO结束,直接用原始目标,比方学生表
student
直接运用Student
目标 - 现在许多代码存在承继关系,比方DTO、VO承继数据库目标,这个坚决不答应
项目目录结构最佳实践
能够参阅github上面的github.com/alvinlkk/ma…这个项目,它是一个极度遵守阿里巴巴代码规约的项目。
这里面有个关于Feign
规划的亮点, 首要是为了防止服务供给方修正了接口,而调用方没有修正导致反常的问题。
- 将
feign
接口抽取出一个独立的模块
- 服务中依赖
feign
模块,完成FeignClient
咱们来看下全体的一个结构。
mall4cloud
├─mall4cloud-api -- 内网接口
│ ├─mall4cloud-api-auth -- 授权对内接口
│ ├─mall4cloud-api-biz -- biz对内接口
│ ├─mall4cloud-api-leaf -- 美团分布式id生成接口
│ ├─mall4cloud-api-multishop -- 店铺对内接口
│ ├─mall4cloud-api-order -- 订单对内接口
│ ├─mall4cloud-api-platform -- 渠道对内接口
│ ├─mall4cloud-api-product -- 产品对内接口
│ ├─mall4cloud-api-rbac -- 用户人物权限对内接口
│ ├─mall4cloud-api-search -- 查找对内接口
│ └─mall4cloud-api-user -- 用户对内接口
├─mall4cloud-auth -- 授权校验模块
├─mall4cloud-biz -- mall4cloud 事务代码。如图片上传/短信等
├─mall4cloud-common -- 一些公共的办法
│ ├─mall4cloud-common-cache -- 缓存相关公共代码
│ ├─mall4cloud-common-core -- 公共模块核心(公共中的公共代码)
│ ├─mall4cloud-common-database -- 数据库连接相关公共代码
│ ├─mall4cloud-common-order -- 订单相关公共代码
│ ├─mall4cloud-common-product -- 产品相关公共代码
│ ├─mall4cloud-common-rocketmq -- rocketmq相关公共代码
│ └─mall4cloud-common-security -- 安全相关公共代码
├─mall4cloud-gateway -- 网关
├─mall4cloud-leaf -- 基于美团leaf的生成id服务
├─mall4cloud-multishop -- 商家端
├─mall4cloud-order -- 订单服务
├─mall4cloud-payment -- 付出服务
├─mall4cloud-platform -- 渠道端
├─mall4cloud-product -- 产品服务
├─mall4cloud-rbac -- 用户人物权限模块
├─mall4cloud-search -- 查找模块
└─mall4cloud-user -- 用户服务
结束语
关于运用分层这块我觉得没那么简略,特别是团队大了以后,人员水平良莠不齐,很难约束,很简单自由发挥,各写各的。不知道我们有没有什么好的办法呢?
欢迎重视个人公众号『JAVA旭阳』交流交流