我们知道通过abp cli命令可以快速的搭建一个最基本的abp项目环境,但我们项目中一般都需要使用自己的UI、数据库和基础配置,如果每次都用官方默认模板创建项目,那就需要每次都重复前两章的过程来搭建基础代码框架,这显然太浪费时间了;
这章我们将介绍如何打造自己的abp框架代码模板。
首先,到github上下载abp源码,https://github.com/abpframework/abp/releases,文中使用的v5.0.0-rc.1版本;解压后复制templates目录到磁盘任意位置
这里我们只修改app项目的模板,打开app/aspnet-core目录下的MyCompanyName.MyProjectName.sln解决方案文件,之前我们项目都是angular前端,mysql数据库,apiHost集成IdentityServer的,只需要要修改以下的项目即可:
为了将模板从abp源码中独立出来发布,首先将项目文件中所有的abp项目引用替换为包引用,比如MyCompanyName.Application项目:
然后按照第一章的方法修改MyCompanyName.MyProjectName.EntityFrameworkCore项目,使其支持MySql数据库;
另外在此基础上,我们可以添加点别的基础功能,或者删除点没用的东西
1、删除掉多余的多语言资源
定位到MyCompanyName.MyProjectName.Domain.Shared项目的Localization/MyProjectName目录,删除多余的多语言资源,只保留自己常用,这里我们只保留中文和英文
继续定位到MyCompanyName.MyProjectName.HttpApi.HostWithIds项目的MyProjectNameHttpApiHostModule文件,移除多余的语言定义
2、配置审计日志参数
打开MyCompanyName.MyProjectName.HttpApi.HostWithIds项目的MyProjectNameHttpApiHostModule文件,在ConfigureServices方法中添加如下内容
public override void ConfigureServices(ServiceConfigurationContext context)
{
var configuration = context.Services.GetConfiguration();
var hostingEnvironment = context.Services.GetHostingEnvironment();
Configure<AbpAuditingOptions>(options =>
{
options.IsEnabled = true;
options.IsEnabledForAnonymousUsers = false; // 不记录匿名用户的日志
options.IsEnabledForGetRequests = false; // 不记录Get请求用户的日志
});
...
...
}
此处根据自身情况设置吧,按默认选项在实际生产环境中可能会产生大量日志,我在之前项目中1个月产生10多万条,按上面配置就好多了
3、添加文件上传下载支持
为配合后面章节的内容,将文件处理相关的配置做到模板里,后面生成代码就直接支持文件处理了
还是在打开MyCompanyName.MyProjectName.HttpApi.HostWithIds项目的MyProjectNameHttpApiHostModule文件中,修改ConfigureConventionalControllers方法如下
private void ConfigureConventionalControllers()
{
Configure<AbpAspNetCoreMvcOptions>(options =>
{
options.ConventionalControllers.Create(typeof(MyProjectNameApplicationModule).Assembly);
options.ConventionalControllers.FormBodyBindingIgnoredTypes.Add(typeof(RemoteStreamContent));
});
}
修改ConfigureSwaggerServices方法的代码如下
options =>
{
options.SwaggerDoc("v1", new OpenApiInfo {Title = "FixtrueControl API", Version = "v1"});
options.DocInclusionPredicate((docName, description) => true);
options.CustomSchemaIds(type => type.FullName);
options.MapType<FileContentResult>(() => new OpenApiSchema { Type = "string", Format = "binary" });
});
修改ConfigureCors方法中添的代码如下:
options.AddPolicy(DefaultCorsPolicyName, builder =>
{
builder
.WithOrigins(
configuration["App:CorsOrigins"]
.Split(",", StringSplitOptions.RemoveEmptyEntries)
.Select(o => o.RemovePostFix("/"))
.ToArray()
)
.WithAbpExposedHeaders()
.WithExposedHeaders("Content-Disposition") // file-download
.SetIsOriginAllowedToAllowWildcardSubdomains()
.AllowAnyHeader()
.AllowAnyMethod()
.AllowCredentials();
});
4、修改Serilog日志记录参数
打开MyCompanyName.MyProjectName.HttpApi.HostWithIds项目的Program.cs文件,将如下内容修改如下:
// 始终打印控制台日志
.WriteTo.Async(c => c.Console())
#if RELEASE
// 尽在发布版本中包含文件日志
.WriteTo.Async(c => c.File("logs/logs.txt", rollingInterval: RollingInterval.Day))
#endif
.Crea
这么修改是因为按照原来方式,我将程序部署到docker中时,无法查看控制台日志,另外我在debug模式时只要看控制台日志就行了,不要写文件日志
5、继承的多语言资源问题
打开MyCompanyName.MyProjectName.HttpApi的MyProjectNameHttpApiModule文件,定位到AddBaseTypes处,此处应该是可以不要的,因为在angular中可以通过资源前缀定位到任意其他模块的多语言资源的,添加AddBaseTypes会在appConfiguration配置中附带BaseType中所有的资源项,我们通过api/abp/application-configuration接口访问查看结果就可以发现每个abp自带的业务模块都包含同样的AbpUiResource多语言资源项目,如果我们自己的所有模块再都加上这些资源,这个接口返回的json内容就会增大不少;个人建议最多只在主项目中继承AbpUiResource,这样前端可以不用附带资源前缀就可以访问多语言资源;在自建的模块中全部不要继承AbpUiResource
6、前端api访问代理类生成配置
这个配置在自定义模块是要用到的,因为我们通常不会将所有功能都在一个模块中完成,分模块后前端代理类的生成也需要分模块,这个在后面章节会详细介绍
在MyCompanyName.MyProjectName.Application.Contracts项目中添加MyProjectNameRemoteServiceConsts.cs类,填充文件内容如下:
namespace MyCompanyName.MyProjectName
{
public class MyProjectNameRemoteServiceConsts
{
public const string RemoteServiceName = "MyProjectName";
public const string AreaName = "my-project-name";
}
}
7、在数据库迁移时添加默认的角色
在MyCompanyName.MyProjectName.Domain项目中添加目录Identity,在改目录下添加DefaultRolesDataSeedContributor.cs文件,文件内容如下:
using Microsoft.AspNetCore.Identity;
using System.Threading.Tasks;
using Volo.Abp.Data;
using Volo.Abp.DependencyInjection;
using Volo.Abp.Guids;
using Volo.Abp.Identity;
using Volo.Abp.MultiTenancy;
namespace MyCompanyName.MyProjectName.Identity
{
public class DefaultRolesDataSeedContributor : IDataSeedContributor, ITransientDependency
{
protected IGuidGenerator GuidGenerator { get; }
protected IdentityRoleManager RoleManager { get; }
protected ICurrentTenant CurrentTenant { get; }
protected ILookupNormalizer LookupNormalizer { get; }
protected IIdentityRoleRepository RoleRepository { get; }
public DefaultRolesDataSeedContributor(IGuidGenerator guidGenerator, ILookupNormalizer lookupNormalizer,
IdentityRoleManager roleManager, ICurrentTenant currentTenant, IIdentityRoleRepository roleRepository)
{
LookupNormalizer = lookupNormalizer;
GuidGenerator = guidGenerator;
CurrentTenant = currentTenant;
RoleManager = roleManager;
RoleRepository = roleRepository;
}
public async Task SeedAsync(DataSeedContext context)
{
var tenantId = context?.TenantId;
using (CurrentTenant.Change(tenantId))
{
// 添加一个ordinary角色
const string ordinaryRoleName = "ordinary";
var ordinaryRole =
await RoleRepository.FindByNormalizedNameAsync(LookupNormalizer.NormalizeName(ordinaryRoleName));
if (ordinaryRole == null)
{
ordinaryRole = new Volo.Abp.Identity.IdentityRole(
GuidGenerator.Create(),
ordinaryRoleName,
tenantId
)
{
IsStatic = true,
IsPublic = true,
IsDefault = true // 将角色设置为默认角色,创建用户时会自动赋予该角色
};
(await RoleManager.CreateAsync(ordinaryRole)).CheckErrors();
}
}
}
}
}
abp在数据迁移时会检测到所有IDataSeedContributor,因此会执行DefaultRolesDataSeedContributor 中的SeedAsync方法,插入默认角色,这样在用户自行注册或者管理员添加用户时就默认拥有ordinary的权限了
8、angular前端修改
这里按照上一节coreui的方案进行修改,就不赘述了
9、使用模板生成项目
进入到F:\BlogSamples\templates\app目录(个人模板存放位置),选中angular和aspnet-core目录,将这两个目录打包到app-5.0.0-rc.1.zip中
在任意目录打开控制台程序,执行abp cli 命令如下:
abp new MyGroup.TestProject -u angular --mobile none -d ef -csf -cs "server=192.168.100.175;port=3306;database=abp_test2;uid=test;pwd=Test123$;SslMode=none" -ts "F:\BlogSamples\templates\app" -v 5.0.0-rc.1
代码生成成功后,用vs2022打开aspnet-core解决方案,先运行MyGroup.TestProject.DbMigrator项目执行数据迁移,然后编译运行Api.Host项目,用vscode打开angular目录,执行npm install 和npm start ,浏览器打开http://localhost:4200/后,熟悉的界面又回来了,同时我们也发现默认角色已经加进来了
也可以将app-5.0.0-rc.1.zip文件上传到个人网站中,在命令中只需将本地磁盘地址替换为网络地址即可