单体工程结构

news2024/11/26 10:22:28

本文主要说明下单体项目的工程结构如何设计,目前业界存在两种主流的应用工程结构:一种是阿里推出的《Java开发手册》中推荐的,另外一种是基于DDD(领域驱动设计)推荐的。下面我们来看下两种工程结构是怎样的。

一、 基于阿里《Java开发手册》的分层结构

阿里巴巴的官方文档的分层主要是分为如下这些层:

开放API 层:可直接封装Service 接口暴露成RPC 接口;通过Web 封装成http 接口;网关控制层等。
终端显示层:各个端的模板渲染并执行显示的层。当前主要是velocity 渲染,JS 渲染,JSP 渲染,移动端展示等。
Web 层:主要是对访问控制进行转发,各类基本参数校验,或者不复用的业务简单处理等。
Service 层:相对具体的业务逻辑服务层。
Manager 层:通用业务处理层,它有如下特征:
          1)对第三方平台封装的层,预处理返回结果及转化异常信息,适配上层接口。
           2)对Service 层通用能力的下沉,如缓存方案、中间件通用处理。
           3)与DAO 层交互,对多个DAO 的组合复用。
DAO 层:数据访问层,与底层MySQL、Oracle、Hbase、OB 等进行数据交互。
第三方服务:包括其它部门RPC 服务接口,基础平台,其它公司的HTTP 接口,如淘宝开放平台、支付宝付款服务、高德地图服务等。
外部数据接口:外部(应用)数据存储服务提供的接口,多见于数据迁移场景中。

调用关系如下:

涉及到的领域模型如下:

DO(Data Object):此对象与数据库表结构一一对应,通过DAO 层向上传输数据源对象。
DTO(Data Transfer Object):数据传输对象,Service 或Manager 向外传输的对象。
BO(Business Object):业务对象,可以由Service 层输出的封装业务逻辑的对象。
Query:数据查询对象,各层接收上层的查询请求。注意超过2 个参数的查询封装,禁止使用Map 类来传输。
VO(View Object):显示层对象,通常是Web 向模板渲染引擎层传输的对象

基于这样的规范我创建了一个demo工程的目录,下面我来解释下这个结构



├─src
│  ├─main
│  │  ├─java
│  │  │  └─com
│  │  │      └─demo
│  │  │          ├─client           --第三方服务:调用第三方服务
│  │  │          │  ├─model         --模型对象
│  │  │          │  └─service       --接口
│  │  │          ├─controler        --终端显示层
│  │  │          │  ├─request       --请求对象
│  │  │          │  ├─response      --响应包装对象
│  │  │          │  └─vo            --不同接口显示层对象
│  │  │          ├─dao              --DAO 层
│  │  │          │  ├─config        --数据库的配置文件
│  │  │          │  ├─dbclient      --与底层MySQL、Oracle、Hbase等进行数据交互的文件
│  │  │          │  ├─query         --数据查询对象
│  │  │          │  ├─do            --此对象与数据库表结构一一对应
│  │  │          │  ├─serializer    --序列化相关  
│  │  │          │  ├─sharding      --分库分表类目
│  │  │          │  └─utils         --一些公共类
│  │  │          ├─facede           --开放API 层:对外封装的Service接口暴露成RPC接口
│  │  │          │  ├─constant      --常量
│  │  │          │  ├─model         
│  │  │          │  ├─request       --请求对象
│  │  │          │  └─service       --接口层
│  │  │          ├─job              --开放API 层:处理job工作           
│  │  │          │  └─model         --数据传输对象
│  │  │          ├─manager          --Manager 层
│  │  │          │  └─dto           
│  │  │          ├─mq               --开放API 层:处理mq工作
│  │  │          │  ├─config
│  │  │          │  ├─consumer      --处理消费者工作
│  │  │          │  ├─model
│  │  │          │  └─publish       --处理生产者工作

