.NET Core 园区服务框架
- [TOC]
环境依赖
.NET Core 3.1
特性
ELink 身份认证 :
- 通过登陆接口获取身份 JwtToken,在请求头内 添加值 Key:Authorization Value:Bearer JwtToken
程序内 HttpContext.User.Identity.IsAuthenticated 状态为True
推荐使用 服务端 无状态 各个服务Token通用
- 通过登陆接口获取身份 JwtToken,在Cookie内 添加值 Key:token Value:JWTToken
HttpContext.User.Identity.IsAuthenticated 状态为False
服务端 无状态 各个服务Token通用
不推荐,做了多余解析消耗性能, 仅为了 钉钉微信登陆跳转而支持
- 通过登陆接口获取工号,在Cookie内 添加值 Key:euid Value:工号
该方式年后废弃 不在支持
环境配置
- database.json 内配置数据库连接 2021-02-04 已统一至 appsettings.json内
- appsettings.json 内 Startup 节点 配置程序端口
- APIConfig.json 内配置插件参数, 详细参考各个插件自身说明
介绍
在主程序中启用
通过IHostBuilder的UsePluginFactory方法启用插件库
var builder = Host.CreateDefaultBuilder(args);
builder.UsePluginFactory();
使用程序运行目录下的plugins目录作为插件程序集目录, 使用appsettings.json配置文件作为插件配置文件注意 直接生成dll到宿主插件目录 ,在宿主自动重载插件时目录可能会出现dll引用错误, 建议手动覆盖插件的文件到目录内去除不必须的dll
编写支持初始化的插件
插件是实现了IPlugin接口的类,提供了PluginBase基类,一般从此类继承即可。标准插件具有启动和停止方法,通过IPluginFactory进行控制。
要编写插件,一般遵循以下步骤:
- 创建插件项目(.NET Core 类库),如TestPluginA
- 添加
ELink.IPluginFactory.dll - 创建插件类,如Plugin,从PluginBase继承
- 在插件中控制宿主的依赖注入,如注入新的服务等,这时候可通过实现支持初始化的插件(
ISupportInitPlugin)来实现,该接口的Init方法将在依赖注入构建之前调用,通过方法参数IPluginInitContext中的ServiceCollection可以注入容器。
public class Plugin : PluginBase, ISupportInitPlugin
{
public void Init(IPluginInitContext context)
{
// 注入服务
// 宿主 依赖注入构建前执行
//context.ServiceCollection.TryAddScoped<ICustomerService>();
// 宿主会自动注入插件内继承【ControllerBase】的Controller
}
public override Task StartAsync(IPluginContext context)
{
// 插件启动前执行
// 宿主 依赖注入构建后执行
Console.WriteLine("插件A已启动");
return base.StartAsync(context);
}
public override Task StopAsync(IPluginContext context)
{
Console.WriteLine("插件A已停止");
return base.StopAsync(context);
}
}
//Route 注意插件间不要重复
[Route("TestPlugin/[controller]/[action]")]
public class TestController : ControllerBase
{
[HttpGet]
public ActionResult<List<Employee>> Get()
{
var sdf = new BaseService<Employee>();
return sdf.GetWhere(p => 1 == 1);
//return sdf.GetFirst(p => 1 == 1);
}
[SugarTable("t_employee")]
public class Employee
{
[SugarColumn(IsPrimaryKey = true)]
public string employeeid { get; set; }
public string employeename { get; set; }
public string employeeno { get; set; }
}
}
*启动或停止方法中可通过context中的ServiceProvider获取注入服务*
- 通过
PluginAttribute特性设置插件的元数据[Plugin(Alias = "PluginA", Description = "测试插件")]
public class Plugin : PluginBase
{
}
*载入的插件列表信息可以通过`PluginFactory.PluginInfoList`获取*
插件启动
IPluginFactory 本身实现了 .NET Core扩展库的IHostedService机制,插件的启动及停止将自动跟随宿主进行
使用插件配置
建议还是自定义一个配置文件来读取
插件支持 .NET Core 扩展库中的Options及Configuration机制,只需要从SupportConfigPluginBase<TOptions>类继承实现插件即可,其中TOptions泛型为插件的配置类型。插件配置自动从宿主配置或启用插件工厂时传入的配置中获取,插件配置位于配置下的plugins节点,该节点下以插件类名称或插件别名(通过PluginAttribute特性指定)作为键名,此键之下为插件的配置,如以下配置文件:
{
"Plugins": {
"PluginA": {
"TestConfig": "Hello World"
},
}
}扩展PluginA实现配置:
- 定义配置类,如PluginOptions
public class PluginOptions
{
public string TestConfig { get; set; }
}
- 实现插件
[Plugin(Alias = "PluginA", Description = "测试插件")]
public class Plugin : SupportConfigPluginBase<PluginOptions>, ISupportInitPlugin
{
public Plugin(IOptionsMonitor<PluginOptions> options) : base(options)
{
}
public void Init(IPluginInitContext context)
{
// 注入服务 初始化方法中也可使用注入的配置
//context.ServiceCollection.TryAddScoped<ICustomerService>();
Console.WriteLine($"Init 插件配置:{Options.TestConfig}");
}
public override Task StartAsync(IPluginContext context)
{
Console.WriteLine("插件A已启动");
Console.WriteLine($"StartAsync 插件配置:{Options.TestConfig}");
return base.StartAsync(context);
}
public override Task StopAsync(IPluginContext context)
{
Console.WriteLine("插件A已停止");
return base.StopAsync(context);
}
特性:
接口路由请使用接口项目名/版本/url的形式 如testplugin/v1/user
支持热加载
插件目录只允许出现dll结尾的文件,防止引用时出错, 如和主程序dll重复 默认优先使用插件目录下的dll
采用 SqlSugar ORM 组件 https://github.com/sunkaixuan/SqlSugar
采用 服务 + 接口 的形式封装框架
采用 NLog 日志组件
采用 Swagger 自动生成 WebAPI 说明文档
封装全局 异常 拦截器 (自动记录系统异常日志)
封装全局 请求 拦截器 (自动记录接口请求日志)
appsettings.json 配置 CORS 跨域
database.json 配置 数据库连接
多数据库支持(待实现) SqlSugar 支持
缓存关系数据库查询结果 配合redis 待实现
| # | 模块功能 | 项目文件 | 说明 |
|---|---|---|---|
| 1 | 公共库 | ELink.Common | 存放常用类库 、加密解密单元等 , 类扩展 |
| 2 | 核心库 | ELink.Core ELink.DataAccess | 数据库、缓存相关类 |
| 4 | 服务层 | BLL | Service 、 IServer, Model, Dto 基础服务类 |
| 5 | 业务层 | ELink.Web | WebAPI 主程序 插件宿主 |
| 6 | 插件库 | ELink.PluginFactory ELink.IPluginFactory | 插件实现 分离防止热加载时出现找不到实现 |
Hangfire.HttpJob Josn配置
| # | 字段名称 | 备注 |
|---|---|---|
| 1 | JobName | 你给这个httpjob起的名称【必填项】 |
| 2 | Method | 这个httpjob的请求方式 "get" 或者 "post" 【必填项】 |
| 4 | ContentType | 这个httpjob的请求ContentType 默认"application/json" 【必填项】 |
| 5 | Url | 这个httpjob的请求url 【必填项】 |
| 6 | DelayFromMinutes | 需要延迟执行的分钟,==注意:0 代表立刻执行; -1代表只能手动触发; >=1代表延迟分钟数== 【必填项】 |
| 7 | Data | 这个httpjob在Method=“post”的时候可以指定post的内容,可以是一个对象也可以是一个string或者其他类型 |
| 8 | Timeout | 这个httpjob请求的超时时间(单位是毫秒 例如5000 代表是5秒) |
| 9 | BasicUserName | 这个httpjob请求需要启用basic认证时设置的username |
| 10 | BasicPassword | 这个httpjob请求需要启用basic认证时设置的密码 |
| 11 | EnableRetry | 失败的时候(比如超时 远程服务器请求错误等)是否启用重试 默认false |
| 12 | RetryTimes | 错误尝试次数自定义,EnableRetry=true的时候启用 |
| 13 | RetryDelaysInSeconds | 失败重试区间,半角逗号隔开,EnableRetry=true的时候启用 |
| 14 | SendSuccess | 这个httpjob请求无异常的时候是否发送通知 默认false |
| 15 | SendFail | 这个httpjob请求异常的时候是否发送通知 默认true |
| 16 | DingTalk.Token | 设置钉钉机器人的群Token 没有这个不会发送的 |
| 17 | DingTalk.AtPhones | 设置钉钉机器人发送消息的时候要不要@人,多个用半角逗号隔开 |
| 18 | DingTalk.IsAtAll | 设置钉钉机器人发送消息的时候要不要@所有的人,默认false |
评论