来聊聊Java项目分层规范

简介: 本文讨论了Java项目的分层规范,强调了分层的重要性以避免代码不易扩展和职责边界模糊。作者分享了阿里提出的六层分层模型(开放接口层、终端显示层、Web层、Service层、Manager层、Mapper层)以及对应的领域模型(DO、DTO、VO、query)。同时,提出了简化版的分层规约,以提高开发效率。作者是CSDN Java博客专家,维护者之一的Java Guide项目,并提供了个人项目结构示例。文章鼓励读者关注其公众号以获取更多交流机会。

写在文章开头

近期和读者交流聊到项目规范,借着这个机会我们不妨聊聊主流Java项目是如何进行分层的。

Hi,我是 sharkChili ,是个不断在硬核技术上作死的 java coder ,是 CSDN的博客专家 ,也是开源项目 Java Guide 的维护者之一,熟悉 Java 也会一点 Go ,偶尔也会在 C源码 边缘徘徊。写过很多有意思的技术博客,也还在研究并输出技术的路上,希望我的文章对你有帮助,非常欢迎你关注我的公众号: 写代码的SharkChili

因为近期收到很多读者的私信,所以也专门创建了一个交流群,感兴趣的读者可以通过上方的公众号获取笔者的联系方式完成好友添加,点击备注 “加群” 即可和笔者和笔者的朋友们进行深入交流。

为什么需要分层

大部分人都认为Java项目的分层无非是controllerservicemapper这3层,尽管这种规约在Java web项目几乎是默认的,有时却因为团队沟通或者需求快速迭代,导致项目中会出现以下几种情况:

  1. 接口逻辑全写在controllerservice仅做透传持久层的透传。
  2. mapper层对象直接返回到controller层,直接无视service层。
  3. controller层对象不做任何转换直接一路传到mapper层。

就笔者的个人经验而言,这种情况大部分出现在有一定开发经验老码农身上,而新人接手项目时没有经过沟通,直接照猫画虎,于是这种恶习便一路传下来,进而出现如下几个问题:

  1. 代码不易扩展。
  2. 分层效果让团队难以接受。
  3. 各层职责边界不清晰,难以复用。

分层最佳实践

阿里提出的分层规范

按照阿里的规约,对应的项目会按照如下规范进行分层:

  1. 开放接口层:封装service方法对外暴露为RPC接口或者通过web封装成HTTP接口进行网关安全控制或者流量控制等。
  2. 终端显示层:各个模板渲染并显示的层级,我们可直接通俗的理解为前端渲染的页面。
  3. web层:主要对访问控制进行转发、参数校验、逻辑调用等,也就是我们常说的controller层。
  4. service:真正逻辑处理的层级,严格来说一个controller就对应一个service,之所以用逻辑都封装在service是为了方便后续封装RPC接口时,可以通过直接调用service完成扩展。
  5. manager:通用的业务处理层级,常用于第三方平台能力封装,或者中间件、缓存方案通用处理、对多mapper进行逻辑组合,总的来说manager层提供各种原子服务接口,而service层对这些原子接口进行逻辑编排。
  6. mapper层:持久层,也就是直接和数据库交互的一层。

对应的我们给出分层的图解:

分层的领域模型

明确分层后,我们也需要针对各层提出领域模型规约:

  1. DO(data object):即持久层对象,所有的数据库查询后转换为Java映射的对象都以DO结尾,该层与数据表一一对应。
  2. DTO(data transfer object):持久层完成查询之后得到的DO对象service层或者manager层就需要将其转换为DTO对外传输。
  3. VO(view object)controller层返回给视图层进行渲染的对象。
  4. query:入参对象,如果超过两个则需要封装,禁止使用Map,这是强制要求。

很明显,这种做法虽然保证了层级分明,但是为了所谓的规范却耗费开发大量精力进行对象转化,明显降低了开发的效率。

简化分层规约

