ABPvNext微服务架构详细教程——基础服务层
1. 创建服务
在除⾝份管理相关服务以外的其他业务服务中,我们不需要包含⽤户⾓⾊权限管理功能模块,ABP vNext框架为我们提供了模块模式,其默认模板不包含⾝份管理相关模块,更适合⽤于搭建普通的业务微服务。以产品管理服务为例,我们在解决⽅案⽬录中到service⽬录,在其中创建productmanager⽬录,切换⾄该⽬录并启动cmd命令⾏。使⽤以下命令创建产品管理服务:
abp new Demo.ProductManager -t module --no-ui
其中-t module表⽰模块模式,--no-ui表⽰不使⽤UI界⾯,在ABP vNext框架Module模式下⼀直存在⼀个问题,创建时⽆法和Application⼀样使⽤-dbms参数设置数据库类型,⽽是使⽤默认的SQL Server数据库类型,这⾥我们的项⽬采⽤MySQL数据库,需要⼿动修改为MySQL,具体⽅法见下⼀章节。
因为我们⾝份认证服务采⽤统⼀的服务,所以我们在⽣成的模板中到host⽬录下的ProductManager.IdentityServer项⽬⽂件夹并删除,数据库我们不使⽤MongoDB,所以可以将src⽬录下
的ProductManager.MongoDB项⽬⽂件夹和test⽬录下的ProductManager.MongoDB.Tests项⽬⽂件夹删除。之后我们可以删除该项⽬根⽬录下database⽂件夹和除Demo.ProductManager.sln、common.props以外的所有⽂件,如果不需要对该项⽬进⾏单元测试,也可删除test⽂件夹。清理后,跳转到总解决⽅案所在⽬录,使⽤解决⽅案构建⼯具将个产品管理服务所有项⽬添加到总解决⽅案,添加后效果如下:
2. 切换为MySQL数据库
将Module模式项⽬从SQL Server数据库更改为MySQL数据库步骤如下:
1. 到ProductManager.HttpApi.Host项⽬移除其Nuget引⽤中的Volo.Abp.EntityFrameworkCore.SqlServer,然后添加Nuget引⽤
Volo.Abp.EntityFrameworkCore.MySQL,注意版本号和主项⽬ABP框架版本⼀致。
2. 到ProductManager.HttpApi.Host项⽬中的模块类ProductManagerHttpApiHostModule,将其特性DependsOn特性中引⽤
的typeof(AbpEntityFrameworkCoreSqlServerModule) 更改为typeof(AbpEntityFrameworkCoreMySQLModule) 并将其命名空间引⽤using
Volo.Abp.EntityFrameworkCore.SqlServer; 改为using Volo.Abp.EntityFrameworkCore.MySQL; 。将ConfigureServices⽅法的
Configure<AbpDbContextOptions>(options => { options.UseSqlServer(); });改为 Configure<AbpDbContextOptions>(options => { options.UseMySQL(); });
3. 到ProductManager.HttpApi.Host项⽬中的ProductManagerHttpApiHostMigrationsDbContextFactory类,将其⽅法CreateDbContext中的var builder =
new DbContextOptionsBuilder<ProductManagerHttpApiHostMigrationsDbContext>()
.UseSqlServer(configuration.GetConnectionString("ProductManager")); 改为以下代码(注意我的MySQL版本为5.7,具体版本号请依据个⼈情况修改):var builder = new DbContextOptionsBuilder<ProductManagerHttpApiHostMigrationsDbContext>()
.UseMySql(configuration.GetConnectionString("ProductManager"),ServerVersion.Parse("5.7.28-mysql"));
4. 修改Demo.ProductManager.HttpApi.Host项⽬的appsettings.json配置⽂件,和Application模式不同,我们会发现Module模式下ABP vNext框架提供的项⽬
模板ConnectionStrings项会包含Default和ProductManager两个配置项。其中Default为ABP框架基础
配置信息的数据库,⾝份管理服务已包含其所需的所有数据,所以我们将Default配置为和⾝份管理中⼼相同的数据库链接。ProductManger也就是和当前项⽬相同的数据库配置项,所指向的数据库为对当前模块领域实体持久化的数据库,需要在当前项⽬中配置和创建。
5. 进⼊Demo.ProductManager.HttpApi.Host项⽬所在⽬录,执⾏数据迁移命令 dotnet-ef database update ,执⾏成功后查看数据库,发现已创建模块数据
库,且仅包含__EFMigrationsHistory表,则数据库链接成功。
3.初始化运⾏
在Demo.ProductManager.Application、Demo.ProductManager.Application.Contracts、Demo.ProductManager.HttpApi三个项⽬中分别到Samples⽂件夹并删除,这是ABP vNext提供的样例API,没有实际⽤途。
设置端⼝号为5010并允许IP地址访问,⽅式为在Demo.ProductManager.HttpApi.Host项⽬配置⽂件appsettings.json中添加配置项:"urls": "*:5010"
上⼀章节我们已经配置了数据库链接字符串,我们继续编辑Demo.ProductManager.HttpApi.Host项⽬配置⽂件appsettings.json,设置Redis链接字符串。
启动Demo.ProductManager.HttpApi.Host项⽬并访问localhost:5010/swagger/index.html,可以正常显⽰Swagger页⾯,即启动成功。
4.产品管理
4.1.
在Demo.ProductManager.Domain项⽬中添加Products⽂件夹(产品领域)并创建Product类(产品聚合根)代码如下:
using System;
using Volo.Abp.Domain.Entities;
namespace Demo.ProductManager.Products;
///<summary>
///产品
///</summary>
public class Product : AggregateRoot<Guid>
{
///<summary>
///名称
///</summary>
public string Name { get; set; }
///<summary>
/
//价格
///</summary>
public float Price { get; set; }
}
4.2. 数据库创建
在Demo.ProductManager.EntityFrameworkCore项⽬中到IProductManagerDbContext接⼝和ProductManagerDbContext类,分别添加 DbSet<Product> Products { get; set; } 和public DbSet<Product> Products { get; set; } 属性并添加响应引⽤。
在Demo.ProductManager.EntityFrameworkCore项⽬中到ProductManagerDbContextModelCreatingExtensions类中的ConfigureProductManager⽅法内添加以下内容:
builder.Entity<Product>(b =>
{
b.ToTable(ProductManagerDbProperties.DbTablePrefix + "Products", ProductManagerDbProperties.DbSchema);
b.ConfigureByConvention();
});
这⾥使⽤实体类默认设置,如果需要进⾏⾃定义修改,可⾃⾏编辑实体配置。
在Demo.ProductManager.HttpApi.Host项⽬所在⽬录中执⾏创建数据迁移语句:
dotnet-ef migrations Add BuildProduct
创建成功后执⾏数据迁移:
dotnet-ef database update
执⾏成功后,我们可以再ProductManager模块数据库中看到已新增数据库表Product,此表中除主键ID和我们⾃⼰定义的两个字段以外,如果Product继承⾃AggregateRoot,则会包含ExtraProperties和
ConcurrencyStamp两个字段,分别为扩展属性和并发戳。若继承⾃Entity则默认不会包含这两个字段。
4.3.
为⽅便演⽰,本实例采⽤CrudAppService,对Product提供增删改查接⼝,具体实现⽅式如下:
在Demo.ProductManager.Application.Contracts项⽬中创建Products⽂件夹并在其中创建Dto⽂件夹。在Dto⽂件夹中存放产品管理的数据传输对象,这⾥增改查接⼝统⼀使⽤ProductDto,代码如下:
using System;
using Volo.Abp.Application.Dtos;
using Volo.Abp.Domain.Entities;
namespace Demo.ProductManager.Products.Dto;
///<summary>
///产品DTO
///</summary>
public class ProductDto : EntityDto<Guid>, IHasConcurrencyStamp
{
///<summary>
///名称
///</summary>
public string Name { get; set; }
///<summary>
///价格
///</summary>
public float Price { get; set; }
///<summary>
///并发戳
///</summary>
public string ConcurrencyStamp { get; set; }
}
这⾥因为我们使⽤聚合根,修改数据时需要提供并发戳ConcurrencyStamp,但EntityDto中并未提供该字段,所以需继承IHasConcurrencyStamp接⼝。
在Demo.ProductManager.Application.Contracts项⽬Products⽂件夹下添加产品管理应⽤服务接⼝IProductAppService如下:
using System;
using Demo.ProductManager.Products.Dto;
using Volo.Abp.Application.Services;
namespace Demo.ProductManager.Products;
///<summary>
///产品管理应⽤服务接⼝
///</summary>
public interface IProductAppService : ICrudAppService<ProductDto, Guid>
{
}
在Demo.ProductManager.Application项⽬中添加Products⽂件夹,添加应⽤服务类ProductAppService如下:
using System;
using Demo.ProductManager.Products.Dto;
using Volo.Abp.Application.Services;
using Volo.Abp.Domain.Repositories;
namespace Demo.ProductManager.Products;
///<summary>
///产品管理应⽤服务
///</summary>
public class ProductAppService:CrudAppService<Product,ProductDto,Guid>,IProductAppService
{
public ProductAppService(IRepository<Product, Guid> repository) : base(repository)
{
}
}
为⽅便多个领域下AutoMapper映射关系的管理,我在每个领域单独创建⼀个静态类,以扩展⽅法的⽅式编写当前领域的对象映射关系。例如在当前Products领域中,在Demo.ProductManager.Application项⽬中Products⽂件夹下添加静态类ProductAutoMapperProfile如下:
using Demo.ProductManager.Products.Dto;
namespace Demo.ProductManager.Products;
public static class ProductAutoMapperProfile
{
public static void CreatProductMapper(this ProductManagerApplicationAutoMapperProfile profile)
{
profile.CreateMap<Product, ProductDto>();
profile.CreateMap<ProductDto, Product>();
}
}
之后,就可以在ProductManagerApplicationAutoMapperProfile类的ProductManagerApplicationAutoMapperProfile⽅法中增加以下代码:
this.CreatProductMapper();
通常情况,DTO和实体的字段并⾮完全⼀⼀对应,我们需要再映射过程中忽略映射关系的校验,具体⽅法为将ProductManagerApplicationModule类中ConfigureServices⽅法下 Configure<AbpAutoMapperOptions>(options => { options.AddMaps<ProductManagerApplicationModule>(validate: true); }); 这⼀句validate参数值改为falsemysql下载app
4.4
ABP vNext框架Module模式模板默认未开启动态WebAPI,需要我们⼿动启⽤动态WebAPI,具体⽅式
为在Demo.ProductManager.HttpApi.Host项⽬的ProductManagerHttpApiHostModule类ConfigureServices⽅法中添加以下代码:
Configure<AbpAspNetCoreMvcOptions>(options =>
{
options
.ConventionalControllers
.Create(typeof(ProductManagerApplicationModule).Assembly);
});
通常情况,我们使⽤的仓储为ABP vNext框架提供的默认仓储实现,我们需要⼀次性添加所有默认仓储,具体⽅法为在
Demo.ProductManager.EntityFrameworkCore项⽬中ProductManagerEntityFrameworkCoreModule类的ConfigureServices⽅法中,
到 context.Services.AddAbpDbContext<ProductManagerDbContext>(…… ,在其中添加options.AddDefaultRepositories();修改为:
context.Services.AddAbpDbContext<ProductManagerDbContext>(options =>
{
/* Add custom repositories here. Example:
* options.AddRepository<Question, EfCoreQuestionRepository>();
*/
options.AddDefaultRepositories();
});
完成以上修改后,运⾏Demo.ProductManager.HttpApi.Host项⽬并打开localhost:5010/swagger/index.html,可显⽰Swagger页⾯并包含,
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论