学习了阿星Plus的博客项目,自己也试着搭建自己的博客。
ABP和ABP.VNext的主要区别在于核心库的精简、对领域驱动设计(DDD)的关注、以及使用的技术栈。
1、ABP VNext的核心库相比ABP更加精简,它将原有许多组件从核心库中抽离成独立的组件,这使得开发者可以更灵活地选择需要的功能。这种设计使得ABP VNext更加模块化,但也意味着管理的独立项目数量增加。
2、ABP VNext更加关注领域驱动设计,引入了聚合根、实体、值对象等概念,并提供了仓储模式和领域服务等基础设施。
ABP VNext相对于ABP,在核心库的精简、对领域驱动设计的关注以及使用的技术栈方面都有所不同。
使用命令安装ABP框架(最新版)
dotnet tool install -g Volo.Abp.Cli
dotnet tool update -g Volo.Abp.Cli
安装指定版本:
dotnet tool install -g Volo.Abp.Cli --version 3.1.0
abp new 项目名称 -> 新建项目
或者下载指定版本的ABP:
abp new Mag.Blog -csf --version 3.1.0
项目创建成功。
对项目目录做一个整理:
- 在src目录下新增项目Mag.Blog.Application.Caching,用来处理应用服务缓存
- 在src目录下新增项目Mag.Blog.BackgroundJobs,用来处理后台定时任务
- 在src目录下新增项目Mag.Blog.Swagger,这里用来编写Swagger扩展、Filter等
- 在src目录下新增项目Mag.Blog.ToolKits,这里放公共的工具类、扩展方法
- 在src目录下删除Mag.Blog.DbMigrator
- 在src目录下删除Mag.Blog.HttpApi.Client
- 修改Mag.Blog.HttpApi.Web解决方案名称为Mag.Blog.HttpApi.Hosting
- 删除Mag.Blog.HttpApi.Hosting下暂时无用的文件,只留下Program.cs
- 删除Mag.Blog.sln.DotSettings文件
项目瘦身:
Meowv.Blog.HttpApi.Hosting
新建类:MagBlogHttpApiHostingModule.cs继承自AbpModule
using Volo.Abp.AspNetCore.Mvc;
using Volo.Abp.Autofac;
using Volo.Abp.Modularity;
using Volo.Abp;
using Microsoft.Extensions.Hosting;
using Microsoft.AspNetCore.Builder;
namespace Mag.Blog.HttpApi.Hosting
{
[DependsOn(
typeof(AbpAspNetCoreMvcModule),
typeof(AbpAutofacModule)
)]
public class MagBlogHttpApiHostingModule : AbpModule
{
public override void ConfigureServices(ServiceConfigurationContext context)
{
base.ConfigureServices(context);
}
public override void OnApplicationInitialization(ApplicationInitializationContext context)
{
var app = context.GetApplicationBuilder();
var env = context.GetEnvironment();
// 环境变量,开发环境
if (env.IsDevelopment())
{
// 生成异常页面
app.UseDeveloperExceptionPage();
}
// 路由
app.UseRouting();
// 路由映射
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
}
}
}
然后在Startup.cs
使用,services.AddApplication<MeowvBlogHttpApiHostingModule>();
public class Startup
{
public void ConfigureServices(IServiceCollection services)
{
services.AddApplication<MagBlogHttpApiHostingModule>();
}
public void Configure(IApplicationBuilder app)
{
app.InitializeApplication();
}
}
修改Program.cs
代码:
public static async Task Main(string[] args)
{
await Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(builder =>
{
builder.UseIISIntegration()
.UseStartup<Startup>();
}).UseAutofac().Build().RunAsync();
}
Mag.Blog.HttpApi
Mag.Blog.HttpApi
职责主要是编写Controller,API都写在这里,同时它要依赖于Mag.Blog.Application
模块 , 删除原来的默认模块,新增默认模块类名称为:MagBlogHttpApiModule.cs
[DependsOn(
typeof(AbpIdentityHttpApiModule),
typeof(MagBlogApplicationModule)
)]
public class MagBlogHttpApiModule : AbpModule
{
}
Mag.Blog.Application
Mag.Blog.Application
为我们的应用服务层,在这里编写服务的接口以及对应的实现,删除原有默认类,新建默认模块类:MagBlogApplicationModule
namespace Mag.Blog
{
[DependsOn(
typeof(AbpIdentityApplicationModule)
)]
public class MagBlogApplicationModule : AbpModule
{
public override void ConfigureServices(ServiceConfigurationContext context)
{
Configure<AbpAutoMapperOptions>(options =>
{
options.AddMaps<MagBlogApplicationModule>(validate:true);
});
}
}
}
然后在Mag.Blog.HttpApi
层中添引用:Mag.Blog.Application
,同时添加依赖模块类,MagBlogApplicationModule
Mag.Blog.HttpApi
设置输出一下API XML文件,XML文件的作用后续Swagger会用到
<Project Sdk="Microsoft.NET.Sdk">
<Import Project="..\..\common.props" />
<PropertyGroup>
<TargetFramework>netcoreapp3.1</TargetFramework>
<RootNamespace>Mag.Blog</RootNamespace>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
<DocumentationFile>..\Mag.Blog.HttpApi.Hosting\Mag.Blog.HttpApi.xml</DocumentationFile>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\Mag.Blog.Application.Contracts\Mag.Blog.Application.Contracts.csproj" />
<ProjectReference Include="..\Mag.Blog.Application\Mag.Blog.Application.csproj" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Volo.Abp.Account.HttpApi" Version="3.1.0" />
<PackageReference Include="Volo.Abp.Identity.HttpApi" Version="3.1.0" />
<PackageReference Include="Volo.Abp.PermissionManagement.HttpApi" Version="3.1.0" />
<PackageReference Include="Volo.Abp.TenantManagement.HttpApi" Version="3.1.0" />
<PackageReference Include="Volo.Abp.FeatureManagement.HttpApi" Version="3.1.0" />
</ItemGroup>
</Project>
在Mag.Blog.Application类库中新建一个服务基类:ServiceBase.cs
继承自ApplicationService
namespace Mag.Blog
{
/* Inherit your application services from this class.
*/
public abstract class ServiceBase : ApplicationService
{
}
}
新建测试服务接口与实现类:IHelloWorldService,HelloWorldService
namespace Mag.Blog.HelloWorld
{
public interface IHelloWorldService
{
string HelloWorld();
}
}
namespace Mag.Blog.HelloWorld
{
public class HelloWorldService : ServiceBase, IHelloWorldService
{
public string HelloWorld()
{
return "Hello Word!";
}
}
}
在Mag.Blog.HttpApi类库中新增测试控制器HelloWorldController
namespace Mag.Blog.Controllers
{
[ApiController]
[Route("[controller]")]
public class HelloWorldController : AbpController
{
private readonly IHelloWorldService _helloWorldService;
public HelloWorldController(IHelloWorldService helloWorldService)
{
_helloWorldService = helloWorldService;
}
[HttpGet]
public string HelloWorld()
{
return _helloWorldService.HelloWorld();
}
}
}
设置Mag.Blog.HttpApi.Hosting类库为启动项目,并在默认模块类中依赖Mag.Blog.HttpApi类库的默认类
F5启动项目,浏览器输入HelloWorld,显示测试项
瘦身之后的项目结构为:
Mag.Blog.Domain
层为我们的实体领域模型,是领域层,设置输出一下XML文件,XML文件的作用后续Swagger会用到
<Project Sdk="Microsoft.NET.Sdk">
<Import Project="..\..\common.props" />
<PropertyGroup>
<TargetFramework>netcoreapp3.1</TargetFramework>
<RootNamespace>Mag.Blog</RootNamespace>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
<DocumentationFile>..\Mag.Blog.HttpApi.Hosting\Mag.Blog.Domain.xml</DocumentationFile>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\Mag.Blog.Domain.Shared\Mag.Blog.Domain.Shared.csproj" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Volo.Abp.Identity.Domain" Version="3.1.0" />
</ItemGroup>
</Project>
删除.Domain层下的文件,添加默认模块MagBlogDomainModule.cs,
依赖AbpIdentityDomainModule
namespace Mag.Blog
{
[DependsOn(typeof(AbpIdentityDomainModule))]
public class MagBlogDomainModule : AbpModule
{
}
}
Mag.Domain.Shared
层相当于.Domain
的一个扩展一样,这里放一下项目用到的枚举、公共常量等内容,需要引用我们的.Domain
项目
新增一个模块类MagBlogDomainSharedModule.cs
,它依赖AbpIdentityDomainSharedModule
模块
namespace Mag.Blog
{
[DependsOn(typeof(AbpIdentityDomainSharedModule))]
public class MagBlogDomainSharedModule : AbpModule
{
}
}
应用层
Mag.Blog.Application添加引用Mag.Blog.Application.Caching 缓存项目,会用到两个包,Volo.Abp.Caching
、Microsoft.Extensions.Caching.Redis,
新建一个模块类MagBlogApplicationCachingModule.cs
,依赖于AbpCachingModule
和我们的MagBlogDomainModule
模块
namespace Mag.Blog.Application.Caching
{
[DependsOn(typeof(AbpCachingModule),
typeof(MagBlogDomainModule))]
public class MagBlogApplicationCachingModule : AbpModule
{
public override void ConfigureServices(ServiceConfigurationContext context)
{
base.ConfigureServices(context);
}
}
}
Mag.Application.Contracts
删掉里面所有文件,.Application.Contracts
层用来放传输对象(DTO),添加项目引用Mag.Blog.Domain.Shared
,同时开启输出XML文件到我们.HttpApi.Hosting
<Project Sdk="Microsoft.NET.Sdk">
<Import Project="..\..\common.props" />
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<RootNamespace>Mag.Blog</RootNamespace>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
<DocumentationFile>..\Mag.Blog.HttpApi.Hosting\Mag.Blog.Application.Contracts.xml</DocumentationFile>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\Mag.Blog.Domain.Shared\Mag.Blog.Domain.Shared.csproj" />
</ItemGroup>
</Project>
Mag.Blog.EntityFrameworkCore
Mag.Blog.EntityFrameworkCore
层删掉默认生成的文件。它主要是集成了EF Core,自定义仓储,支持多种数据库 MySQL、SqlServer、PostgreSql、Sqlite等,添加数据库相关的项目包,引用Mag.Blog.Domain.Shared
项目
<Project Sdk="Microsoft.NET.Sdk">
<Import Project="..\..\common.props" />
<PropertyGroup>
<TargetFramework>netcoreapp3.1</TargetFramework>
<RootNamespace>Mag.Blog</RootNamespace>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\Mag.Blog.Domain\Mag.Blog.Domain.csproj" />
<PackageReference Include="Volo.Abp.EntityFrameworkCore.MySQL" Version="3.1.0" />
<PackageReference Include="Volo.Abp.EntityFrameworkCore.PostgreSql" Version="3.1.0" />
<PackageReference Include="Volo.Abp.EntityFrameworkCore.Sqlite" Version="3.1.0" />
<PackageReference Include="Volo.Abp.EntityFrameworkCore.SqlServer" Version="3.1.0" />
</ItemGroup>
</Project>
新建一个模块类MagBlogFrameworkCoreModule.cs
,依赖MagBlogDomainModule
和数据库模块
namespace Mag.Blog
{
[DependsOn(typeof(MagBlogDomainModule),
typeof(AbpEntityFrameworkCoreModule),
typeof(AbpEntityFrameworkCoreMySQLModule),
typeof(AbpEntityFrameworkCorePostgreSqlModule),
typeof(AbpEntityFrameworkCoreSqlServerModule),
typeof(AbpEntityFrameworkCoreSqliteModule))]
public class MagBlogFrameworkCoreModule : AbpModule
{
public override void ConfigureServices(ServiceConfigurationContext context)
{
base.ConfigureServices(context);
}
}
}
Mag.Blog.EntityFrameworkCore.DbMigrations
Mag.Blog.EntityFrameworkCore.DbMigrations
层主要做数据库迁移,用code-first方式创建数据库表.
Mag.Blog..ToolKits
Mag.Blog.ToolKits
层是我们手动创建的项目,我主要用它来包装一些扩展方法,公共的工具类.