│  │  │          ├─service          --Service 层
│  │  │             ├─schedule      --处理定时任务
│  │  │          │  ├─bo
│  │  │          │  └─dto
│  │  │          └─web              --Web 层
│  │  │              ├─filter       --过滤层
│  │  │              └─Interceptor  --拦截器层
│  │  └─resources                   --资源文件
│  │      └─META-INF
│  └─test                           --针对每个层次文件的测试文件
│      └─java
│          └─com
│              └─demo
│                  ├─client
│                  │  ├─model
│                  │  └─service
│                  ├─controler
│                  │  ├─request
│                  │  ├─response
│                  │  └─vo
│                  ├─dao
│                  │  ├─config
│                  │  ├─dbclient
│                  │  ├─do
│                  │  ├─query
│                  │  ├─sharding
│                  │  ├─serializer
│                  │  ├─sharding
│                  │  └─utils
│                  ├─facede
│                  │  ├─constant
│                  │  ├─model
│                  │  ├─request
│                  │  └─service
│                  ├─job
│                  │  └─model
│                  ├─manager
│                  │  └─dto
│                  ├─mq
│                  │  ├─config
│                  │  ├─consumer
│                  │  ├─model
│                  │  └─publish

│                  ├─service
│                  │  ├─schedule
│                  │  ├─bo
│                  │  └─dto
│                  └─web
│                      ├─filter
│                      └─Interceptor
└─
 

可能上面的信息比较多看者比较不清晰,下面我们用列表来展示下:

层次

包名

对象名规范

备注

测试层

test

对象名规范同各层级

开放API 层

job、mq、

model

model为模型对象

终端显示层

controler

request、response、vo

Web 层

web

Service层

service

bo、dto

Manager层

manager

dto

DAO层

dao

query、do

第三方服务

client

model

二、 基于DDD(领域驱动设计)的分层结构

DDD(领域驱动设计,Domain-Driven Design)的分层结构主要是为了更好地组织和分离关注点,确保业务逻辑的清晰性和可维护性。DDD 的分层结构通常包括以下几个层次:

  1. 用户接口层(User Interface Layer):
    • 这一层主要负责与前端应用或其他外部服务的交互。
    • 它会接收和响应外部请求,并将业务逻辑的结果展示给用户。
    • 这一层不应该包含任何业务逻辑,主要是数据的展示和接收。
  1. 应用服务层(Application Service Layer):
    • 这一层是DDD中的业务编排层,它协调领域层中的各个组件来执行特定的业务用例。
    • 应用服务层通常包含服务组合、编排、安全认证、权限校验、事务控制等功能。
    • 应用服务层可能会调用多个领域服务来完成一个复杂的业务操作。
  1. 领域层(Domain Layer):
    • 这是DDD中的核心层,包含了业务领域的所有核心逻辑和概念。
    • 领域层主要由实体(Entity)、值对象(Value Object)、领域服务(Domain Service)和领域事件(Domain Event)等组成。
    • 实体和值对象表达了业务概念,而领域服务则实现了复杂的业务规则。
  1. 基础设施层(Infrastructure Layer):
    • 这一层提供了技术实现和支撑服务,如数据库访问、消息传递、缓存等。
    • 基础设施层为上层提供了技术细节的实现,隐藏了底层技术的复杂性。
    • 基础设施层通常实现了领域层中定义的接口和协议,使得上层可以专注于业务逻辑。

DDD的分层结构遵循了依赖倒置原则(Dependency Inversion Principle),即高层模块不应该依赖于低层模块,它们都应该依赖于抽象。此外,DDD的分层结构还强调了领域层的独立性和核心地位,确保业务逻辑的稳定性和可重用性。四个层次调用关系如下:

根据这样的架构我们来理解下和工程结构的映射关系大致如下:

具体到业务流程中是这样的:

基于ddd,我们也可以根据这样的架构来设计一个工程结构,如下:

