ABP vNext 标准分层解决方案项目结构完整解析

ABP vNext 标准分层解决方案项目结构完整解析

这是 ABP CLI 一键生成的完整分层式(Tiered)多模板解决方案 ,包含领域层、应用层、API、认证服务、Blazor多套UI、数据库迁移、客户端代理等全套模块,下面按职责分类拆解每个项目。

一、核心领域分层(DDD 基础四层,业务核心)

1. MyCompany.MyProject.Domain.Shared(领域共享层)

最小粒度共享程序集,无依赖污染

  • 存放:枚举、常量、异常码、本地化资源、共享DTO接口、权限常量、业务常量
  • 引用范围:所有项目都会引用它,不能依赖任何业务实现层,只放纯定义
  • 示例:订单状态枚举、错误Code、系统权限字符串、多语言.json资源文件

2. MyCompany.MyProject.Domain(领域层,DDD核心)

业务领域模型、聚合根、领域服务、领域事件

  • 核心内容:实体(AggregateRoot)、值对象、仓储接口 IRepository、领域服务 DomainService、领域事件定义、业务规则校验
  • 只依赖 Domain.Shared,不依赖数据库、API、UI,纯业务逻辑,与技术无关
  • 职责:承载核心业务规则,比如订单创建校验库存、会员等级计算逻辑

3. MyCompany.MyProject.Application.Contracts(应用契约层)

前后端/服务之间的数据契约,接口定义

  • 存放:应用服务接口 IXXXAppService、输入DTO(CreateXXXDto)、输出DTO(XXXDto)、查询分页对象
  • 仅依赖 Domain.Shared,不包含任何业务实现,是API对外暴露的"接口契约"
  • 作用:给前端/第三方客户端提供强类型调用约定,HttpApi.Client 会根据它生成代理

4. MyCompany.MyProject.Application(应用服务层)

业务流程编排,DDD应用层

  • 实现 Application.Contracts 里的所有 IXXXAppService 接口
  • 依赖:Domain(仓储、领域服务)+ Application.Contracts
  • 职责:事务控制、DTO映射、调用领域层、权限校验、工作流编排,不写核心业务规则,只做流程组装
  • 示例:创建订单AppService:校验用户权限 → 调用领域订单创建 → 扣减库存领域服务 → 发送领域事件

二、数据持久层(数据库实现)

MyCompany.MyProject.EntityFrameworkCore(EF Core 数据库实现)

  • 实现 Domain 层定义的所有 IRepository 仓储接口
  • 包含:DbContext、实体与数据库表映射配置、数据种子(Seed)、EF迁移脚本
  • 依赖 Domain、Domain.Shared
  • 仅用于SQL Server/MySQL等关系型数据库

MyCompany.MyProject.MongoDB(MongoDB 持久化实现)

  • MongoDB仓储实现,和EntityFrameworkCore二选一或共存
  • 存放Mongo DbContext、实体映射、Mongo仓储实现

MyCompany.MyProject.DbMigrator(数据库迁移控制台工具)

独立控制台程序,上线执行数据库初始化/迁移

  1. 执行EF迁移,创建/更新数据库表
  2. 初始化种子数据:管理员账号、默认租户、权限、系统配置、初始化字典
  3. 部署流水线专用,不依赖Web服务,单独运行完成库初始化

三、API 网关 & 客户端代理(前后端通信)

1. MyCompany.MyProject.HttpApi(API控制器层)

RESTful API 对外暴露层

  • 自动把 Application AppService 转为 Controller,ABP自动路由
  • 仅做转发:接收Http请求 → 调用对应AppService → 返回DTO
  • 依赖 Application、Application.Contracts
  • 不写业务逻辑,纯http适配层

2. MyCompany.MyProject.HttpApi.Client(红标重点,HTTP客户端代理)

强类型API调用客户端,给UI/第三方服务调用后端API

  • 根据 Application.Contracts 自动生成C#代理类,封装HttpClient请求
  • 项目内包含动态客户端生成代码,Blazor、第三方微服务直接引用调用接口,不用手写Http请求
  • 核心价值:前端C#项目(Blazor)无需重复定义DTO和请求逻辑,直接像本地方法一样调用远程AppService

3. MyCompany.MyProject.HttpApi.Host / HttpApi.HostWithIds

API独立宿主(分层架构专用)

  • HttpApi.Host:独立API服务启动项目,发布为单独后端接口服务
  • HttpApi.HostWithIds:集成OpenIddict身份服务一体的API宿主(一体化架构,API+认证在一个站点)
  • 配置跨域、Swagger、授权、路由,对外提供接口访问地址

