dao层如何调用对象_你的项目应该如何正确分层?

00d02c54a632aae134aa43386bef957e.png

你好,欢迎收听极客视点。

说起应用分层,大部分人都会认为这不是很简单嘛,就Controller、Service、Mapper三层。但在“简单”背后,很多人并没有将各层级的职责划分清楚。比如在很多代码中,Controller比Service还多,Service被当成透传了,这是开发代码容易被忽略的地方。这样往往造成层级关系混乱,后续代码无法复用、维护困难。

此前,公众号“咖啡拿铁(ID:close_3092860495)”介绍了优化代码分层的方法,供你参考。

如何进行分层

一个好的应用分层需要具备以下几点:

  • 方便后续代码进行维护扩展;
  • 分层的效果需要让整个团队都接受;
  • 各层的职责边界清晰。

阿里巴巴的分层规范

da3d5f59933cdf8c8191aadc53c1c1f1.png 在阿里的编码规范中,对分层的要求如下:

1. 开放接口层:可直接封装 Service 方法暴露成 RPC 接口;通过 Web 封装成 http 接口;进行网关安全控制、流量控制等。

2. 终端显示层:各个端的模板渲染并执行显示的层。当前主要是 velocity 渲染、JS 渲染、JSP 渲染、移动端展示等。

3. Web 层:主要是对访问控制进行转发,各类基本参数校验,或者不复用的业务简单处理等。

4. Service 层:相对具体的业务逻辑服务层。

5. Manager 层:通用业务处理层,它有如下特征:一是对第三方平台封装的层,预处理返回结果及转化异常信息;二是对Service层通用能力的下沉,如缓存方案、中间件通用处理;三是与DAO层交互,对多个DAO的组合复用。

6 .DAO 层:数据访问层,与底层 MySQL、Oracle、Hbase 进行数据交互。

阿里巴巴规约中的分层比较清晰,简单明了,但是描述得还是过于简单了,很多人还是分不清楚Service层和Manager层之间的关系,导致很多项目中根本没有Manager层的存在。下面介绍具体业务中应该如何实现分层。

优化分层

首先需要说明的是,如果RPC框架选用Thrift,可能会比其他的RPC框架多出一层,作用和Controller层类似:

ca0d4dea19cf676fed4f88f6efdbc46b.png
最上层的Controller和TService是阿里分层规范中的第一层:轻业务逻辑、参数校验、异常兜底。通常这种接口可以轻易更换接口类型,所以业务逻辑必须要轻,甚至不做具体逻辑。

其次是Service层,这是业务层,复用性较低,这里推荐每一个Controller方法都对应一个Service,不要把业务编排放在Controller中去做,否则以后你要接入Thrift,又需要把业务编排再做一次,这会导致你每接入一个入口层,代码都得重新复制一份。如下图所示:

c2b1fe467d6f465a908499f41179cbc8.png 这样大量的重复工作必定会导致开发效率下降,所以你要把业务编排逻辑都放进Service层中。

2f7a58565f57279eb6b1189c1b19998f.png
然后是Mannager层,这是可复用逻辑层。这里的Mannager可以是单个服务,比如Cache、MQ等等;也可以是复合的,当你需要调用多个Mannager时,可以将它们合为一个Mannager,比如逻辑上的连表查询等。如果是httpMannager或rpcMannager,还需要在这一层做一些数据转换。

再来看DAO层,这是数据库访问层。主要负责“操作数据库的某张表,映射到某个Java对象”,DAO应该只允许自己的Service访问。

最后顺便聊一聊分层领域模型的转换,在阿里巴巴编码规约中,列举了下面几个领域模型规约:

  • DO(Data Object):与数据库表结构一一对应,通过DAO层向上传输数据源对象。
  • DTO(Data Transfer Object):数据传输对象,Service或Manager向外传输的对象。
  • BO(Business Object):业务对象,由Service层输出的封装业务逻辑的对象。
  • AO(Application Object):应用对象,在Web层与Service层之间抽象的复用对象模型,极为贴近展示层,复用度不高。
  • VO(View Object):显示层对象,通常是Web向模板渲染引擎层传输的对象。
  • Query:数据查询对象,各层接收上层的查询请求。注意超过2个参数的查询封装,禁止使用Map类来传输。

