diff --git a/apihost/Tnb.API.Entry/Configurations/AppSetting.json b/apihost/Tnb.API.Entry/Configurations/AppSetting.json index ab57c449..da71e465 100644 --- a/apihost/Tnb.API.Entry/Configurations/AppSetting.json +++ b/apihost/Tnb.API.Entry/Configurations/AppSetting.json @@ -1,7 +1,7 @@ { "AppSettings": { "InjectMiniProfiler": true, - "SupportPackageNamePrefixs": ["Tnb"] + "SupportPackageNamePrefixs": [ "Tnb" ] }, "Kestrel": { "Endpoints": { @@ -9,5 +9,13 @@ "Url": "http://localhost:9231" } } + }, + "YitId": { + "WorkerId": 1, //必须 全局唯一,必须 程序设定,理论最大值 2^WorkerIdBitLength-1 + "WorkerIdBitLength": 4, //机器码位长,决定 WorkerId 的最大值,默认值6,取值范围 [1, 16] + "SeqBitLength": 4 //序列数位长,默认值6,取值范围 [3, 21](建议不小于4),决定每毫秒基础生成的ID个数 + }, + "UnifyResultSettings": { + "ShowExceptionDetail": true } } \ No newline at end of file diff --git a/apihost/Tnb.API.Entry/Configurations/ConnectionStrings.json b/apihost/Tnb.API.Entry/Configurations/ConnectionStrings.json index 400ed1f7..af10cd10 100644 --- a/apihost/Tnb.API.Entry/Configurations/ConnectionStrings.json +++ b/apihost/Tnb.API.Entry/Configurations/ConnectionStrings.json @@ -1,7 +1,7 @@ { "ConnectionStrings": { "ConfigId": "default", - "DBName": "tnb", + "DBName": "tnb_bas", "DBType": "PostgreSQL", //MySql;SqlServer;Oracle;PostgreSQL;Dm;Kdbndp;Sqlite; "Host": "localhost", "Port": "9202", @@ -17,7 +17,7 @@ //"DefaultConnection": "Data Source=(DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=192.168.0.19)(PORT=1521))(CONNECT_DATA=(SERVER = DEDICATED)(SERVICE_NAME=JNPFCLOUD)));User Id=JNPFCLOUD;Password=JNPFCLOUD" //PostgreSQL //"DefaultConnection": "PORT=5432;DATABASE=java_boot_dev_postgresql;HOST=192.168.0.103;PASSWORD=123456;USER ID=postgres" - "DefaultConnection": "server=localhost;port=9202;database=tnb;uid=totong;pwd=IPANyxGSKxIXg0dBM;pooling=true;" + "DefaultConnection": "server=localhost;port=9202;database=tnb_bas;uid=totong;pwd=IPANyxGSKxIXg0dBM;pooling=true;" //MySql //"DefaultConnection": "server=192.168.0.10;Database=netcore_test;Uid=netcore_test;Pwd=jhpGB3A88CF57fBC;AllowLoadLocalInfile=true" } diff --git a/apihost/Tnb.API.Entry/Extensions/SqlSugarConfigureExtensions.cs b/apihost/Tnb.API.Entry/Extensions/SqlSugarConfigureExtensions.cs index a9bb5ca7..ae206987 100644 --- a/apihost/Tnb.API.Entry/Extensions/SqlSugarConfigureExtensions.cs +++ b/apihost/Tnb.API.Entry/Extensions/SqlSugarConfigureExtensions.cs @@ -1,6 +1,8 @@ using System.ComponentModel.DataAnnotations; using System.Reflection; using JNPF; +using JNPF.Logging; +using Spire.Xls; using SqlSugar; namespace Microsoft.Extensions.DependencyInjection; @@ -39,33 +41,33 @@ public static class SqlSugarConfigureExtensions services.AddSqlSugar(connectConfigList, client => { - //connectConfigList.ForEach(config => - //{ - // var db = ((SqlSugarScope)client).GetConnectionScope((string)config.ConfigId); + //connectConfigList.ForEach(config => + //{ + // var db = ((SqlSugarScope)client).GetConnectionScope((string)config.ConfigId); - // // 设置超时时间 - // db.Ado.CommandTimeOut = 30; + // // 设置超时时间 + // db.Ado.CommandTimeOut = 30; - // // 打印SQL语句 - // db.Aop.OnLogExecuting = (sql, pars) => - // { - // if (sql.StartsWith("SELECT", StringComparison.OrdinalIgnoreCase)) - // Console.ForegroundColor = ConsoleColor.Green; - // if (sql.StartsWith("UPDATE", StringComparison.OrdinalIgnoreCase) || sql.StartsWith("INSERT", StringComparison.OrdinalIgnoreCase)) - // Console.ForegroundColor = ConsoleColor.White; - // if (sql.StartsWith("DELETE", StringComparison.OrdinalIgnoreCase)) - // Console.ForegroundColor = ConsoleColor.Blue; - // Console.WriteLine("【" + DateTime.Now + "——执行SQL】\r\n" + UtilMethods.GetSqlString(config.DbType, sql, pars) + "\r\n"); - // App.PrintToMiniProfiler("SqlSugar", "Info", sql + "\r\n" + db.Utilities.SerializeObject(pars.ToDictionary(it => it.ParameterName, it => it.Value))); - // }; - // db.Aop.OnError = (ex) => - // { - // Console.ForegroundColor = ConsoleColor.Red; - // var pars = db.Utilities.SerializeObject(((SugarParameter[])ex.Parametres).ToDictionary(it => it.ParameterName, it => it.Value)); - // Console.WriteLine("【" + DateTime.Now + "——错误SQL】\r\n" + UtilMethods.GetSqlString(config.DbType, ex.Sql, (SugarParameter[])ex.Parametres) + "\r\n"); - // App.PrintToMiniProfiler("SqlSugar", "Error", $"{ex.Message}{Environment.NewLine}{ex.Sql}{pars}{Environment.NewLine}"); - // }; - //}); + // // 打印SQL语句 + // db.Aop.OnLogExecuting = (sql, pars) => + // { + // var oldColor = Console.ForegroundColor; + // Console.ForegroundColor = ConsoleColor.Green; + // var finalSql = UtilMethods.GetSqlString(db.CurrentConnectionConfig.DbType, sql, pars); + // Console.WriteLine($"【{DateTime.Now.ToString("HH:mm:ss.fff")}——SQL执行完成】{db.Ado.SqlExecutionTime.TotalMilliseconds} ms"); + // Console.WriteLine(finalSql); + // Console.ForegroundColor = oldColor; + // if (db.Ado.SqlExecutionTime.TotalMilliseconds > 3000) + // { + // Log.Warning($"慢查询: {db.Ado.SqlExecutionTime.TotalMilliseconds}ms, SQL: " + finalSql); + // } + // Console.WriteLine(); + // }; + // db.Aop.OnError = (ex) => + // { + // Log.Error(UtilMethods.GetSqlString(db.CurrentConnectionConfig.DbType, ex.Sql, (SugarParameter[])ex.Parametres)); + // }; + //}); }); return services; diff --git a/apihost/Tnb.API.Entry/Program.cs b/apihost/Tnb.API.Entry/Program.cs index fad3dedc..6b43488e 100644 --- a/apihost/Tnb.API.Entry/Program.cs +++ b/apihost/Tnb.API.Entry/Program.cs @@ -1,3 +1,5 @@ +using JNPF.Common.Security; + Serve.Run(RunOptions.Default .AddWebComponent().WithArgs(args)); diff --git a/apihost/Tnb.API.Entry/Startup.cs b/apihost/Tnb.API.Entry/Startup.cs index 2cb85469..c26a3e50 100644 --- a/apihost/Tnb.API.Entry/Startup.cs +++ b/apihost/Tnb.API.Entry/Startup.cs @@ -24,6 +24,7 @@ using System.Xml; using System; using System.Text; using Top.Api; +using JNPF.Common.Security; namespace JNPF.API.Entry; @@ -207,6 +208,8 @@ public class Startup : AppStartup endpoints.MapControllerRoute(name: "default", pattern: "{controller=Home}/{action=Index}/{id?}"); }); + SnowflakeIdHelper.InitYitIdWorker(); + serviceProvider.GetRequiredService().StartTimerJob(); } @@ -226,7 +229,13 @@ public class Startup : AppStartup } private string LoggerFileFormat(LogMessage msg) { - return $"{LoggerLevelName(msg.LogLevel)} {msg.LogDateTime.ToString(DATEFORMAT)} {msg.ThreadId}# {msg.Message}"; + var txt = $"{LoggerLevelName(msg.LogLevel)} {msg.LogDateTime.ToString(DATEFORMAT)} {msg.ThreadId}# {msg.Message}"; + if (msg.Exception != null) + { + //var EXCEPTION_SEPARATOR_WITHCOLOR = AppendWithColor(default, EXCEPTION_SEPARATOR, logLevelColors).ToString(); + txt += $"{Environment.NewLine}{msg.Exception}"; + } + return txt; } private string LoggerConsoleFormat(LogMessage msg) { @@ -236,7 +245,12 @@ public class Startup : AppStartup 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"; + var txt = $"{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"; + if (msg.Exception != null) + { + //var EXCEPTION_SEPARATOR_WITHCOLOR = AppendWithColor(default, EXCEPTION_SEPARATOR, logLevelColors).ToString(); + txt += $"{Environment.NewLine}{fclr}{msg.Exception}\u001b[49m"; + } + return txt; } - } \ No newline at end of file diff --git a/apihost/Tnb.API.Entry/Tnb.API.Entry.csproj b/apihost/Tnb.API.Entry/Tnb.API.Entry.csproj index e6fa9d11..cc3742b7 100644 --- a/apihost/Tnb.API.Entry/Tnb.API.Entry.csproj +++ b/apihost/Tnb.API.Entry/Tnb.API.Entry.csproj @@ -8,7 +8,7 @@ none - + @@ -42,10 +42,4 @@ - - - - - - \ No newline at end of file diff --git a/apihost/Tnb.API.Entry/_install.bat b/apihost/Tnb.API.Entry/_install.bat new file mode 100644 index 00000000..0c662c05 --- /dev/null +++ b/apihost/Tnb.API.Entry/_install.bat @@ -0,0 +1,25 @@ +@echo off +%1 %2 +ver|find "5.">nul&&goto :Admin +mshta vbscript:createobject("shell.application").shellexecute("%~s0","goto :Admin","","runas",1)(window.close)&goto :eof + +:Admin +cd /d %~dp0 +echo -------------------------------- +echo 1 --- install +echo 2 --- uninstall +echo -------------------------------- +setlocal + set svcName=ToTong.TNB.Master + set binPath=Tnb.API.Entry.exe + set /p mode=input number to choise: + if %mode%==1 ( + sc create %svcName% binpath=%~dp0%binPath% displayname=%svcName% start= auto + sc description %svcName% %svcName% + net start %svcName% + ) else if %mode%==2 ( + net stop %svcName% + sc delete %svcName% + ) +endlocal +pause \ No newline at end of file diff --git a/common/Tnb.Common.Core/Manager/DataBase/DataBaseManager.cs b/common/Tnb.Common.Core/Manager/DataBase/DataBaseManager.cs index de5a7180..6a15b628 100644 --- a/common/Tnb.Common.Core/Manager/DataBase/DataBaseManager.cs +++ b/common/Tnb.Common.Core/Manager/DataBase/DataBaseManager.cs @@ -28,7 +28,7 @@ public class DataBaseManager : IDataBaseManager, ITransient /// /// 初始化客户端. /// - private static SqlSugarScope? _sqlSugarClient; + private static SqlSugarScope _sqlSugarClient; /// /// 用户管理器. @@ -785,7 +785,7 @@ public class DataBaseManager : IDataBaseManager, ITransient sb.Append(@"select a.relname F_TABLE,a.n_live_tup F_SUM,b.description F_TABLENAME from sys_stat_user_tables a left outer join sys_description b on a.relid = b.objoid where a.schemaname='public' and b.objsubid='0'"); break; case "postgresql": - sb.Append(@"select cast(relname as varchar) as F_TABLE,reltuples as F_SUM, cast(obj_description(relfilenode,'pg_class') as varchar) as F_TABLENAME from pg_class c inner join pg_namespace n on n.oid = c.relnamespace and nspname='public' inner join pg_tables z on z.tablename=c.relname where relkind = 'r' and relname not like 'pg_%' and relname not like 'sql_%' and schemaname='public' order by relname"); + sb.Append(@"select cast(relname as varchar) as F_TABLE, cast(reltuples as varchar) as F_SUM, cast(obj_description(relfilenode,'pg_class') as varchar) as F_TABLENAME from pg_class c inner join pg_namespace n on n.oid = c.relnamespace and nspname='public' inner join pg_tables z on z.tablename=c.relname where relkind = 'r' and relname not like 'pg_%' and relname not like 'sql_%' and schemaname='public' order by relname"); break; default: throw new Exception("不支持"); diff --git a/common/Tnb.Common/Security/SnowflakeIdHelper.cs b/common/Tnb.Common/Security/SnowflakeIdHelper.cs index 99001e39..211fe01d 100644 --- a/common/Tnb.Common/Security/SnowflakeIdHelper.cs +++ b/common/Tnb.Common/Security/SnowflakeIdHelper.cs @@ -1,5 +1,7 @@ using System.Runtime.InteropServices; using JNPF.Common.Cache; +using JNPF.Common.Const; +using JNPF.FriendlyException; using Yitter.IdGenerator; namespace JNPF.Common.Security; @@ -9,59 +11,56 @@ namespace JNPF.Common.Security; /// public class SnowflakeIdHelper { - // 定义dll路径 - public const string RegWorkerId_DLL_NAME = "lib\\regworkerid_lib_v1.3.1\\yitidgengo.dll"; + // 定义dll路径 + public const string RegWorkerId_DLL_NAME = "lib\\regworkerid_lib_v1.3.1\\yitidgengo.dll"; - // 根据文档定义三个接口 + // 根据文档定义三个接口 - // 注册一个 WorkerId,会先注销所有本机已注册的记录 - // ip: redis 服务器地址 - // port: redis 端口 - // password: redis 访问密码,可为空字符串“” - // maxWorkerId: 最大 WorkerId - [DllImport(RegWorkerId_DLL_NAME, EntryPoint = "RegisterOne", CallingConvention = CallingConvention.Cdecl, ExactSpelling = false)] - private static extern ushort RegisterOne(string ip, int port, string password, int maxWorkerId); + // 注册一个 WorkerId,会先注销所有本机已注册的记录 + // ip: redis 服务器地址 + // port: redis 端口 + // password: redis 访问密码,可为空字符串“” + // maxWorkerId: 最大 WorkerId + [DllImport(RegWorkerId_DLL_NAME, EntryPoint = "RegisterOne", CallingConvention = CallingConvention.Cdecl, ExactSpelling = false)] + private static extern ushort RegisterOne(string ip, int port, string password, int maxWorkerId); - // 注销本机已注册的 WorkerId - [DllImport(RegWorkerId_DLL_NAME, EntryPoint = "UnRegister", CallingConvention = CallingConvention.Cdecl, ExactSpelling = false)] - private static extern void UnRegister(); + // 注销本机已注册的 WorkerId + [DllImport(RegWorkerId_DLL_NAME, EntryPoint = "UnRegister", CallingConvention = CallingConvention.Cdecl, ExactSpelling = false)] + private static extern void UnRegister(); - // 检查本地WorkerId是否有效(0-有效,其它-无效) - [DllImport(RegWorkerId_DLL_NAME, EntryPoint = "Validate", CallingConvention = CallingConvention.Cdecl, ExactSpelling = false)] - private static extern int Validate(int workerId); + // 检查本地WorkerId是否有效(0-有效,其它-无效) + [DllImport(RegWorkerId_DLL_NAME, EntryPoint = "Validate", CallingConvention = CallingConvention.Cdecl, ExactSpelling = false)] + private static extern int Validate(int workerId); - /// - /// 缓存配置. - /// - private static CacheOptions _cacheOptions = App.GetConfig("Cache", true); - - /// - /// 生成ID. - /// - /// - public static string NextId() + /// + /// 初始化YitId配置 + /// + public static void InitYitIdWorker() + { + //var option = new IdGeneratorOptions + //{ + // WorkerId = 1, //必须 全局唯一,必须 程序设定,理论最大值 2^WorkerIdBitLength-1 + // //BaseTime = new DateTime(2023, 1, 1, 0, 0, 0, DateTimeKind.Utc), //用生成ID时的系统时间与基础时间的差值(毫秒数)作为生成ID的时间戳 + // WorkerIdBitLength = 16, //机器码位长,决定 WorkerId 的最大值,默认值6,取值范围 [1, 16] + // //SeqBitLength = 4, //序列数位长,默认值6,取值范围 [3, 21](建议不小于4),决定每毫秒基础生成的ID个数 + // //MinSeqNumber = 5, //最小序列数,默认值5,取值范围 [5, MaxSeqNumber] + // //MaxSeqNumber 最大序列数,设置范围 [MinSeqNumber, 2^SeqBitLength-1],默认值0 + //}; + var option = App.GetConfig("YitId"); + if (option.WorkerId == 0) { - // 这个if判断在高并发的情况下可能会有问题 - if (YitIdHelper.IdGenInstance == null) - { - UnRegister(); - - // 如果不用自动注册WorkerId的话,直接传一个数值就可以了 - var workerId = RegisterOne(_cacheOptions.ip, _cacheOptions.port, _cacheOptions.password, 63); - - // 创建 IdGeneratorOptions 对象,可在构造函数中输入 WorkerId: - var options = new IdGeneratorOptions(workerId); - options.WorkerIdBitLength = 16; // 默认值6,限定 WorkerId 最大值为2^6-1,即默认最多支持64个节点。 - options.SeqBitLength = 6; // 默认值6,限制每毫秒生成的ID个数。若生成速度超过5万个/秒,建议加大 SeqBitLength 到 10。 - // options.BaseTime = Your_Base_Time; // 如果要兼容老系统的雪花算法,此处应设置为老系统的BaseTime。 - // ...... 其它参数参考 IdGeneratorOptions 定义。 - - // 保存参数(务必调用,否则参数设置不生效): - YitIdHelper.SetIdGenerator(options); - - // 以上过程只需全局一次,且应在生成ID之前完成。 - } - - return YitIdHelper.NextId().ToString(); + CacheOptions _cacheOptions = App.GetConfig("Cache", true); + option.WorkerId = RegisterOne(_cacheOptions.ip, _cacheOptions.port, _cacheOptions.password, 63); } + YitIdHelper.SetIdGenerator(option); + } + + /// + /// 生成ID. + /// + /// + public static string NextId() + { + return YitIdHelper.NextId().ToString(); + } } \ No newline at end of file diff --git a/common/Tnb.Common/Tnb.Common.csproj b/common/Tnb.Common/Tnb.Common.csproj index 3fe41aff..c37766cd 100644 --- a/common/Tnb.Common/Tnb.Common.csproj +++ b/common/Tnb.Common/Tnb.Common.csproj @@ -17,12 +17,16 @@ - + + + + +