四、认证授权服务(AuthServer 统一身份中心)

MyCompany.MyProject.AuthServer(独立身份认证服务)

Tiered分层架构专用,独立的OpenIddict认证中心

  • 单独部署的登录授权站点,负责颁发JWT、账号密码登录、第三方登录、客户端授权
  • API、Blazor前端全部对接这个服务做统一身份认证,实现单点登录
  • 一体化架构(非分层)会把认证逻辑合并到Web/ApiHost,分层架构拆分独立AuthServer

五、Blazor UI 多套前端项目(ABP内置三种Blazor模式)

Blazor分为 Server、WebAssembly(Client)、WebApp 三种部署形态,Tiered代表分层架构(前端独立、对接远程Api)

1. MyCompany.MyProject.Blazor(基础Blazor共享层)

Blazor页面共享组件、布局、公共UI逻辑、弹窗、菜单、权限组件,给下面所有Blazor项目引用

2. Blazor Server 模式

  • MyCompany.MyProject.Blazor.Server:一体化Blazor Server(和API同进程)
  • MyCompany.MyProject.Blazor.Server.Tiered:分层Blazor Server(独立前端,远程调用HttpApi)

3. Blazor WebAssembly(WebApp)模式(前后端分离,wasm客户端)

  • MyCompany.MyProject.Blazor.WebApp.Client:WebAssembly客户端(浏览器运行)
  • MyCompany.MyProject.Blazor.WebApp:一体化WebApp宿主
  • MyCompany.MyProject.Blazor.WebApp.Tiered:分层WebApp宿主
  • MyCompany.MyProject.Blazor.WebApp.Tiered.Client:分层架构下独立wasm客户端,引用HttpApi.Client调用远程API

4. Blazor.Client

纯WebAssembly客户端共享基础,存放wasm全局逻辑、认证状态管理、前端权限拦截

六、传统MVC/Razor页面Web项目(旧版UI,可选)

MyCompany.MyProject.Web / MyCompany.MyProject.Web.Host

传统ASP.NET Core Razor Pages / MVC UI项目,ABP默认提供两套UI:Blazor + Razor,新项目优先Blazor,老系统用Web层

七、test 测试目录

存放单元测试、集成测试项目,通常包含:Domain单元测试、Application应用服务测试、EF仓储测试

二、两种部署架构对应项目取舍

1. 一体化架构(单站点,开发简单)

使用:HttpApi.HostWithIds / Blazor.Server / Blazor.WebApp

  • 认证、API、UI全部在一个站点,数据库本地访问,无跨服务调用
  • 不需要独立 AuthServer、不需要 Tiered 后缀项目

2. Tiered 分层架构(分布式,生产推荐)

使用带 .Tiered 项目 + 独立 AuthServer + HttpApi.Host

拆分3个独立部署服务:

  1. AuthServer 身份认证中心
  2. HttpApi.Host 后端接口服务
  3. Blazor Tiered 前端站点
    前端通过 HttpApi.Client 远程调用API,多服务分离,支持集群、分布式部署

三、项目依赖流转极简链路(分层调用顺序)

后端内部依赖

Domain.Shared ← Domain ← Application.Contracts ← Application ← HttpApi ← HttpApi.Host

前端调用链路

Blazor 项目 → HttpApi.Client(代理)→ 远程 HttpApi.Host 接口 → Application应用服务 → Domain领域层 → EF/Mongo数据库

四、红标 HttpApi.Client 核心作用总结

  1. 自动封装所有后端AppService的HTTP请求,强类型C#代理
  2. Blazor前端直接引用,不用手写HttpClient、不用重复定义DTO
  3. 自动携带JWT令牌、处理异常、统一请求拦截
  4. 分层架构必备,是前后端C#代码互通的契约桥梁

ABP vNext Tiered 分层架构完整架构图(文字结构化+层级流程图)

一、整体分层架构流程图(从上至下:客户端 → 认证中心 → API服务 → DDD业务层 → 数据层)