3d9d162e1d503833c66e16a2c7e7ba4f.png 每一个层基本都有自己对应的领域模型,而有些人过于追求每一层都用自己的领域模型,这就导致在一次请求中,出现多次对象转换。

一个折中的方案是:

  • 允许Service/Manager可以操作数据领域模型。
  • Controller/TService层的领域模型不允许传入DAO层,这样就不符合职责划分了。
  • 同理,不允许DAO层的数据传入到Controller/TService。

总结

业务分层对于代码规范是比较重要的,决定后续代码是否可复用,是否职责清晰、边界清晰。

以上就是今天的内容,如果你的团队有更好的分层方法,欢迎留言分享。

897d0c143961ede0cbf93570b8ac0d06.png

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/527198.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

mysql索引_MySQL索引介绍和实战

索引是什么MySQL官方对索引的定义为:索引(Index)是帮助MySQL高效获取数据的数据结构。可以得到索引的本质:索引是数据结构,索引的目的是提高查询效率,可以类比英语新华字典,根据目录定位词语如果没有目录呢&#xff0c…

mysql安装需要注意什么意思_mysql 安装过程及注意事项

1.1. 下载:我下载的是64位系统的zip包:下载zip的包:下载后解压:D:\软件安装包\mysql-5.7.20-winx641.2. 配置环境变量:变量名:MYSQL_HOME变量值:E:\mysql-5.7.20-winx64path里添加:%…

gitlab 端口_安装Gitlab-注意端口

文档本身并没有什么特殊,安装也很简单,只是修改端口这里如果有需要的可以看一下安装Gitlab[rootdeploy ~]# sudo yum -y install gitlab-ce默认端口是8080,避免冲突还是修改一下[rootlocalhost ~]# cat /etc/gitlab/gitlab.rb |grep 192.168.…

MySQL read-c_技术分享 | MySQL C API 参数 MYSQL_OPT_READ_TIMEOUT 的一些行为分析

作者:戴岳兵MYSQL_OPT_READ_TIMEOUT 是 MySQL c api 客户端中用来设置读取超时时间的参数。在 MySQL 的官方文档中,该参数的描述是这样的:MYSQL_OPT_READ_TIMEOUT (argument type: unsigned int *)The timeout in seconds for each attempt t…

mysql解释中fitered_MySQL的explain中的参数说明

1、id每个被独立执行的操作的标识,表示对象被操作的顺序;id值大,先被执行;如果相同,执行顺序从上到下。若没有子查询和联合查询,id则都是1。Mysql会按照id从大到小的顺序执行query,在id相同的情…

vue脚手架搭建项目_复习之vue脚手架搭建项目的两种方法

安装脚手架node 版本要求: > 8.9 。关于旧版本:如果在这之前已经全局安装了旧版本的vue-cli(1.x 或 2.x),那么需要先卸载掉。卸载旧版本运行:npm uninstall vue-cli -g 或 yarn global remove vue-cli。安装vue/cli&#xff1a…

pythonsocket中tcp通信接收不到数据_TCP 为什么三次握手而不是两次握手(正解版)...

先说结论为了实现可靠数据传输, TCP 协议的通信双方, 都必须维护一个序列号, 以标识发送出去的数据包中, 哪些是已经被对方收到的。 三次握手的过程即是通信双方相互告知序列号起始值, 并确认对方已经收到了序列号起始…

mysql无法启动如何备份文件_mysql 5.7 停电导致无法启动、如何备份数据,重新安装mysql...

用于记录服务器停电导致,mysql启动失败后,如何备份数据,重新安装mysql,主要分为数据备份,mysql重新安装。1、mysql无法启动时,进行数据备份。执行:systemctl start mysqld,启动失败。…

python tkinter entry默认值_Python ---(六)Tkinter窗口组件:Entry

The Tkinter Entry Widget##简介Entry(输入框)组件通常用于获取用户的输入文本。##何时使用 Entry 组件?Entry 组件仅允许用于输入一行文本,如果用于输入的字符串长度比该组件可显示空间更长,那内容将被滚动。这意味着该字符串将不能被全部看…

