java开发MVC三层架构上再加一层Manager层原理详解
MVC三层架构
我们在刚刚成为程序员的时候,就会被前辈们 “教育” 说系统的设计要遵循 MVC(Model-View-Controller)架构。它将整体的系统分成了 Model(模型),View(视图)和 Controller(控制器)三个层次,也就是将用户视图和业务处理隔离开,并且通过控制器连接起来,很好地实现了表现和逻辑的解耦,是一种标准的软件分层架构。
MVC分层架构是架构上最简单的一种分层方式。为了遵循这种分层架构我们在构建项目时往往会建立这样三个目录:controller、service 和 dao,它们分别对应了表现层、逻辑层还有数据访问层。
每层的作用如下:
Controller层:主要是对访问控制进行转发,各类基本参数校验,或者不复用的业务简单处理。
Service层:主要是处理业务逻辑和事务
Dao层:负责与底层数据库MySQL,Oracle等进行数据交互
可是随着我们的业务逻辑越来复杂,代码写的越来越多,这种简单的三层架构的问题也越来越明显。
MVC架构弊端
传统的MVC分层有以下几个很明显的问题:
Service层代码臃肿
Service层很容易出现大事务,事务嵌套,导致问题很多,而且极难排查
dao层参杂业务逻辑
dao层sql语句复杂,关联查询比较多
为了解决这个问题,我们参考《alibaba java开发手册》,在Service层之下再独立出一个通用业务处理层(Manager层)
在这个分层架构中主要增加了 Manager 层,它与 Service 层的关系是:Manager 层提供原子的服务接口,Service 层负责依据业务逻辑来编排原子接口。
Manager层的特征
在《alibaba java开发手册》中是这样描述Manager层的:
Manager 层:通用业务处理层,它有如下特征:
对第三方平台封装的层,预处理返回结果及转化异常信息,适配上层接口;对 Service 层通用能力的下沉,如缓存方案、中间件通用处理;与 DAO 层交互,对多个 DAO 的组合复用。
在实际开发中我们可以这样使用Manager层
复杂业务,service提供数据给Manager层,负责业务编排,然后把事务下沉到Manager层,Manager层不允许相互调用,不会出现事务嵌套。
专注于不带业务sql语言,也可以在manager层进行通用业务的dao层封装。
避免复杂的join查询,数据库压力比java大很多,所以要严格控制好sql,所以可以在manager层进行拆分,比如复杂查询。
当然对于简单的业务,可以不使用Manager层。
Manager层使用案例
这里我们举个例子说明一下Manager层的使用场景:
假设你有一个用户系统,他有一个获取用户信息的接口,它调用逻辑Service层的 getUser
方法,getUser
方法又和 User DB
交互获取数据。如下图左边展示部分。
这时,产品提出一个需求,在 APP 中展示用户信息的时候,如果用户不存在,那么要自动给用户创建一个用户。同时,要做一个 HTML5 的页面,HTML5 页面要保留之前的逻辑,也就是不需要创建用户。
此时按照传统的三层架构,逻辑层的边界就变得不清晰,表现层也承担了一部分的业务逻辑,因为我们往往会在表现层Controller中增加业务逻辑处理,将获取用户和创建用户接口编排起来。
而添加Manager层以后,Manager 层提供创建用户和获取用户信息的接口,而 Service 层负责将这两个接口组装起来。这样就把原先散布在表现层的业务逻辑都统一到了 Service 层,每一层的边界就非常清晰了。
接下来我们看一段实际代码说明一下Service层与Manager层如何进行区分?
@Transactional(rollbackFor = Throwable.class) public Result<String> upOrDown(Long departmentId, Long swapId) { // 验证 1 DepartmentEntity departmentEntity = departmentDao.selectById(departmentId); if (departmentEntity == null) { return Result.error("部门xxx不存在"); } // 验证 2 DepartmentEntity swapEntity = departmentDao.selectById(swapId); if (swapEntity == null) { return Result.error("部门xxx不存在"); } // 验证 3 Long count = employeeDao.countByDepartmentId(departmentId); if (count != null && count > 0) { return Result.error("员工不存在"); } // 操作数据库 4 Long departmentSort = departmentEntity.getSort(); departmentEntity.setSort(swapEntity.getSort()); departmentDao.updateById(departmentEntity); swapEntity.setSort(departmentSort); departmentDao.updateById(swapEntity); return Result.OK("success"); }
上面代码在我们在我们采用三层架构时经常会遇到,那么它有什么问题呢?
上面的代码是典型的长事务问题(类似的还有调用第三方接口),前三步都是使用 connection 进行验证操作,但是由于方法上有@Transactional 注解,所以这三个验证都是使用的同一个 connection。
若对于复杂业务、复杂的验证逻辑,会导致整个验证过程始终占用该 connection 连接,占用时间可能会很长,直至方法结束,connection 才会交还给数据库连接池。
对于复杂业务的不可预计的情况,长时间占用同一个 connection 连接不是好的事情,应该尽量缩短占用时间。
说明:对于@Transactional 注解,当 spring 遇到该注解时,会自动从数据库连接池中获取 connection,并开启事务然后绑定到 ThreadLocal 上,如果业务并没有进入到最终的 操作数据库环节,那么就没有必要获取连接并开启事务,应该直接将 connection 返回给数据库连接池,供其他使用。
所以我们在加入Manager层以后可以这样写:
DepartmentService.java public Result<String> upOrDown(Long departmentId, Long swapId) { // 验证 1 DepartmentEntity departmentEntity = departmentDao.selectById(departmentId); if (departmentEntity == null) { return Result.error("部门xxx不存在"); } // 验证 2 DepartmentEntity swapEntity = departmentDao.selectById(swapId); if (swapEntity == null) { return Result.error("部门xxx不存在"); } // 验证 3 Long count = employeeDao.countByDepartmentId(departmentId); if (count != null && count > 0) { return Result.error("员工不存在"); } // 操作数据库 4 departmentManager.upOrDown(departmentSort,swapEntity); return Result.OK("success"); }
DepartmentManager.java @Transactional(rollbackFor = Throwable.class) public void upOrDown(DepartmentEntity departmentEntity ,DepartmentEntity swapEntity){ Long departmentSort = departmentEntity.getSort(); departmentEntity.setSort(swapEntity.getSort()); departmentDao.updateById(departmentEntity); swapEntity.setSort(departmentSort); departmentDao.updateById(swapEntity); }
将数据在 service 层准备好,然后传递给 manager 层,由 manager 层添加 @Transactional
事务注解进行数据库操作。
以上就是MVC三层架构上再加一层Manager层原理详解的详细内容,更多关于MVC架构Manager层原理的资料请关注猪先飞其它相关文章!
原文出处:https://blog.csdn.net/jianzhang11/article/details/120884260
相关文章
详解redis desktop manager安装及连接方式
这篇文章主要介绍了redis desktop manager安装及连接方式,本文图文并茂给大家介绍的非常详细,具有一定的参考借鉴价值,需要的朋友可以参考下...2021-01-15- 这篇文章主要介绍了SpringMVC文件上传原理及实现过程解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下...2020-07-15
C# MVC模式中应该怎样区分应用程序逻辑(Controller层)和业务逻辑(Model层)?
这篇文章主要介绍了C# MVC模式中应该怎样区分应用程序逻辑(Controller层)和业务逻辑(Model层)?,这也小编做.NET项目时经常思考和让人混乱的一个问题,这篇文章写的挺好,一下清晰了许多,需要的朋友可以参考下...2020-06-25使用Maven 搭建 Spring MVC 本地部署Tomcat的详细教程
这篇文章主要介绍了使用Maven 搭建 Spring MVC 本地部署Tomcat,本文通过图文并茂的形式给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下...2021-08-16- 这篇文章主要介绍了SpringMvc自动装箱及GET请求参数原理解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下...2020-09-19
- 这篇文章主要介绍了SpringMvc获取请求头请求体消息过程解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下...2020-09-17
Springmvc ResponseBody响应json数据实现过程
这篇文章主要介绍了Springmvc ResponseBody响应json数据实现过程,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下...2020-10-26- 本篇文章介绍了,基于C#后台调用跨域MVC服务及带Cookie验证的实现。需要的朋友参考下...2020-06-25
- 这篇文章主要为大家介绍了javascript中的MVC模式,MVC是一种软件架构模式,一般把软件模式分为三部分,本文就针对MVC模式的三部分进行讲解,感兴趣的小伙伴们可以参考一下...2016-02-01
- Spring MVC是Spring系列框架中使用频率最高的部分。不管是Spring Boot还是传统的Spring项目,只要是Web项目都会使用到Spring MVC部分。因此程序员一定要熟练掌握MVC部分。本篇博客简要分析Spring MVC处理一个请求的流程。...2021-02-06
- 这篇文章主要介绍了仅30行代码实现Javascript中的MVC的方法,MVC的基础是观察者模式,这是实现model和view同步的关键,想要深入了解的朋友可以参考本文...2016-02-18
使用jQuery.form.js/springmvc框架实现文件上传功能
这篇文章主要介绍了使用jQuery.form.jsspringmvc框架实现文件上传功能,非常具有参考借鉴价值,感兴趣的朋友一起学习吧...2016-05-14- 这篇文章主要介绍了SpringMVC和rabbitmq集成的使用案例,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...2021-01-20
- 这篇文章主要介绍了CocosCreator MVC架构,同学们在制作游戏过程中,尽量使用一些架构,会避免很多问题...2021-04-16
- 本文主要讲解AngularJS MVC体系结构,这里提供详细的教程供大家学习参考,有需要的小伙伴可以参考下...2016-08-24
web面试MVC与MVVM区别及Vue为什么不完全遵守MVVM解答
这篇文章主要介绍了web面试中常问问题,MVC与MVVM区别以及Vue为什么不完全遵守MVVM的难点解答,有需要的朋友可以借鉴参考下,希望能够有所帮助...2021-09-24- 本篇文章主要介绍了ASP.NET MVC API 接口验证的示例代码,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧...2021-09-22
SpringMVC中的handlerMappings对象用法
这篇文章主要介绍了SpringMVC中的handlerMappings对象用法,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教...2021-09-26ASP.NET Core MVC如何实现运行时动态定义Controller类型
这篇文章主要介绍了ASP.NET Core MVC如何实现运行时动态定义Controller类型,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧...2021-09-22- 这篇文章主要介绍了SpringMVC表单提交参数400错误解决方案,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下...2020-10-21