#mermaid-svg-o5AqG1tVXxtNjbfR{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-o5AqG1tVXxtNjbfR .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-o5AqG1tVXxtNjbfR .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-o5AqG1tVXxtNjbfR .error-icon{fill:#552222;}#mermaid-svg-o5AqG1tVXxtNjbfR .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-o5AqG1tVXxtNjbfR .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-o5AqG1tVXxtNjbfR .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-o5AqG1tVXxtNjbfR .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-o5AqG1tVXxtNjbfR .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-o5AqG1tVXxtNjbfR .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-o5AqG1tVXxtNjbfR .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-o5AqG1tVXxtNjbfR .marker{fill:#333333;stroke:#333333;}#mermaid-svg-o5AqG1tVXxtNjbfR .marker.cross{stroke:#333333;}#mermaid-svg-o5AqG1tVXxtNjbfR svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-o5AqG1tVXxtNjbfR p{margin:0;}#mermaid-svg-o5AqG1tVXxtNjbfR .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-o5AqG1tVXxtNjbfR .cluster-label text{fill:#333;}#mermaid-svg-o5AqG1tVXxtNjbfR .cluster-label span{color:#333;}#mermaid-svg-o5AqG1tVXxtNjbfR .cluster-label span p{background-color:transparent;}#mermaid-svg-o5AqG1tVXxtNjbfR .label text,#mermaid-svg-o5AqG1tVXxtNjbfR span{fill:#333;color:#333;}#mermaid-svg-o5AqG1tVXxtNjbfR .node rect,#mermaid-svg-o5AqG1tVXxtNjbfR .node circle,#mermaid-svg-o5AqG1tVXxtNjbfR .node ellipse,#mermaid-svg-o5AqG1tVXxtNjbfR .node polygon,#mermaid-svg-o5AqG1tVXxtNjbfR .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-o5AqG1tVXxtNjbfR .rough-node .label text,#mermaid-svg-o5AqG1tVXxtNjbfR .node .label text,#mermaid-svg-o5AqG1tVXxtNjbfR .image-shape .label,#mermaid-svg-o5AqG1tVXxtNjbfR .icon-shape .label{text-anchor:middle;}#mermaid-svg-o5AqG1tVXxtNjbfR .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-o5AqG1tVXxtNjbfR .rough-node .label,#mermaid-svg-o5AqG1tVXxtNjbfR .node .label,#mermaid-svg-o5AqG1tVXxtNjbfR .image-shape .label,#mermaid-svg-o5AqG1tVXxtNjbfR .icon-shape .label{text-align:center;}#mermaid-svg-o5AqG1tVXxtNjbfR .node.clickable{cursor:pointer;}#mermaid-svg-o5AqG1tVXxtNjbfR .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-o5AqG1tVXxtNjbfR .arrowheadPath{fill:#333333;}#mermaid-svg-o5AqG1tVXxtNjbfR .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-o5AqG1tVXxtNjbfR .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-o5AqG1tVXxtNjbfR .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-o5AqG1tVXxtNjbfR .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-o5AqG1tVXxtNjbfR .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-o5AqG1tVXxtNjbfR .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-o5AqG1tVXxtNjbfR .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-o5AqG1tVXxtNjbfR .cluster text{fill:#333;}#mermaid-svg-o5AqG1tVXxtNjbfR .cluster span{color:#333;}#mermaid-svg-o5AqG1tVXxtNjbfR div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-o5AqG1tVXxtNjbfR .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-o5AqG1tVXxtNjbfR rect.text{fill:none;stroke-width:0;}#mermaid-svg-o5AqG1tVXxtNjbfR .icon-shape,#mermaid-svg-o5AqG1tVXxtNjbfR .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-o5AqG1tVXxtNjbfR .icon-shape p,#mermaid-svg-o5AqG1tVXxtNjbfR .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-o5AqG1tVXxtNjbfR .icon-shape .label rect,#mermaid-svg-o5AqG1tVXxtNjbfR .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-o5AqG1tVXxtNjbfR .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-o5AqG1tVXxtNjbfR .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-o5AqG1tVXxtNjbfR :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 持久层实现
DDD业务分层
HttpApi.Host 接口网关
独立认证服务 AuthServer
前端UI层
1.登录获取JWT
1.登录获取JWT
1.登录获取JWT
2.携带Token远程调用
2.携带Token远程调用
HTTP请求
实现
依赖仓储接口
依赖仓储接口
Blazor WebAssembly Tiered Client
Blazor Server Tiered
第三方客户端/小程序/Postman
AuthServer 身份中心

OpenIddict 登录/颁发JWT/第三方登录
HttpApi.Client 强类型代理

封装HttpClient、自动带Token、DTO契约
HttpApi 控制器层

转发HTTP请求到应用服务
Application 应用服务层