java 静态块初始化_简单了解java中静态初始化块的执行顺序

这篇文章主要介绍了简单了解java中静态初始化块的执行顺序,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下在java中,其应该是先于所有的方法执行。下面是测试代码:public class Test1 {st…

java 常量区存放 new_java---堆、栈、常量池的存储数据

说到Java中堆、栈和常量池,首先还是看看他们各自存放的数据类型吧!栈:Java的JVM的内存可分为3个区:堆(heap)、栈(stack)和方法区(method)也叫静态存储区。堆区:(存放所有new出来的对象;)1.存储的全部是对象&#xff0c…

log加时间 securecrt_SecureCRT配置自动记录日志

很多人用SecureCRT时,希望自动记录日志,一个是方便以后查阅,一个是对自己的操作有个记录。可以看看自己做了什么操作,有时甚至可以看看之前是不是犯了什么错,是个很不错的功能。设置很简单,还可以根据连接的…

java泛型改进_java泛型高级篇 - 真正理解协变与逆变 | 鱼儿的博客

无论你是否听过java泛型的协变与逆变,我们直接进入例子,一起来看一下java泛型比较高级的用法。例子1:copy函数第1个例子我们实现copy函数,它将List中的元素复制到List中。JavaList src Arrays.asList(1,2,3,4,5);List dst new A…

java实训遇到问题解决_「instantiationexception」关于java出现 java.lang.InstantiationException异常的分析与解决方案 - seo实验室...

instantiationexceptionjava.lang.instantiationexception 是指不能实例化某个对象,一般在我们使用java反射机制去创建某个对象的时候实例化到了一个抽象类或者接口(java中抽象类和接口是不能被实例化),而今天我遇到的则是我在使用反射机制实例化某个持久…

java对外发布接口文档_java之接口文档规范

一、xxxxxx获取指定任务爬取的所有url的接口接口名称:xxxxxx获取指定任务爬取的所有url的接口访问链接:http://IP:PORT/crwalTask/findUrlExceptionById?ctIdctIdVal&timetimeVal&limitlimitVal传入参数类型:String,int参数内容:返回…

java画好看坦克_坦克大战第一节——画出自己的坦克(新手篇)

刚刚开始学习java,对java不是很熟悉,但是自己的兴趣挺喜欢java。现在自己在自学java做一个小游戏,坦克大战。自己现在完成了画出自己的坦克和坦克的移动方向。希望各位大神指导一下我这个刚刚学java的新手小白。我会每完成一个阶段&#xff0…

java中timer类包_Java~util包中Timer的使用, 演示cancel方法 和 对比schedule和scheduleAtFixedRate方法...

TimerTimer类的主要作用就是设置计划任务,但封装任务的类却是TimerTask类执行计划任务的代码要放人TimerTask的子类中,因为TimerTask是一个抽象类。而且要重写其run方法 因为这是一个抽象方法.常见问题任务执行完了, 但进程并没有销毁,通过源码查看构造方…

centos eclipse java_CentOS7 安装 Eclipse

咳咳, 虽然大神的 Linux 都是命令行的, 但是谁让 LZ 是 LJ, 桌面开俩终端不觉得更好么。。。CentOS7 安装 Eclipse, 比在 Window 系统下安装 Eclipse 要复杂得多。。参考 : https://segmentfault.com/a/11900000026517…

java opencv orb_opencv python ORB算法

理论ORB(Oriented FAST and Rotated BRIEF)是一种快速特征点提取和描述的算法,这个算法是由Ethan Rublee, Vincent Rabaud, Kurt Konolige以及Gary R.Bradski在2011年一篇名为“ORB:An Efficient Alternative to SIFTor SURF”的文章中提出.ORB算法分为两部分&#…

php中define的参数_php中define的用法有哪些

php中define的用法:1、【define()】函数定义一个常量;2、定义常量名称及值,代码为【define(name,value,case_insensitive)】;3、定义一个大小写敏感的常量。php中define的用法:1、define()函数理解1define()函数定义一…