├─com.company.microservice
├─com.company.microservice
│    │ 
│    ├─apis   API接口层 
│    │    └─controller       控制器,对外提供(Restful)接口
│    │ 
│    ├─application  应用层
│    │    ├─model            数据传输对象模型及其装配器(含校验)
│    │    │    ├─assembler   装配器,,实现模型转换eg. apiModel<=> domainModel
│    │    │    └─dto         模型定义(含校验规则)      
│    │    ├─service          应用服务,非核心服务,跨领域的协作、复杂分页查询等
│    │    ├─task             任务定义,协调领域模型
│    │    ├─listener         事件监听定义
│    │    └─***              others
│    │ 
│    ├─domain   领域层
│    │    ├─common           模块0-公共代码抽取,限于领域层有效  
│    │    ├─module-xxx       模块1-xxx,领域划分的模块,可理解为子域划分     
│    │    ├─module-user      模块2-用户子域(领域划分的模块,可理解为子域划分)
│    │    │    ├─action      行为定义
│    │    │    │    ├─UserDomainService.java        领域服务,用户领域服务
│    │    │    │    ├─UserPermissionChecker.java    其他行为,用户权限检查器
│    │    │    │    ├─WhenUserCreatedEventPublisher.java     领域事件,当用户创建完成时的事件 
│    │    │    ├─model       领域聚合内模型 
│    │    │    │    ├─UserEntity.java                领域实体,有唯一标识的充血模型,如本身的CRUD操作在此处
│    │    │    │    ├─UserDictVObj.java              领域值对象,用户字典kv定义       
│    │    │    |    ├─UserDPO.java                   领域负载对象    
│    │    │    ├─repostiory  领域仓储接口
│    │    │    │    ├─UserRepository.java
│    │    │    ├─reference   领域适配接口
│    │    │    │    ├─UserEmailSenderFacade.java
│    │    │    └─factory     领域工厂  
│    │ 
│    ├─infrastructure  基础设施层
│    │    ├─persistence      持久化机制
│    │    │    ├─converter   持久化模型转换器
│    │    │    ├─po          持久化对象定义 
│    │    │    └─repository.impl  仓储类,持久化接口&实现,可与ORM映射框架结合
│    │    ├─general          通用技术支持,向其他层输出通用服务
│    │    │    ├─config      配置类
│    │    │    ├─toolkit     工具类  
│    │    │    ├─extension   扩展定义  
│    │    │    └─common      基础公共模块等 
│    │    ├─reference        引用层,包装外部接口用,防止穿插到Domain层腐化领域模型等
│    │    │    ├─dto         传输模型定义
│    │    │    ├─converter   传输模型转换器       
│    │    │    └─facade.impl 适配器具体实现,此处的RPC、Http等调用
│    │ 
│    └─resources  
│        ├─statics  静态资源
│        ├─template 系统页面 
│        └─application.yml   全局配置文件

以上就是我对于两种工程结构的阐述,对于两种项目结构,大家要根据自己的项目情况和公司情况进行微调。原因是每种理论都有自己的产生背景、适用条件和使用方法,不能硬搬硬套。而且理论也是有很多变种的,例如ddd也有很多种架构的,例如:洋葱架构、六边形架构等,根据每项架构我们的工程结构肯定还会有一些变种,限于知识的理解不深,本次就不再描述了。ddd我了解的专家是张逸老师,他的著作《解构领域驱动设计》对于ddd的解释是比较全面的,我们做技术的也是基于在一个公司里面做业务,所以工作的上下文中又有了公司和业务者两块,针对这两块,现在的认识是要通过学习togaf这样的企业架构框架和周金根老师的《业务架构解构与实践》这样的著作来深化自己对做好技术工作的理解。

三、两种结构的适用背景

(一)阿里巴巴分层架构

现在对这个结构的认识是比较适用于:

1、在团队还比较小,职责还不是那么清晰的时候,

2、发展变化比较大的业务,因为此时还没有明确的领域概念,团队设置上也没有专人来保证领域的设计;

3、重心在与快速的支撑业务。

(二)ddd分层架构

DDD模式适用于以下几种场景:

1、支持处理复杂业务逻辑场景:当应用程序需要处理复杂的业务逻辑时,DDD可以将业务逻辑封装在领域模型中,从而更好地反映业务需求和业务流程,降低了系统架构的复杂度;

2、多团队协作:当多个团队共同开发一个大型系统时,DDD分层架构可以帮助团队之间更好地协作,每个团队负责不同的领域模型和业务逻辑,减少冲突和重复开发;

3、大型业务需要长期演化并快速迭代和交付的场景:每个子域都可以独立开发、部署和扩展,这样可以使得团队可以快速迭代和交付应用程序