流程编排、事务、DTO映射
Application.Contracts 契约层

IAppService、输入输出DTO
Domain 领域层

聚合根、实体、领域服务、业务规则
Domain.Shared 共享层

枚举、常量、权限、本地化
EntityFrameworkCore EF仓储实现

DbContext、数据库迁移
MongoDB Mongo仓储实现
SQL Server/MySQL/MongoDB 数据库
DbMigrator 迁移工具

初始化库、种子数据、执行迁移脚本

二、按程序集依赖关系图(项目引用流向,底层→上层)

#mermaid-svg-xRgiIR4RWGzxwR3z{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-xRgiIR4RWGzxwR3z .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-xRgiIR4RWGzxwR3z .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-xRgiIR4RWGzxwR3z .error-icon{fill:#552222;}#mermaid-svg-xRgiIR4RWGzxwR3z .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-xRgiIR4RWGzxwR3z .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-xRgiIR4RWGzxwR3z .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-xRgiIR4RWGzxwR3z .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-xRgiIR4RWGzxwR3z .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-xRgiIR4RWGzxwR3z .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-xRgiIR4RWGzxwR3z .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-xRgiIR4RWGzxwR3z .marker{fill:#333333;stroke:#333333;}#mermaid-svg-xRgiIR4RWGzxwR3z .marker.cross{stroke:#333333;}#mermaid-svg-xRgiIR4RWGzxwR3z svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-xRgiIR4RWGzxwR3z p{margin:0;}#mermaid-svg-xRgiIR4RWGzxwR3z .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-xRgiIR4RWGzxwR3z .cluster-label text{fill:#333;}#mermaid-svg-xRgiIR4RWGzxwR3z .cluster-label span{color:#333;}#mermaid-svg-xRgiIR4RWGzxwR3z .cluster-label span p{background-color:transparent;}#mermaid-svg-xRgiIR4RWGzxwR3z .label text,#mermaid-svg-xRgiIR4RWGzxwR3z span{fill:#333;color:#333;}#mermaid-svg-xRgiIR4RWGzxwR3z .node rect,#mermaid-svg-xRgiIR4RWGzxwR3z .node circle,#mermaid-svg-xRgiIR4RWGzxwR3z .node ellipse,#mermaid-svg-xRgiIR4RWGzxwR3z .node polygon,#mermaid-svg-xRgiIR4RWGzxwR3z .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-xRgiIR4RWGzxwR3z .rough-node .label text,#mermaid-svg-xRgiIR4RWGzxwR3z .node .label text,#mermaid-svg-xRgiIR4RWGzxwR3z .image-shape .label,#mermaid-svg-xRgiIR4RWGzxwR3z .icon-shape .label{text-anchor:middle;}#mermaid-svg-xRgiIR4RWGzxwR3z .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-xRgiIR4RWGzxwR3z .rough-node .label,#mermaid-svg-xRgiIR4RWGzxwR3z .node .label,#mermaid-svg-xRgiIR4RWGzxwR3z .image-shape .label,#mermaid-svg-xRgiIR4RWGzxwR3z .icon-shape .label{text-align:center;}#mermaid-svg-xRgiIR4RWGzxwR3z .node.clickable{cursor:pointer;}#mermaid-svg-xRgiIR4RWGzxwR3z .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-xRgiIR4RWGzxwR3z .arrowheadPath{fill:#333333;}#mermaid-svg-xRgiIR4RWGzxwR3z .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-xRgiIR4RWGzxwR3z .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-xRgiIR4RWGzxwR3z .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-xRgiIR4RWGzxwR3z .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-xRgiIR4RWGzxwR3z .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-xRgiIR4RWGzxwR3z .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-xRgiIR4RWGzxwR3z .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-xRgiIR4RWGzxwR3z .cluster text{fill:#333;}#mermaid-svg-xRgiIR4RWGzxwR3z .cluster span{color:#333;}#mermaid-svg-xRgiIR4RWGzxwR3z div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-xRgiIR4RWGzxwR3z .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-xRgiIR4RWGzxwR3z rect.text{fill:none;stroke-width:0;}#mermaid-svg-xRgiIR4RWGzxwR3z .icon-shape,#mermaid-svg-xRgiIR4RWGzxwR3z .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-xRgiIR4RWGzxwR3z .icon-shape p,#mermaid-svg-xRgiIR4RWGzxwR3z .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-xRgiIR4RWGzxwR3z .icon-shape .label rect,#mermaid-svg-xRgiIR4RWGzxwR3z .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-xRgiIR4RWGzxwR3z .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-xRgiIR4RWGzxwR3z .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-xRgiIR4RWGzxwR3z :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} Domain.Shared
Domain
Application.Contracts
Application
HttpApi
HttpApi.Host
EntityFrameworkCore
MongoDB
AuthServer
HttpApi.Client
Blazor.WebApp.Tiered
Blazor.Server.Tiered
Blazor共享层

