242 lines
7.6 KiB
C#
242 lines
7.6 KiB
C#
using JNPF.API.Entry.Handlers;
|
||
using JNPF.Common.Cache;
|
||
using JNPF.Common.Core.Filter;
|
||
using JNPF.DatabaseAccessor;
|
||
using JNPF.EventHandler;
|
||
using JNPF.JsonSerialization;
|
||
using JNPF.Message.Handlers;
|
||
using JNPF.TaskScheduler.Interfaces.TaskScheduler;
|
||
using JNPF.UnifyResult;
|
||
using Microsoft.AspNetCore.HttpOverrides;
|
||
using Microsoft.Extensions.Options;
|
||
using Newtonsoft.Json.Serialization;
|
||
using Newtonsoft.Json;
|
||
using Senparc.CO2NET.RegisterServices;
|
||
using Senparc.CO2NET;
|
||
using Senparc.Weixin;
|
||
using Senparc.Weixin.Entities;
|
||
using Senparc.Weixin.RegisterServices;
|
||
using SqlSugar;
|
||
using IGeekFan.AspNetCore.Knife4jUI;
|
||
using JNPF.SpecificationDocument;
|
||
using JNPF.Logging;
|
||
using System.Xml;
|
||
using System;
|
||
using System.Text;
|
||
using Top.Api;
|
||
|
||
namespace JNPF.API.Entry;
|
||
|
||
public class Startup : AppStartup
|
||
{
|
||
public void ConfigureServices(IServiceCollection services)
|
||
{
|
||
services.AddConsoleFormatter(option =>
|
||
{
|
||
option.MessageFormat = LoggerConsoleFormat;
|
||
});
|
||
|
||
// SqlSugar
|
||
services.SqlSugarConfigure();
|
||
|
||
// Jwt处理程序
|
||
services.AddJwt<JwtHandler>(enableGlobalAuthorize: true);
|
||
|
||
// 跨域
|
||
services.AddCorsAccessor();
|
||
|
||
// 注册EventBus服务
|
||
services.AddEventBus(options =>
|
||
{
|
||
//// 创建连接工厂
|
||
//var factory = new RabbitMQ.Client.ConnectionFactory
|
||
//{
|
||
// // 设置主机名
|
||
// HostName = "192.168.0.232",
|
||
|
||
// // 用户名
|
||
// UserName = "jnpf",
|
||
|
||
// // 密码
|
||
// Password = "jnpf@2019",
|
||
//};
|
||
|
||
//// 创建默认内存通道事件源对象,可自定义队列路由key,比如这里是 eventbus
|
||
//var rbmqEventSourceStorer = new RabbitMQEventSourceStorer(factory, "eventbus", 3000);
|
||
|
||
//// 替换默认事件总线存储器
|
||
//options.ReplaceStorer(serviceProvider =>
|
||
//{
|
||
// return rbmqEventSourceStorer;
|
||
//});
|
||
|
||
options.UseUtcTimestamp = false;
|
||
|
||
// 不启用事件日志
|
||
options.LogEnabled = false;
|
||
|
||
// 事件执行器(失败重试)
|
||
options.AddExecutor<RetryEventHandlerExecutor>();
|
||
});
|
||
|
||
// 注册远程请求
|
||
services.AddRemoteRequest();
|
||
|
||
services.AddConfigurableOptions<CacheOptions>();
|
||
services.AddConfigurableOptions<ConnectionStringsOptions>();
|
||
services.AddConfigurableOptions<TenantOptions>();
|
||
|
||
services.AddControllers()
|
||
.AddMvcFilter<RequestActionFilter>()
|
||
.AddInjectWithUnifyResult<RESTfulResultProvider>()
|
||
.AddJsonOptions(options => options.JsonSerializerOptions.PropertyNamingPolicy = null)
|
||
.AddNewtonsoftJson(options =>
|
||
{
|
||
// 默认命名规则
|
||
options.SerializerSettings.ContractResolver = new DefaultContractResolver();
|
||
|
||
// 设置时区为 UTC
|
||
options.SerializerSettings.DateTimeZoneHandling = DateTimeZoneHandling.Utc;
|
||
|
||
// 格式化json输出的日期格式
|
||
options.SerializerSettings.DateFormatString = "yyyy-MM-dd HH:mm:ss";
|
||
|
||
// 忽略空值
|
||
// options.SerializerSettings.NullValueHandling = NullValueHandling.Ignore;
|
||
|
||
// 忽略循环引用
|
||
options.SerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;
|
||
|
||
// 格式化json输出的日期格式为时间戳
|
||
options.SerializerSettings.Converters.Add(new NewtonsoftDateTimeJsonConverter());
|
||
});
|
||
|
||
// 配置Nginx转发获取客户端真实IP
|
||
// 注1:如果负载均衡不是在本机通过 Loopback 地址转发请求的,一定要加上options.KnownNetworks.Clear()和options.KnownProxies.Clear()
|
||
// 注2:如果设置环境变量 ASPNETCORE_FORWARDEDHEADERS_ENABLED 为 True,则不需要下面的配置代码
|
||
services.Configure<ForwardedHeadersOptions>(options =>
|
||
{
|
||
options.ForwardedHeaders = ForwardedHeaders.All;
|
||
options.KnownNetworks.Clear();
|
||
options.KnownProxies.Clear();
|
||
});
|
||
|
||
// 视图引擎
|
||
services.AddViewEngine();
|
||
|
||
// 任务调度
|
||
services.AddTaskScheduler();
|
||
|
||
// 脱敏词汇检测
|
||
services.AddSensitiveDetection();
|
||
|
||
// WebSocket服务
|
||
services.AddWebSocketManager();
|
||
|
||
// 微信
|
||
services.AddSenparcGlobalServices(App.Configuration) // Senparc.CO2NET 全局注册
|
||
.AddSenparcWeixinServices(App.Configuration); // Senparc.Weixin 注册(如果使用Senparc.Weixin SDK则添加)
|
||
services.AddSession();
|
||
services.AddMemoryCache(); // 使用本地缓存必须添加
|
||
|
||
// 日志监听
|
||
// services.AddMonitorLogging(options =>
|
||
//{
|
||
// options.IgnorePropertyNames = new[] { "Byte" };
|
||
// options.IgnorePropertyTypes = new[] { typeof(byte[]) };
|
||
//});
|
||
|
||
services.AddFileLogging(options =>
|
||
{
|
||
options.MessageFormat = LoggerFileFormat;
|
||
options.FileNameRule = fileName => string.Format(fileName, DateTime.Now); // 每天创建一个文件
|
||
options.HandleWriteError = (writeError) => // 写入失败时启用备用文件
|
||
{
|
||
writeError.UseRollbackFileName(Path.GetFileNameWithoutExtension(writeError.CurrentFileName) + "-oops" + Path.GetExtension(writeError.CurrentFileName));
|
||
};
|
||
});
|
||
|
||
services.AddUnitOfWork<SqlSugarUnitOfWork>();
|
||
|
||
services.OSSServiceConfigure();
|
||
|
||
services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
|
||
|
||
services.AddSchedule();
|
||
}
|
||
|
||
public void Configure(IApplicationBuilder app, IWebHostEnvironment env, IServiceProvider serviceProvider, IOptions<SenparcSetting> senparcSetting, IOptions<SenparcWeixinSetting> senparcWeixinSetting)
|
||
{
|
||
// 添加状态码拦截中间件
|
||
app.UseUnifyResultStatusCodes();
|
||
|
||
// app.UseHttpsRedirection(); // 强制https
|
||
app.UseStaticFiles();
|
||
|
||
#region 微信
|
||
|
||
IRegisterService register = RegisterService.Start(senparcSetting.Value).UseSenparcGlobal();//启动 CO2NET 全局注册,必须!
|
||
register.UseSenparcWeixin(senparcWeixinSetting.Value, senparcSetting.Value);//微信全局注册,必须!
|
||
|
||
#endregion
|
||
|
||
app.UseWebSockets();
|
||
|
||
app.UseRouting();
|
||
|
||
app.UseCorsAccessor();
|
||
|
||
app.UseAuthentication();
|
||
app.UseAuthorization();
|
||
|
||
app.UseKnife4UI(options =>
|
||
{
|
||
options.RoutePrefix = "newapi"; // 配置 Knife4UI 路由地址,现在是 /newapi
|
||
foreach (var groupInfo in SpecificationDocumentBuilder.GetOpenApiGroups())
|
||
{
|
||
options.SwaggerEndpoint("/" + groupInfo.RouteTemplate, groupInfo.Title);
|
||
}
|
||
});
|
||
|
||
app.UseInject(string.Empty);
|
||
|
||
app.MapWebSocketManager("/api/message/websocket", serviceProvider.GetService<IMHandler>());
|
||
|
||
app.UseEndpoints(endpoints =>
|
||
{
|
||
endpoints.MapControllerRoute(name: "default", pattern: "{controller=Home}/{action=Index}/{id?}");
|
||
});
|
||
|
||
serviceProvider.GetRequiredService<ITimeTaskService>().StartTimerJob();
|
||
}
|
||
|
||
const string DATEFORMAT = "HH:mm:ss.fff";
|
||
private string LoggerLevelName(LogLevel level)
|
||
{
|
||
return level switch
|
||
{
|
||
LogLevel.Trace => "Trace",
|
||
LogLevel.Debug => "Debug",
|
||
LogLevel.Information => "Info",
|
||
LogLevel.Warning => "Warn",
|
||
LogLevel.Error => "Error",
|
||
LogLevel.Critical => "Crit",
|
||
_ => "None"
|
||
};
|
||
}
|
||
private string LoggerFileFormat(LogMessage msg)
|
||
{
|
||
return $"{LoggerLevelName(msg.LogLevel)} {msg.LogDateTime.ToString(DATEFORMAT)} {msg.ThreadId}# {msg.Message}";
|
||
}
|
||
private string LoggerConsoleFormat(LogMessage msg)
|
||
{
|
||
var fclr = msg.LogLevel switch
|
||
{
|
||
LogLevel.Warning => "\u001b[1m\u001b[33m",
|
||
LogLevel.Error => "\u001b[1m\u001b[31m",
|
||
_ => "\u001b[39m\u001b[22m"
|
||
};
|
||
return $"{fclr}{LoggerLevelName(msg.LogLevel)}\u001b[49m \u001b[36m{msg.LogDateTime.ToString(DATEFORMAT)}\u001b[49m \u001b[39m\u001b[22m{msg.ThreadId}#\u001b[49m {fclr}{msg.Message}\u001b[49m";
|
||
}
|
||
|
||
} |