如果将普通的CRUD业务系统也按照这套模式实现,反而会增加系统的复杂度。在现在的认识中,一般中大型的技术团队要能支撑起ddd这样的分层架构,在架构师层面至少有企业架构师、领域架构师(应用架构师)、业务架构师(应用架构师)、技术架构师、基础结构架构师,基础架构架构师有的有会分为、安全架构师、数据架构师其中的几个,但是在团队比较小变化大的业务中,很难支撑这样的团队配置,导致要在做好业务架构设计和时间、人力成本、机会成本、人员职责等产生了矛盾,最终妥协的结构应该就是采取阿里巴巴分层来快速低成本的支持业务跑起来。

参考:DDD-经典四层架构应用_ddd四层架构-CSDN博客、DDD领域驱动设计四、分层架构和代码模型_ddd四种领域模型-CSDN博客、Java应用工程结构 - CN.programmer.Luxh - 博客园 (cnblogs.com)、业务架构 - 知乎 (zhihu.com)、领域驱动设计 - 企业架构设计方法与实践 (tonydeng.github.io)

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

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

相关文章

基于FPGA的UDP实现(包含源工程文件)

1、概括 前文通过FPGA实现了ARP和ICMP协议&#xff0c;ARP协议一般用来获取目的IP地址主机的MAC地址&#xff0c;ICMP通过回显请求和回显应答来判断以太网链路是否通畅&#xff0c;这两个协议都不是用来传输用户数据的。如果用户需要向PC端传输大量数据&#xff0c;那么就必须使…

Swift Combine 通过用户输入更新声明式 UI 从入门到精通十五

Combine 系列 Swift Combine 从入门到精通一Swift Combine 发布者订阅者操作者 从入门到精通二Swift Combine 管道 从入门到精通三Swift Combine 发布者publisher的生命周期 从入门到精通四Swift Combine 操作符operations和Subjects发布者的生命周期 从入门到精通五Swift Com…

证明之缺角正方形网格的铺地砖问题

缺角正方形网格的铺地砖问题 “挑战难题&#xff1a;多米诺骨牌与无法覆盖的方格” 这里有个著名的难题。画八横八纵正方形网格&#xff0c;去掉相对的两个角。你能用多米诺骨牌形状的地砖——每一块正好覆盖两个相邻方格&#xff0c;把剩余部分覆盖吗&#xff1f;我在下图中…

bert-vits2本地部署报错疑难问题汇总

环境&#xff1a; bert-vits2.3 win 和wsl 问题描述&#xff1a; bert-vits2本地部署报错疑难问题汇总 解决方案&#xff1a; 问题1: Conda安装requirements里面依赖出现ERROR: No matching distribution found for opencc1.1.6 解决方法 需要在 Python 3.11 上使用 Op…

Springboot加载bootstrap和application原理

Springboot加载bootstrap和application原理 bootstrap.yml能被springboot加载导入依赖 <parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.4.6</version><rel…

StringBuilder

StringBuilder代表可变字符串&#xff0c;相当于一个容器&#xff0c;里面的字符串可以改变&#xff0c;用来操作字符串。此类设计用作StringBuffer替代品。 构造方法&#xff1a; StringBuilder() StringBuilder(String str) 操作方法&#xff1a; 1. append()&#xff1…

【Spring】定义过滤器Filter和拦截器Interceptor

# 定义过滤器 package com.holen.filter;import jakarta.servlet.Filter; import jakarta.servlet.FilterChain; import jakarta.servlet.ServletException; import jakarta.servlet.ServletRequest; import jakarta.servlet.ServletResponse; import java.io.IOException;pub…

2048游戏C++板来啦!

个人主页&#xff1a;PingdiGuo_guo 收录专栏&#xff1a;C干货专栏 大家好呀&#xff0c;我是PingdiGuo_guo&#xff0c;今天我们来学习如何用C编写一个2048小游戏。 文章目录 1.2048的规则 2.步骤实现 2.1: 初始化游戏界面 2.1.1知识点 2.1.2: 创建游戏界面 2.2: 随机…

【开源】基于JAVA+Vue+SpringBoot的班级考勤管理系统

目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块2.1 系统基础支持模块2.2 班级学生教师支持模块2.3 考勤签到管理2.4 学生请假管理 三、系统设计3.1 功能设计3.1.1 系统基础支持模块3.1.2 班级学生教师档案模块3.1.3 考勤签到管理模块3.1.4 学生请假管理模块 3.2 数据库设…

VS Code主题设置(美化VS Code)(主题+背景+图标+特效+字体)