所以我们对此做一个折中,得到下面这样一个开发规约图解,其交互过程为:

  1. 入参一律使用query,进行参数校验之后,由于controller或者Tservicequery传给service或者manager
  2. servicemanager在业务处理时可直接操作mapper层的DO对象进行逻辑处理。
  3. servicemanager完成逻辑后最终封装成VO返回给上层也就是controller或者Tservice层。

由此我们既实现了规范的的分层又保证了开发的效率。

常见的web架构示例

基于上述的分层理论,笔者给出一个个人比较常用的项目结构,整体结构树如下所示,读者可参考自行调整使用:

    |- web-project   // 项目根目录
        |- src
            |- main                  // 业务逻辑
                |- assembly          // 基于maven assembly插件的服务化打包方案
                    |- bin           // 模块脚本(启动、停止、重启)
                    |- sbin          // 管理员角色使用的脚本(环境检查、系统检测等等)
                    |- assembly.xml  // 配置文件
                |- java              // 源代码
                    |- com
                        |- sharkchili
                            |- www
                                |- system
                                    |- annotation     // 注解
                                    |- aspect         // 面向切面编程
                                    |- config         // 配置文件POJO
                                    |- filter         // 过滤器
                                    |- constant       // 存放常量
                                    |- utils          // 工具
                                    |- exception      // 异常
                                    |- controller     // 控制层(将请求通过URL匹配,分配到不同的接收器/方法进行处理,然后返回结果)
                                    |- service        // 服务层接口
                                        |- impl       // 服务层实现
                                    |- mapper/repository // 数据访问层,与数据库交互为service提供接口
                                    |- entity/domain     // 实体对象
                                        |- dto // 持久层需要的实体对象(用于服务层与持久层之间的数据传输对象)
                                        |- vo // 视图层需要的实体对象(用于服务层与视图层之间的数据传输对象)
                                    |- *Application.java  // 入口启动类
                |- resources         // 资源
                    |- static        // 静态资源(html、css、js、图片等)
                    |- templates     // 视图模板(jsp、thymeleaf等)
                    |- mapper        // 存放数据访问层对应的XML配置
                        |- *Mapper.xml
                        |- ...
                    |- application.yml        // 公共配置
                    |- application-dev.yml    // 开发环境配置
                    |- application-prod.yml   // 生产环境配置
                    |- banner.txt    
                    |- logback.xml            // 日志配置
            |- test                  // 测试源码
               |- java               
                    |- com
                        |- sharkchili
                            |- www
                                |- system
                                    |- 根据具体情况按源码目录结构存放编写的测试用例
        |- target     // 编译打包输出目录(自动生成,不需要创建)
        |- pom.xml    // 该模块的POM文件
    |- sql            // 项目需要的SQL脚本
    |- doc            // 精简版的开发、运维手册
    |- .gitignore     // 哪些文件不用传到版本管控工具中
    |- pom.xml        // 工程总POM文件
    |- README.md      // 注意事项
External Libraries    // 相关JAR包依赖

小结

以上便是笔者对于项目分层规范的总结,希望对你有帮助。

我是 sharkchiliCSDN Java 领域博客专家开源项目—JavaGuide contributor,我想写一些有意思的东西,希望对你有帮助,如果你想实时收到我写的硬核的文章也欢迎你关注我的公众号: 写代码的SharkChili
因为近期收到很多读者的私信,所以也专门创建了一个交流群,感兴趣的读者可以通过上方的公众号获取笔者的联系方式完成好友添加,点击备注 “加群” 即可和笔者和笔者的朋友们进行深入交流。

参考

优秀的代码都是如何分层的?
:https://mp.weixin.qq.com/s/KL3U4mpi2-bnyFjfKNDPTw

同事问我代码结构中 Manager层是干什么的:https://juejin.cn/post/7032680627069517854

SpringBoot项目的目录结构及名规范
:https://blog.csdn.net/goodjava2007/article/details/122275079

