java开发MVC三层架构上再加一层Manager层原理的示例分析

技术java开发MVC三层架构上再加一层Manager层原理的示例分析这篇文章主要为大家展示了“java开发MVC三层架构上再加一层Manager层原理的示例分析”,内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面

本文主要向您展示“java开发中向MVC三层架构添加管理器层的原理示例分析”,简单易懂。很清楚是为了帮你解决疑惑。让边肖带领大家学习《java开发中MVC三层架构添加管理器层原理的实例分析》一文。

MVC三层架构

我们刚成为程序员的时候,被前辈“教育”系统设计要遵循MVC(Model-View-Controller)架构。它将整个系统分为模型、视图和控制器三个层次,即把用户视图和业务处理分开,通过控制器把它们连接起来,从而实现表示和逻辑的解耦。这是一个标准的软件分层架构。

java开发MVC三层架构上再加一层Manager层原理的示例分析

MVC分层架构是架构中最简单的分层方式。为了遵循这种分层架构,我们在构建项目时往往会设置三个目录:控制器、服务和dao,分别对应表示层、逻辑层和数据访问层。

java开发MVC三层架构上再加一层Manager层原理的示例分析

每一层的功能如下:

控制器层:主要转发访问控制,验证各种基本参数,或者简单处理不可重用的服务。

服务层:主要处理业务逻辑和事务。

Dao层:负责与底层数据库MySQL和Oracle的数据交互。

然而,随着我们的业务逻辑变得越来越复杂,编写的代码越来越多,这种简单的三层架构的问题变得越来越明显。

MVC架构弊端

传统MVC分层存在以下明显问题:

服务层代码臃肿。

服务层容易出现大事务和嵌套事务,导致很多问题,极难排除。

Dao层参与业务逻辑。

dao层的Sql语句很复杂,有很多相关的查询。

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

java开发MVC三层架构上再加一层Manager层原理的示例分析

在这种分层架构中,主要增加了Manager层,其与service层的关系是Manager层提供原子Service接口,Service层负责根据业务逻辑安排原子接口。

00-1010管理器层在《alibaba java开发手册》中描述如下:

经理层:一般业务处理层,具有以下特点:

对于第三方平台封装的层,对返回结果进行预处理,对异常信息进行转换,适应层接口;服务层通用能力的下沉,如缓存方案和中间件通用处理;与DAO层交互,组合复用多个DAO。

在实际开发中,我们可以像这样使用管理器层。

复杂业务,服务向管理器层提供数据,负责业务安排,然后将事务下沉到管理器层。管理器层不允许相互调用,所以不会有事务嵌套。

专注于没有业务的sql语言,同时在经理层将一般业务封装在dao层。

避免复杂的连接查询,因为数据库的压力比java大得多,所以我们应该严格控制sql,这样我们就可以在管理器层拆分它,比如复杂的查询。

当然,对于简单的业务,可能不会使用Manager层。

Manager层的特征

这里,让我们举一个例子来说明Manager层的使用场景:

假设你有一个用户系统,它有一个获取用户信息的接口。它调用逻辑服务层中的getUser方法,getUser方法与用户数据库交互以获取数据。如下图左侧所示。

这时,产品提出了一个要求。在APP中显示用户信息时,如果用户不存在,应该自动为用户创建一个用户。同时,制作一个HTML5页面,HTML5页面要保持之前的逻辑,即不需要创建用户。

java开发MVC三层架构上再加一层Manager层原理的示例分析

此时,按照传统的三层架构,逻辑层的边界变得不清晰,表示层也承载了部分业务逻辑,因为我们经常在表示层Controller中加入业务逻辑处理,安排用户的获取和用户界面的创建。

添加管理器层后,管理器层提供创建。

建用户和获取用户信息的接口,而 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事务注解进行数据库操作。

以上是“java开发MVC三层架构上再加一层Manager层原理的示例分析”这篇文章的所有内容,感谢各位的阅读!相信大家都有了一定的了解,希望分享的内容对大家有所帮助,如果还想学习更多知识,欢迎关注行业资讯频道!

内容来源网络,如有侵权,联系删除,本文地址:https://www.230890.com/zhan/60902.html

(0)

相关推荐

  • 上引号,这段话在人字上加引号的作用

    技术上引号,这段话在人字上加引号的作用这段话在“人“字上加引号的作用是表示特殊的称谓,指具有特殊含义的词语上引号。引号的作用如下:1、表示引用的部分。文章中的人物对话或者是直接引用别人的话(或文章)用引号,为的是把他们和

    生活 2021年10月20日
  • 如何读取netcdf数据并在matplotlib Basemap上绘图

    技术如何读取netcdf数据并在matplotlib Basemap上绘图这篇文章主要为大家展示了“如何读取netcdf数据并在matplotlib Basemap上绘图”,内容简而易懂,条理清晰,希望能够帮助大家解决疑

    攻略 2021年12月8日
  • 从源代码构建Tomcat的方式是什么

    技术从源代码构建Tomcat的方式是什么今天就跟大家聊聊有关从源代码构建Tomcat的方式是什么,可能很多人都不太了解,为了让大家更加了解,小编给大家总结了以下内容,希望大家根据这篇文章可以有所收获。本次我们从源代码入手

    攻略 2021年12月8日
  • 小程序Vant组件如何将默认样式单位px转为rpx

    技术小程序Vant组件如何将默认样式单位px转为rpx本篇内容介绍了“小程序Vant组件如何将默认样式单位px转为rpx”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处

    攻略 2021年10月29日
  • sqlite3基本操作(sqlite3怎么创建数据表)

    技术SQLite3如何实现数据库全文搜索这篇文章主要为大家展示了“SQLite3如何实现数据库全文搜索”,内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下“SQLite3如何实现数据

    攻略 2021年12月18日
  • Java语言中的线程安全问题是怎样的

    技术Java语言中的线程安全问题是怎样的Java语言中的线程安全问题是怎样的,相信很多没有经验的人对此束手无策,为此本文总结了问题出现的原因和解决方法,通过这篇文章希望你能解决这个问题。Java语言是一种支持多线程的语言

    攻略 2021年10月23日