目录 切换整体主题&#xff08;整体主题&#xff09; 切换文件图标主题 设置VS Code背景图案 字体特效 连击特效 字体设置 主题的具体效果放在了文章末尾&#xff0c;这篇文章后续也会进行更新 ————————————————————————————…

Vulnhub靶机:DC3

一、介绍 运行环境&#xff1a;Virtualbox 攻击机&#xff1a;kali&#xff08;10.0.2.15&#xff09; 靶机&#xff1a;DC3&#xff08;10.0.2.56&#xff09; 目标&#xff1a;获取靶机root权限和flag 靶机下载地址&#xff1a;https://www.vulnhub.com/entry/dc-32,312…

get和set方法太多太臃肿?快使用 lombok

目录 0. lombok 介绍 1. lombok 使用 1.1 创建一个 maven 项目 1.2 在项目中引用依赖 1.3 在 idea 中添加 lombok 插件 1.4 使用 lombok 注解 1.5 Idea 运行报 Lombok requires enables annotation process 错误解决办法 0. lombok 介绍 当我们写一个类时&#xff0c;为了…

EsayExcel文件导入导出

目录 准备工作 监听器类 导入测试 导出测试 上传Excel 下载Excel 混合导出模板导出 headRowNumber(1)&#xff1a;从第几行开始读 准备工作 导入依赖 <!--easyexcel--> <dependency><groupId>com.alibaba</groupId>x<artifactId>easye…

微服务—ES数据同步

目录 数据同步 问题分析 方案1. 同步调用 方案2. 异步通知 方案3. 监听binlog​编辑 各方案对比 案例——利用MQ实现数据同步 步骤1. 导入hotel-admin项目 步骤2. 声明交换机、队列 步骤3. 发送MQ消息 步骤4. 接收MQ消息 步骤5. 测试同步功能 数据同步 elasticsea…

小白学Halcon100例:如何获取物品中心坐标并展示

文章目录 *读入彩色图片*分解彩色图片为三通道*阈值分割*链接*选择特征*提取目标中心*绘制目标中心--*设置线宽为1*创建十字轮廓*清空窗体*设置绘制模式为绘制边缘*显示目标*显示目标中心*读入彩色图片

算法学习——LeetCode力扣回溯篇4

算法学习——LeetCode力扣回溯篇4 332. 重新安排行程 332. 重新安排行程 - 力扣&#xff08;LeetCode&#xff09; 描述 给你一份航线列表 tickets &#xff0c;其中 tickets[i] [fromi, toi] 表示飞机出发和降落的机场地点。请你对该行程进行重新规划排序。 所有这些机票…

python 基础知识点(蓝桥杯python科目个人复习计划41)

今日复习内容&#xff1a;动态规划&#xff08;基础&#xff09; 动态规划是一种解决多阶段决策过程中最优化问题的数学方法和算法思想。它通常用于解决具有重叠子问题和最优子结构性质的问题&#xff0c;通常将问题划分为相互重叠的子问题&#xff0c;利用子问题的解来求解原…

机器学习3----决策树

这是前期准备 import numpy as np import pandas as pd import matplotlib.pyplot as plt #ID3算法 #每个特征的信息熵 # target : 账号是否真实&#xff0c;共2种情况 # yes 7个 p0.7 # no 3个 p0.3 info_D-(0.7*np.log2(0.7)0.3*np.log2(0.3)) info_D #日志密度…

一周学会Django5 Python Web开发-Django5 Hello World编写

锋哥原创的Python Web开发 Django5视频教程&#xff1a; 2024版 Django5 Python web开发 视频教程(无废话版) 玩命更新中~_哔哩哔哩_bilibili2024版 Django5 Python web开发 视频教程(无废话版) 玩命更新中~共计14条视频&#xff0c;包括&#xff1a;2024版 Django5 Python we…

Cocos2dx-lua ScrollView[一]基础篇

一.ScrollView概述 cocos游戏中ScrollView控件大量使用,95%以上的项目都会使用ScrollView,个别游戏可能全部使用翻页的滑动效果。如果想要精通Cocos的UI开发,精通ScrollView控件非常关键,因此对ScrollView的使用进行总结很有必要。 下文缩写说明:sv = ScrollView, item代…