三、分层职责拆解对照(对应你截图里所有项目)

1. 接入层(最外层,用户访问)

  1. Blazor 系列 Tiered 项目:前端界面,浏览器交互,远程调用后端API
  2. AuthServer:独立单点登录服务,签发JWT令牌,所有客户端统一认证入口
  3. HttpApi.Host:独立后端接口服务,提供RESTful接口

2. 通信契约层(前后端统一标准)

  1. HttpApi.Client(红标项目):基于Application.Contracts自动生成C#客户端代理,前端无需手写HTTP请求
  2. Application.Contracts:前后端数据交换标准(接口、DTO),是整个系统的"契约文档"

3. DDD核心业务四层(后端业务逻辑)

项目 层级 核心职责
Domain.Shared 共享层 全局常量、枚举、权限Key、多语言、基础异常,无业务实现
Domain 领域层(DDD核心) 实体、聚合根、领域服务、核心业务规则、仓储接口
Application.Contracts 应用契约 应用服务接口、入参/出参DTO,对外暴露能力定义
Application 应用服务层 实现契约接口,事务、权限校验、流程编排、DTO转换

4. 数据持久层

  1. EntityFrameworkCore:EF Core实现Domain定义的仓储,数据库映射、迁移
  2. MongoDB:MongoDB仓储实现,NoSQL数据库适配
  3. DbMigrator:控制台工具,单独执行数据库迁移、初始化种子数据(租户、管理员、权限)

5. 辅助/UI兼容项目

  1. Blazor(无Tiered):一体化Blazor(前后端同进程,本地调用应用服务,不通过HttpApi.Client)
  2. Web / Web.Host:传统Razor MVC页面UI(老版UI方案)
  3. test:单元/集成测试项目

四、一体化架构 vs Tiered分层架构 差异补充

  1. 一体化架构(单站点部署)
    • 无独立AuthServer、无Tiered前端项目、无需HttpApi.Client远程调用
    • UI、API、认证全部在一个Host内,直接本地引用Application层,调用链路短,适合小型项目
  2. Tiered分层架构(分布式生产架构,你截图里的模板)
    • 拆分3个独立服务:Auth认证中心、HttpApi接口服务、Blazor前端站点
    • 前端通过HttpApi.Client走HTTP远程调用API,服务可独立集群、扩容、分库部署,中大型企业系统标准方案

五、一次完整请求全链路(Tiered分层场景)

  1. 用户打开Blazor前端 → 跳转AuthServer登录,输入账号密码获取JWT令牌
  2. 前端点击业务按钮 → 通过HttpApi.Client携带Token发起HTTP请求到HttpApi.Host
  3. HttpApi控制器接收请求,调用对应Application应用服务
  4. Application层校验权限、组装业务流程,调用Domain领域服务执行核心业务规则
  5. Domain通过EF/Mongo仓储操作数据库,完成增删改查
  6. 数据逐层返回,经HttpApi.Client序列化展示到Blazor页面
相关推荐
布朗克1682 小时前
39 Spring Boot Web实战
前端·spring boot·后端·实战
西安邮电大学2 小时前
有关数组的经典算法题
java·后端·其他·算法·面试
山东点狮信息科技有限公司2 小时前
点狮HRM-HRM系统安全体系与数据保护方案
后端·安全·spring·spring cloud·微服务·系统安全·资产
摇滚侠2 小时前
SpringMVC 入门到实战 SpringMVC 的执行流程 96
java·后端·spring·maven·intellij-idea
布朗克1682 小时前
38 Spring Boot入门——自动配置、核心注解与Starter机制
java·spring boot·后端
程序员老申2 小时前
外呼突然全挂了,追查 24 分钟后我发现了 etcd 最阴的一颗雷
后端·程序员
何以解忧,唯有..2 小时前
Go语言变量的声明方式详解
开发语言·后端·golang
长栎2 小时前
MyBatis 缓存为啥总是失效?装饰器模式套娃的代价
后端
bright_ye2 小时前
setjmp & longjmp 深度详解 + 代码示例
后端