目录
相关文章
|
11天前
|
NoSQL Java 关系型数据库
Liunx部署java项目Tomcat、Redis、Mysql教程
本文详细介绍了如何在 Linux 服务器上安装和配置 Tomcat、MySQL 和 Redis,并部署 Java 项目。通过这些步骤,您可以搭建一个高效稳定的 Java 应用运行环境。希望本文能为您在实际操作中提供有价值的参考。
72 26
|
23天前
|
XML Java 测试技术
从零开始学 Maven:简化 Java 项目的构建与管理
Maven 是一个由 Apache 软件基金会开发的项目管理和构建自动化工具。它主要用在 Java 项目中,但也可以用于其他类型的项目。
36 1
从零开始学 Maven:简化 Java 项目的构建与管理
|
22天前
|
Java
Java项目中高精度数值计算:为何BigDecimal优于Double
在Java项目开发中,涉及金额计算、面积计算等高精度数值操作时,应选择 `BigDecimal` 而非 `Double`。`BigDecimal` 提供任意精度的小数运算、多种舍入模式和良好的可读性,确保计算结果的准确性和可靠性。例如,在金额计算中,`BigDecimal` 可以精确到小数点后两位,而 `Double` 可能因精度问题导致结果不准确。
|
25天前
|
安全 IDE Java
Java常见规范及易忘点
遵循Java编程规范和注意易忘点是提高代码质量和可维护性的关键。通过规范的命名、格式、注释和合理的代码组织,可以让代码更加清晰和易于维护。同时,注意空指针检查、线程安全、集合框架和字符串操作等常见易忘点,可以减少程序错误,提高运行效率。结合单一职责原则、面向接口编程和合理的异常处理,能够编写出高质量的Java代码。希望本文能够帮助Java开发者提升编码水平,写出更高效、更可靠的代码。
24 2
|
1月前
|
Java Android开发
Eclipse 创建 Java 项目
Eclipse 创建 Java 项目
39 4
|
1月前
|
SQL Java 数据库连接
从理论到实践:Hibernate与JPA在Java项目中的实际应用
本文介绍了Java持久层框架Hibernate和JPA的基本概念及其在具体项目中的应用。通过一个在线书店系统的实例,展示了如何使用@Entity注解定义实体类、通过Spring Data JPA定义仓库接口、在服务层调用方法进行数据库操作,以及使用JPQL编写自定义查询和管理事务。这些技术不仅简化了数据库操作,还显著提升了开发效率。
44 3
|
1月前
|
前端开发 Java 数据库
如何实现一个项目,小白做项目-java
本教程涵盖了从数据库到AJAX的多个知识点,并详细介绍了项目实现过程,包括静态页面分析、数据库创建、项目结构搭建、JSP转换及各层代码编写。最后,通过通用分页和优化Servlet来提升代码质量。
52 1
|
2月前
|
JavaScript 前端开发 Java
解决跨域问题大集合:vue-cli项目 和 java/springboot(6种方式) 两端解决(完美解决)
这篇文章详细介绍了如何在前端Vue项目和后端Spring Boot项目中通过多种方式解决跨域问题。
393 1
解决跨域问题大集合:vue-cli项目 和 java/springboot(6种方式) 两端解决(完美解决)
|
1月前
|
JavaScript Java 项目管理
Java毕设学习 基于SpringBoot + Vue 的医院管理系统 持续给大家寻找Java毕设学习项目(附源码)
基于SpringBoot + Vue的医院管理系统,涵盖医院、患者、挂号、药物、检查、病床、排班管理和数据分析等功能。开发工具为IDEA和HBuilder X,环境需配置jdk8、Node.js14、MySQL8。文末提供源码下载链接。
|
2月前
|
Java Apache Maven
Java/Spring项目的包开头为什么是com?
本文介绍了 Maven 项目的初始结构,并详细解释了 Java 包命名惯例中的域名反转规则。通过域名反转(如 `com.example`),可以确保包名的唯一性,避免命名冲突,提高代码的可读性和逻辑分层。文章还讨论了域名反转的好处,包括避免命名冲突、全球唯一性、提高代码可读性和逻辑分层。最后,作者提出了一个关于包名的问题,引发读者思考。
Java/Spring项目的包开头为什么是com?
下一篇
DataWorks