前语

最近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 层:数据拜访层,与底层 MySQLOracleHbase 等进行数据交互。
  • 外部接口或第三方渠道:包含其它部分 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 层向上传输数据源目标。
  1. VO和DTO什么区别?

VO比较简单混杂的是DTODTO是展现层与服务层之间传递数据的目标,能够这样说,关于绝大部分的运用场景来说,DTOVO的特点值基本是共同的,并且他们一般都是POJO,那么已然有了VO,为什么还需求DTO呢?

例如服务层有一个getUser的办法回来一个系统用户,其中有一个特点是gender(性别),关于服务层来说,它只从语义上界说:1-男性,2-女人,0-未指定,而关于展现层来说,它或许需求用“帅哥”代表男性,用“美人”代表女人,用“隐秘”代表未指定。说到这里,或许你还会反驳,在服务层直接就回来“帅哥美人”不就行了吗?关于大部分运用来说,这不是问题,但想象一下,如果需求答应客户能够定制风格,而不同风格关于“性别”的体现方式不一样,又或许这个服务一起供多个客户端运用(不同门户),而不同的客户端关于体现层的要求有所不同,那么,问题就来了。再者,回到规划层面上分析,从职责单一原则来看,服务层只担任事务,与详细的体现形式无关,因此,它回来的DTO,不应该呈现与体现形式的耦合。

  1. BO和DTO的区别?

从用处上进行根本的区别,BO是事务目标,DTO是数据传输目标,尽管BO也能够排列组合数据,但它的功用是对内的,但在供给对外接口时,BO目标中的某些特点目标或许用不到或许不方便对外暴露,那么此时DTO只需求在BO的基础上,抽取自己需求的数据,然后对外供给。在这个关系上,一般不会有数据内容的变化,内容变化要么在BO内部事务计算的时分完结,要么在解说VO的时分完结。

咱们项目根据实际情况总结了分层范畴模型的标准:

  1. 前端传入的参数一致运用DTO接纳
  2. 因为公司是TO B项目,只有一个电脑web端,所以回来给展现层或许Feign回来的目标建议直接用DTO回来,特殊情况采用VO回来
  3. 因为前史原因,和数据库模型对应的不采用DO结束,直接用原始目标,比方学生表student直接运用Student目标
  4. 现在许多代码存在承继关系,比方DTO、VO承继数据库目标,这个坚决不答应

项目目录结构最佳实践

能够参阅github上面的github.com/alvinlkk/ma…这个项目,它是一个极度遵守阿里巴巴代码规约的项目。

【架构设计】你的应用该如何分层呢?

这里面有个关于Feign规划的亮点, 首要是为了防止服务供给方修正了接口,而调用方没有修正导致反常的问题。

  1. feign接口抽取出一个独立的模块

【架构设计】你的应用该如何分层呢?

  1. 服务中依赖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旭阳』交流交流