为什么要在MVC三层架构上再加一层Manager层?,Java进阶面试资料无偿分享

先自我介绍一下,小编浙江大学毕业,去过华为、字节跳动等大厂,目前阿里P7

深知大多数程序员,想要提升技能,往往是自己摸索成长,但自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年最新Java开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友。
img
img
img
img
img
img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上Java开发知识点,真正体系化!

由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新

如果你需要这些资料,可以添加V获取:vip1024b (备注Java)
img

正文

  1. Service层代码臃肿

  2. Service层很容易出现大事务,事务嵌套,导致问题很多,而且极难排查

  3. dao层参杂业务逻辑

  4. dao层sql语句复杂,关联查询比较多

为了解决这个问题,我们参考《alibaba java开发手册》,在Service层之下再独立出一个通用业务处理层(Manager层)

manager层

在这个分层架构中主要增加了 Manager 层,它与 Service 层的关系是:Manager 层提供原子的服务接口,Service 层负责依据业务逻辑来编排原子接口。

Manager层的特征


在《alibaba java开发手册》中是这样描述Manager层的:

Manager 层:通用业务处理层,它有如下特征:

  1. 对第三方平台封装的层,预处理返回结果及转化异常信息,适配上层接口;
  1. 对 Service 层通用能力的下沉,如缓存方案、中间件通用处理;
  1. 与 DAO 层交互,对多个 DAO 的组合复用。

在实际开发中我们可以这样使用Manager层

  1. 复杂业务,service提供数据给Manager层,负责业务编排,然后把事务下沉到Manager层,Manager层不允许相互调用,不会出现事务嵌套。

  2. 专注于不带业务sql语言,也可以在manager层进行通用业务的dao层封装。

  3. 避免复杂的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 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 upOrDown(Long departmentId, Long swapId) {

最后

这份《“java高分面试指南”-25分类227页1000+题50w+字解析》同样可分享给有需要的朋友,感兴趣的伙伴们可挑战一下自我,在不看答案解析的情况,测试测试自己的解题水平,这样也能达到事半功倍的效果!(好东西要大家一起看才香)

image

image

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化的资料的朋友,可以添加V获取:vip1024b (备注Java)
img

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

止,不再深入研究,那么很难做到真正的技术提升。**

需要这份系统化的资料的朋友,可以添加V获取:vip1024b (备注Java)
[外链图片转存中…(img-Shl0rotd-1713676061562)]

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

  • 29
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值