From 9133eae4e0dd307d7d87e1900d3acd4af10d5ebc Mon Sep 17 00:00:00 2001
From: HuiJiOnGit <40553940+HuiJiOnGit@users.noreply.github.com>
Date: Thu, 21 Jan 2021 17:18:10 +0800
Subject: [PATCH 001/456] Update .gitignore
Add.vscode ignores folders
---
.gitignore | 3 +++
1 file changed, 3 insertions(+)
diff --git a/.gitignore b/.gitignore
index 9a7ee7a9..5ac1fe08 100644
--- a/.gitignore
+++ b/.gitignore
@@ -35,6 +35,9 @@ bld/
# Visual Studio 2017 auto generated files
Generated\ Files/
+# Visual Studio Code
+.vscode
+
# MSTest test Results
[Tt]est[Rr]esult*/
[Bb]uild[Ll]og.*
From 21e9b002640267321a0d83acb5cd9d03d670e277 Mon Sep 17 00:00:00 2001
From: hudingwen <765472804@qq.com>
Date: Fri, 19 Mar 2021 08:37:48 +0800
Subject: [PATCH 002/456] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E4=B8=80=E4=B8=AA?=
=?UTF-8?q?=E8=8E=B7=E5=8F=96Quartz=E4=BB=BB=E5=8A=A1=E7=9A=84=E5=91=BD?=
=?UTF-8?q?=E5=90=8D=E7=A9=BA=E9=97=B4=E6=8E=A5=E5=8F=A3?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
Blog.Core.Api/Blog.Core.Model.xml | 20 +++++++++++++++
Blog.Core.Api/Blog.Core.xml | 6 +++++
.../Controllers/TasksQzController.cs | 22 ++++++++++++++++
.../wwwroot/BlogCore.Data.json/Modules.tsv | 22 ++++++++++++++++
.../wwwroot/BlogCore.Data.json/Permission.tsv | 25 +++++++++++++++++--
.../ViewModels/QuartzReflectionViewModel.cs | 21 ++++++++++++++++
6 files changed, 114 insertions(+), 2 deletions(-)
create mode 100644 Blog.Core.Model/ViewModels/QuartzReflectionViewModel.cs
diff --git a/Blog.Core.Api/Blog.Core.Model.xml b/Blog.Core.Api/Blog.Core.Model.xml
index a8bf111f..442aff26 100644
--- a/Blog.Core.Api/Blog.Core.Model.xml
+++ b/Blog.Core.Api/Blog.Core.Model.xml
@@ -1818,6 +1818,26 @@
错误信息
+
+
+ 实现IJob的类
+
+
+
+
+ 命名空间
+
+
+
+
+ 类名
+
+
+
+
+ 备注
+
+
服务器VM
diff --git a/Blog.Core.Api/Blog.Core.xml b/Blog.Core.Api/Blog.Core.xml
index 5ba1282f..648902ef 100644
--- a/Blog.Core.Api/Blog.Core.xml
+++ b/Blog.Core.Api/Blog.Core.xml
@@ -513,6 +513,12 @@
+
+
+ 获取任务命名空间
+
+
+
类别管理【无权限】
diff --git a/Blog.Core.Api/Controllers/TasksQzController.cs b/Blog.Core.Api/Controllers/TasksQzController.cs
index 39fa44fa..04d63d08 100644
--- a/Blog.Core.Api/Controllers/TasksQzController.cs
+++ b/Blog.Core.Api/Controllers/TasksQzController.cs
@@ -1,13 +1,18 @@
using System;
+using System.Collections.Generic;
+using System.Linq;
using System.Linq.Expressions;
+using System.Reflection;
using System.Threading.Tasks;
using Blog.Core.IRepository.UnitOfWork;
using Blog.Core.IServices;
using Blog.Core.Model;
using Blog.Core.Model.Models;
+using Blog.Core.Model.ViewModels;
using Blog.Core.Tasks;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
+using Quartz;
namespace Blog.Core.Controllers
{
@@ -479,6 +484,23 @@ public async Task> ReCovery(int jobId)
return data;
}
+ ///
+ /// 获取任务命名空间
+ ///
+ ///
+ [HttpGet]
+ public MessageModel> GetTaskNameSpace()
+ {
+ var baseType = typeof(IJob);
+ var path = AppDomain.CurrentDomain.RelativeSearchPath ?? AppDomain.CurrentDomain.BaseDirectory;
+ var referencedAssemblies = System.IO.Directory.GetFiles(path, "Blog.Core.Tasks.dll").Select(Assembly.LoadFrom).ToArray();
+ var types = referencedAssemblies
+ .SelectMany(a => a.DefinedTypes)
+ .Select(type => type.AsType())
+ .Where(x => x != baseType && baseType.IsAssignableFrom(x)).ToArray();
+ var implementTypes = types.Where(x => x.IsClass).Select(item => new QuartzReflectionViewModel { nameSpace = item.Namespace, nameClass = item.Name, remark = "" }).ToList();
+ return MessageModel>.Success("获取成功", implementTypes);
+ }
}
}
diff --git a/Blog.Core.Api/wwwroot/BlogCore.Data.json/Modules.tsv b/Blog.Core.Api/wwwroot/BlogCore.Data.json/Modules.tsv
index 97e59c96..a0f2eaef 100644
--- a/Blog.Core.Api/wwwroot/BlogCore.Data.json/Modules.tsv
+++ b/Blog.Core.Api/wwwroot/BlogCore.Data.json/Modules.tsv
@@ -988,5 +988,27 @@
"ModifyBy": null,
"ModifyTime": "\/Date(1546272000000+0800)\/",
"Id": 45
+ },
+ {
+ "IsDeleted": 0,
+ "ParentId": null,
+ "Name": "获取任务类名",
+ "LinkUrl": "\/api\/TasksQz\/GetTaskNameSpace",
+ "Area": null,
+ "Controller": null,
+ "Action": null,
+ "Icon": null,
+ "Code": null,
+ "OrderSort": 0,
+ "Description": null,
+ "IsMenu": 0,
+ "Enabled": 1,
+ "CreateId": 12,
+ "CreateBy": "后台总管理员",
+ "CreateTime": "\/Date(1546272000000+0800)\/",
+ "ModifyId": null,
+ "ModifyBy": null,
+ "ModifyTime": "\/Date(1546272000000+0800)\/",
+ "Id": 46
}
]
diff --git a/Blog.Core.Api/wwwroot/BlogCore.Data.json/Permission.tsv b/Blog.Core.Api/wwwroot/BlogCore.Data.json/Permission.tsv
index 336b33f0..9054658f 100644
--- a/Blog.Core.Api/wwwroot/BlogCore.Data.json/Permission.tsv
+++ b/Blog.Core.Api/wwwroot/BlogCore.Data.json/Permission.tsv
@@ -1,12 +1,12 @@
[
{
"Code": "\/",
- "Name": "QQ欢迎页",
+ "Name": "首页",
"IsButton": 0,
"Pid": 0,
"Mid": 0,
"OrderSort": 0,
- "Icon": "fa-qq",
+ "Icon": "fa-home",
"Description": "33",
"Enabled": 1,
"CreateId": 18,
@@ -1730,5 +1730,26 @@
"IsDeleted": 0,
"Id": 85,
"IsHide": 0
+ },
+ {
+ "Code": " ",
+ "Name": "获取任务名称",
+ "IsButton": 1,
+ "Pid": 76,
+ "Mid": 46,
+ "OrderSort": 0,
+ "Icon": null,
+ "Description": "获取任务名称按钮",
+ "Enabled": 1,
+ "CreateId": 12,
+ "CreateBy": "后台总管理员",
+ "Func": "",
+ "CreateTime": "\/Date(1546272000000+0800)\/",
+ "ModifyId": null,
+ "ModifyBy": null,
+ "ModifyTime": "\/Date(1546272000000+0800)\/",
+ "IsDeleted": 0,
+ "Id": 86,
+ "IsHide": 1
}
]
diff --git a/Blog.Core.Model/ViewModels/QuartzReflectionViewModel.cs b/Blog.Core.Model/ViewModels/QuartzReflectionViewModel.cs
new file mode 100644
index 00000000..8b5e70ee
--- /dev/null
+++ b/Blog.Core.Model/ViewModels/QuartzReflectionViewModel.cs
@@ -0,0 +1,21 @@
+namespace Blog.Core.Model.ViewModels
+{
+ ///
+ /// 实现IJob的类
+ ///
+ public class QuartzReflectionViewModel
+ {
+ ///
+ /// 命名空间
+ ///
+ public string nameSpace{ get; set; }
+ ///
+ /// 类名
+ ///
+ public string nameClass { get; set; }
+ ///
+ /// 备注
+ ///
+ public string remark { get; set; }
+ }
+}
From 74aa72b0a24d0c688f6e6cadc29cdefa74127700 Mon Sep 17 00:00:00 2001
From: anjoy8 <3143422472@qq.com>
Date: Mon, 29 Mar 2021 21:56:14 +0800
Subject: [PATCH 003/456] try use PropertiesAutowired in project
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
尝试使用属性依赖注入,例子参考BlogArticelController
---
Blog.Core.Api/Controllers/BlogController.cs | 7 ++++---
.../Filter/AutofacPropertityModuleReg.cs | 17 +++++++++++++++++
Blog.Core.Api/Startup.cs | 5 +++++
.../ServiceExtensions/AutofacModuleRegister.cs | 2 ++
Blog.Core.Services/BASE/BaseServices.cs | 2 +-
Blog.Core.Services/BlogArticleServices.cs | 6 ++----
6 files changed, 31 insertions(+), 8 deletions(-)
create mode 100644 Blog.Core.Api/Filter/AutofacPropertityModuleReg.cs
diff --git a/Blog.Core.Api/Controllers/BlogController.cs b/Blog.Core.Api/Controllers/BlogController.cs
index 1e0732a9..f36249fd 100644
--- a/Blog.Core.Api/Controllers/BlogController.cs
+++ b/Blog.Core.Api/Controllers/BlogController.cs
@@ -22,9 +22,9 @@ namespace Blog.Core.Controllers
///
[Produces("application/json")]
[Route("api/Blog")]
- public class BlogController : Controller
+ public class BlogController : ControllerBase
{
- readonly IBlogArticleServices _blogArticleServices;
+ public IBlogArticleServices _blogArticleServices { get; set; }
private readonly ILogger _logger;
///
@@ -34,7 +34,6 @@ public class BlogController : Controller
///
public BlogController(IBlogArticleServices blogArticleServices, ILogger logger)
{
- _blogArticleServices = blogArticleServices;
_logger = logger;
}
@@ -57,6 +56,8 @@ public async Task>> Get(int id, int page = 1
}
Expression> whereExpression = a => (a.bcategory == bcategory && a.IsDeleted == false) && ((a.btitle != null && a.btitle.Contains(key)) || (a.bcontent != null && a.bcontent.Contains(key)));
+
+ var testId = await _blogArticleServices.GetBlogDetails(1);
var pageModelBlog = await _blogArticleServices.QueryPage(whereExpression, page, intPageSize, " bID desc ");
diff --git a/Blog.Core.Api/Filter/AutofacPropertityModuleReg.cs b/Blog.Core.Api/Filter/AutofacPropertityModuleReg.cs
new file mode 100644
index 00000000..9691178d
--- /dev/null
+++ b/Blog.Core.Api/Filter/AutofacPropertityModuleReg.cs
@@ -0,0 +1,17 @@
+using Autofac;
+using Microsoft.AspNetCore.Mvc;
+
+namespace Blog.Core.Extensions
+{
+ public class AutofacPropertityModuleReg : Autofac.Module
+ {
+ protected override void Load(ContainerBuilder builder)
+ {
+ var controllerBaseType = typeof(ControllerBase);
+ builder.RegisterAssemblyTypes(typeof(Program).Assembly)
+ .Where(t => controllerBaseType.IsAssignableFrom(t) && t != controllerBaseType)
+ .PropertiesAutowired();
+
+ }
+ }
+}
diff --git a/Blog.Core.Api/Startup.cs b/Blog.Core.Api/Startup.cs
index a1a7e70f..f75a7df5 100644
--- a/Blog.Core.Api/Startup.cs
+++ b/Blog.Core.Api/Startup.cs
@@ -11,9 +11,11 @@
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Mvc;
+using Microsoft.AspNetCore.Mvc.Controllers;
using Microsoft.AspNetCore.Server.Kestrel.Core;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
+using Microsoft.Extensions.DependencyInjection.Extensions;
using Microsoft.Extensions.Hosting;
using Newtonsoft.Json;
using Newtonsoft.Json.Serialization;
@@ -116,6 +118,8 @@ public void ConfigureServices(IServiceCollection services)
options.SerializerSettings.DateTimeZoneHandling = DateTimeZoneHandling.Local;
});
+ services.Replace(ServiceDescriptor.Transient());
+
_services = services;
//支持编码大全 例如:支持 System.Text.Encoding.GetEncoding("GB2312") System.Text.Encoding.GetEncoding("GB18030")
Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);
@@ -125,6 +129,7 @@ public void ConfigureServices(IServiceCollection services)
public void ConfigureContainer(ContainerBuilder builder)
{
builder.RegisterModule(new AutofacModuleRegister());
+ builder.RegisterModule();
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
diff --git a/Blog.Core.Extensions/ServiceExtensions/AutofacModuleRegister.cs b/Blog.Core.Extensions/ServiceExtensions/AutofacModuleRegister.cs
index 888afc79..5cd4ba6a 100644
--- a/Blog.Core.Extensions/ServiceExtensions/AutofacModuleRegister.cs
+++ b/Blog.Core.Extensions/ServiceExtensions/AutofacModuleRegister.cs
@@ -66,6 +66,7 @@ protected override void Load(ContainerBuilder builder)
builder.RegisterAssemblyTypes(assemblysServices)
.AsImplementedInterfaces()
.InstancePerDependency()
+ .PropertiesAutowired()
.EnableInterfaceInterceptors()//引用Autofac.Extras.DynamicProxy;
.InterceptedBy(cacheType.ToArray());//允许将拦截器服务的列表分配给注册。
@@ -73,6 +74,7 @@ protected override void Load(ContainerBuilder builder)
var assemblysRepository = Assembly.LoadFrom(repositoryDllFile);
builder.RegisterAssemblyTypes(assemblysRepository)
.AsImplementedInterfaces()
+ .PropertiesAutowired()
.InstancePerDependency();
#endregion
diff --git a/Blog.Core.Services/BASE/BaseServices.cs b/Blog.Core.Services/BASE/BaseServices.cs
index 6187088f..ebde1bf7 100644
--- a/Blog.Core.Services/BASE/BaseServices.cs
+++ b/Blog.Core.Services/BASE/BaseServices.cs
@@ -13,7 +13,7 @@ namespace Blog.Core.Services.BASE
public class BaseServices : IBaseServices where TEntity : class, new()
{
//public IBaseRepository baseDal = new BaseRepository();
- public IBaseRepository BaseDal;//通过在子类的构造函数中注入,这里是基类,不用构造函数
+ public IBaseRepository BaseDal { get; set; }//通过在子类的构造函数中注入,这里是基类,不用构造函数
public async Task QueryById(object objId)
{
diff --git a/Blog.Core.Services/BlogArticleServices.cs b/Blog.Core.Services/BlogArticleServices.cs
index 5b9aa6ea..512f4fbd 100644
--- a/Blog.Core.Services/BlogArticleServices.cs
+++ b/Blog.Core.Services/BlogArticleServices.cs
@@ -13,12 +13,10 @@ namespace Blog.Core.Services
{
public class BlogArticleServices : BaseServices, IBlogArticleServices
{
- IBaseRepository _dal;
+ public IBaseRepository _dal { get; set; }
IMapper _mapper;
- public BlogArticleServices(IBaseRepository dal, IMapper mapper)
+ public BlogArticleServices(IMapper mapper)
{
- this._dal = dal;
- base.BaseDal = dal;
this._mapper = mapper;
}
///
From f1b21321292ad3ae90989493671c77fd88ea3bbf Mon Sep 17 00:00:00 2001
From: anjoy8 <3143422472@qq.com>
Date: Wed, 31 Mar 2021 19:06:25 +0800
Subject: [PATCH 004/456] =?UTF-8?q?Revert=20"=E8=B0=83=E5=BA=A6=E6=9C=8D?=
=?UTF-8?q?=E5=8A=A1=E6=89=B9=E9=87=8F=E6=B3=A8=E5=85=A5=20=E5=85=8D?=
=?UTF-8?q?=E5=BE=97=E6=AF=8F=E6=AC=A1=E9=83=BD=E5=8E=BB=E5=86=99add"?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
This reverts commit 500b720f5a66048baf272c8a3bdb4d70d377bbb6.
---
.../ServiceExtensions/JobSetup.cs | 20 +-------
Blog.Core.Tasks/QuartzNet/Jobs/JobBase.cs | 25 +++++-----
.../QuartzNet/Jobs/Job_Blogs_Quartz.cs | 48 +++++++++++++++----
.../QuartzNet/Jobs/Job_OperateLog_Quartz.cs | 31 ++++++++----
4 files changed, 79 insertions(+), 45 deletions(-)
diff --git a/Blog.Core.Extensions/ServiceExtensions/JobSetup.cs b/Blog.Core.Extensions/ServiceExtensions/JobSetup.cs
index 318168d2..28350014 100644
--- a/Blog.Core.Extensions/ServiceExtensions/JobSetup.cs
+++ b/Blog.Core.Extensions/ServiceExtensions/JobSetup.cs
@@ -1,10 +1,7 @@
using Blog.Core.Tasks;
using Microsoft.Extensions.DependencyInjection;
-using Quartz;
using Quartz.Spi;
using System;
-using System.Linq;
-using System.Reflection;
namespace Blog.Core.Extensions
{
@@ -21,22 +18,9 @@ public static void AddJobSetup(this IServiceCollection services)
//services.AddHostedService();
services.AddSingleton();
- //services.AddTransient();//Job使用瞬时依赖注入
- //services.AddTransient();//Job使用瞬时依赖注入
+ services.AddTransient();//Job使用瞬时依赖注入
+ services.AddTransient();//Job使用瞬时依赖注入
services.AddSingleton();
- //任务注入
- var baseType = typeof(IJob);
- var path = AppDomain.CurrentDomain.RelativeSearchPath ?? AppDomain.CurrentDomain.BaseDirectory;
- var referencedAssemblies = System.IO.Directory.GetFiles(path, "Blog.Core.Tasks.dll").Select(Assembly.LoadFrom).ToArray();
- var types = referencedAssemblies
- .SelectMany(a => a.DefinedTypes)
- .Select(type => type.AsType())
- .Where(x => x != baseType && baseType.IsAssignableFrom(x)).ToArray();
- var implementTypes = types.Where(x => x.IsClass).ToArray();
- foreach (var implementType in implementTypes)
- {
- services.AddTransient(implementType);
- }
}
}
}
diff --git a/Blog.Core.Tasks/QuartzNet/Jobs/JobBase.cs b/Blog.Core.Tasks/QuartzNet/Jobs/JobBase.cs
index 4e4cd900..a020fd9f 100644
--- a/Blog.Core.Tasks/QuartzNet/Jobs/JobBase.cs
+++ b/Blog.Core.Tasks/QuartzNet/Jobs/JobBase.cs
@@ -9,7 +9,11 @@ namespace Blog.Core.Tasks
{
public class JobBase
{
- public ITasksQzServices _tasksQzServices;
+ public readonly ITasksQzServices _tasksQzServices;
+ public JobBase(ITasksQzServices tasksQzServices)
+ {
+ _tasksQzServices = tasksQzServices;
+ }
///
/// 执行指定任务
///
@@ -39,23 +43,22 @@ public async Task ExecuteJob(IJobExecutionContext context, Func fu
JobExecutionException e2 = new JobExecutionException(ex);
//true 是立即重新执行任务
e2.RefireImmediately = true;
+ //SerilogServer.WriteErrorLog(context.Trigger.Key.Name.Replace("-", ""), $"{context.Trigger.Key.Name}任务运行异常", ex);
+
jobHistory += $",【{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")}】【执行失败:{ex.Message}】";
}
finally
{
taskSeconds = Math.Round(stopwatch.Elapsed.TotalSeconds, 3);
jobHistory += $",【{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")}】【执行结束】(耗时:{taskSeconds}秒)";
- if(_tasksQzServices!=null)
+ var model = await _tasksQzServices.QueryById(jobid);
+ if (model != null)
{
- var model = await _tasksQzServices.QueryById(jobid);
- if (model != null)
- {
- model.RunTimes += 1;
- var separator = "
";
- model.Remark =
- $"{jobHistory}{separator}" + string.Join(separator, StringHelper.GetTopDataBySeparator(model.Remark, separator, 9));
- await _tasksQzServices.Update(model);
- }
+ model.RunTimes += 1;
+ var separator = "
";
+ model.Remark =
+ $"{jobHistory}{separator}" + string.Join(separator, StringHelper.GetTopDataBySeparator(model.Remark, separator, 9));
+ await _tasksQzServices.Update(model);
}
}
diff --git a/Blog.Core.Tasks/QuartzNet/Jobs/Job_Blogs_Quartz.cs b/Blog.Core.Tasks/QuartzNet/Jobs/Job_Blogs_Quartz.cs
index fea1e636..8bdd8205 100644
--- a/Blog.Core.Tasks/QuartzNet/Jobs/Job_Blogs_Quartz.cs
+++ b/Blog.Core.Tasks/QuartzNet/Jobs/Job_Blogs_Quartz.cs
@@ -13,21 +13,53 @@ public class Job_Blogs_Quartz : JobBase, IJob
{
private readonly IBlogArticleServices _blogArticleServices;
- public Job_Blogs_Quartz(IBlogArticleServices blogArticleServices, ITasksQzServices tasksQzServices)
+ public Job_Blogs_Quartz(IBlogArticleServices blogArticleServices, ITasksQzServices tasksQzServices):base(tasksQzServices)
{
- _blogArticleServices = blogArticleServices;
- _tasksQzServices = tasksQzServices;
+ _blogArticleServices = blogArticleServices;
}
public async Task Execute(IJobExecutionContext context)
{
- var executeLog = await ExecuteJob(context, async () => await Run(context));
- }
- public async Task Run(IJobExecutionContext context)
- {
- var list = await _blogArticleServices.Query();
+
+ //var param = context.MergedJobDataMap;
+ // 可以直接获取 JobDetail 的值
+ var jobKey = context.JobDetail.Key;
+ var jobId = jobKey.Name;
+
+ var executeLog = await ExecuteJob(context, async () => await Run(context, jobId.ObjToInt()));
+
// 也可以通过数据库配置,获取传递过来的参数
JobDataMap data = context.JobDetail.JobDataMap;
//int jobId = data.GetInt("JobParam");
+
+ //var model = await _tasksQzServices.QueryById(jobId);
+ //if (model != null)
+ //{
+ // model.RunTimes += 1;
+ // model.Remark += $"{executeLog}
";
+ // await _tasksQzServices.Update(model);
+ //}
+
+ }
+ public async Task Run(IJobExecutionContext context, int jobid)
+ {
+ var list = await _blogArticleServices.Query();
+
+ if (jobid > 0)
+ {
+ var model = await _tasksQzServices.QueryById(jobid);
+ if (model != null)
+ {
+ model.RunTimes += 1;
+ var separator = "
";
+ model.Remark =
+ $"【{DateTime.Now}】执行任务【Id:{context.JobDetail.Key.Name},组别:{context.JobDetail.Key.Group}】【执行成功】:博客数{list.Count}{separator}"
+ + string.Join(separator, StringHelper.GetTopDataBySeparator(model.Remark, separator, 9));
+
+ await _tasksQzServices.Update(model);
+ }
+ }
+
+ await Console.Out.WriteLineAsync("博客总数量" + list.Count.ToString());
}
}
}
diff --git a/Blog.Core.Tasks/QuartzNet/Jobs/Job_OperateLog_Quartz.cs b/Blog.Core.Tasks/QuartzNet/Jobs/Job_OperateLog_Quartz.cs
index eb7aac03..bc364096 100644
--- a/Blog.Core.Tasks/QuartzNet/Jobs/Job_OperateLog_Quartz.cs
+++ b/Blog.Core.Tasks/QuartzNet/Jobs/Job_OperateLog_Quartz.cs
@@ -21,25 +21,24 @@ public class Job_OperateLog_Quartz : JobBase, IJob
private readonly IOperateLogServices _operateLogServices;
private readonly IWebHostEnvironment _environment;
- public Job_OperateLog_Quartz(IOperateLogServices operateLogServices, ITasksQzServices tasksQzServices, IWebHostEnvironment environment)
+ public Job_OperateLog_Quartz(IOperateLogServices operateLogServices, ITasksQzServices tasksQzServices, IWebHostEnvironment environment) : base(tasksQzServices)
{
_operateLogServices = operateLogServices;
_environment = environment;
- _tasksQzServices = tasksQzServices;
}
public async Task Execute(IJobExecutionContext context)
{
- var executeLog = await ExecuteJob(context, async () => await Run(context));
- }
- public async Task Run(IJobExecutionContext context)
- {
-
// 可以直接获取 JobDetail 的值
var jobKey = context.JobDetail.Key;
var jobId = jobKey.Name;
+
+ var executeLog = await ExecuteJob(context, async () => await Run(context, jobId.ObjToInt()));
+
// 也可以通过数据库配置,获取传递过来的参数
JobDataMap data = context.JobDetail.JobDataMap;
-
+ }
+ public async Task Run(IJobExecutionContext context, int jobid)
+ {
List excLogs = new List();
var exclogContent = LogLock.ReadLog(Path.Combine(_environment.ContentRootPath, "Log"), $"GlobalExceptionLogs_{DateTime.Now.ToString("yyyMMdd")}.log", Encoding.UTF8);
@@ -77,6 +76,22 @@ public async Task Run(IJobExecutionContext context)
{
var logsIds = await _operateLogServices.Add(operateLogs);
}
+
+ if (jobid > 0)
+ {
+ var model = await _tasksQzServices.QueryById(jobid);
+ if (model != null)
+ {
+ var list = await _operateLogServices.Query(d => d.IsDeleted == false);
+ model.RunTimes += 1;
+ var separator = "
";
+ model.Remark =
+ $"【{DateTime.Now}】执行任务【Id:{context.JobDetail.Key.Name},组别:{context.JobDetail.Key.Group}】【执行成功】:异常数{list.Count}{separator}"
+ + string.Join(separator, StringHelper.GetTopDataBySeparator(model.Remark, separator, 9));
+
+ await _tasksQzServices.Update(model);
+ }
+ }
}
}
From 2c012922ad4d38d915ebe6868c53222374660886 Mon Sep 17 00:00:00 2001
From: anjoy8 <3143422472@qq.com>
Date: Wed, 31 Mar 2021 19:31:08 +0800
Subject: [PATCH 005/456] Update Job_Blogs_Quartz.cs
---
.../QuartzNet/Jobs/Job_Blogs_Quartz.cs | 16 ++++++++++++----
1 file changed, 12 insertions(+), 4 deletions(-)
diff --git a/Blog.Core.Tasks/QuartzNet/Jobs/Job_Blogs_Quartz.cs b/Blog.Core.Tasks/QuartzNet/Jobs/Job_Blogs_Quartz.cs
index 8bdd8205..1ba85b4d 100644
--- a/Blog.Core.Tasks/QuartzNet/Jobs/Job_Blogs_Quartz.cs
+++ b/Blog.Core.Tasks/QuartzNet/Jobs/Job_Blogs_Quartz.cs
@@ -11,11 +11,11 @@ namespace Blog.Core.Tasks
{
public class Job_Blogs_Quartz : JobBase, IJob
{
- private readonly IBlogArticleServices _blogArticleServices;
+ private readonly IBlogArticleServices _blogArticleServices;
- public Job_Blogs_Quartz(IBlogArticleServices blogArticleServices, ITasksQzServices tasksQzServices):base(tasksQzServices)
+ public Job_Blogs_Quartz(IBlogArticleServices blogArticleServices, ITasksQzServices tasksQzServices) : base(tasksQzServices)
{
- _blogArticleServices = blogArticleServices;
+ _blogArticleServices = blogArticleServices;
}
public async Task Execute(IJobExecutionContext context)
{
@@ -25,7 +25,7 @@ public async Task Execute(IJobExecutionContext context)
var jobKey = context.JobDetail.Key;
var jobId = jobKey.Name;
- var executeLog = await ExecuteJob(context, async () => await Run(context, jobId.ObjToInt()));
+ var executeLog = await ExecuteJob(context, async () => await Run(context));
// 也可以通过数据库配置,获取传递过来的参数
JobDataMap data = context.JobDetail.JobDataMap;
@@ -40,6 +40,14 @@ public async Task Execute(IJobExecutionContext context)
//}
}
+ public async Task Run(IJobExecutionContext context)
+ {
+ var list = await _blogArticleServices.Query();
+ // 也可以通过数据库配置,获取传递过来的参数
+ JobDataMap data = context.JobDetail.JobDataMap;
+ //int jobId = data.GetInt("JobParam");
+ }
+
public async Task Run(IJobExecutionContext context, int jobid)
{
var list = await _blogArticleServices.Query();
From 2225c054889676494e61b641c90d9678c8777f0d Mon Sep 17 00:00:00 2001
From: anjoy8 <3143422472@qq.com>
Date: Thu, 1 Apr 2021 14:56:26 +0800
Subject: [PATCH 006/456] continue in task
---
.../ServiceExtensions/JobSetup.cs | 20 +++++++-
Blog.Core.Tasks/QuartzNet/Jobs/JobBase.cs | 25 +++++-----
.../QuartzNet/Jobs/Job_Blogs_Quartz.cs | 48 ++-----------------
.../QuartzNet/Jobs/Job_OperateLog_Quartz.cs | 34 ++++---------
4 files changed, 41 insertions(+), 86 deletions(-)
diff --git a/Blog.Core.Extensions/ServiceExtensions/JobSetup.cs b/Blog.Core.Extensions/ServiceExtensions/JobSetup.cs
index 28350014..318168d2 100644
--- a/Blog.Core.Extensions/ServiceExtensions/JobSetup.cs
+++ b/Blog.Core.Extensions/ServiceExtensions/JobSetup.cs
@@ -1,7 +1,10 @@
using Blog.Core.Tasks;
using Microsoft.Extensions.DependencyInjection;
+using Quartz;
using Quartz.Spi;
using System;
+using System.Linq;
+using System.Reflection;
namespace Blog.Core.Extensions
{
@@ -18,9 +21,22 @@ public static void AddJobSetup(this IServiceCollection services)
//services.AddHostedService();
services.AddSingleton();
- services.AddTransient();//Job使用瞬时依赖注入
- services.AddTransient();//Job使用瞬时依赖注入
+ //services.AddTransient();//Job使用瞬时依赖注入
+ //services.AddTransient();//Job使用瞬时依赖注入
services.AddSingleton();
+ //任务注入
+ var baseType = typeof(IJob);
+ var path = AppDomain.CurrentDomain.RelativeSearchPath ?? AppDomain.CurrentDomain.BaseDirectory;
+ var referencedAssemblies = System.IO.Directory.GetFiles(path, "Blog.Core.Tasks.dll").Select(Assembly.LoadFrom).ToArray();
+ var types = referencedAssemblies
+ .SelectMany(a => a.DefinedTypes)
+ .Select(type => type.AsType())
+ .Where(x => x != baseType && baseType.IsAssignableFrom(x)).ToArray();
+ var implementTypes = types.Where(x => x.IsClass).ToArray();
+ foreach (var implementType in implementTypes)
+ {
+ services.AddTransient(implementType);
+ }
}
}
}
diff --git a/Blog.Core.Tasks/QuartzNet/Jobs/JobBase.cs b/Blog.Core.Tasks/QuartzNet/Jobs/JobBase.cs
index a020fd9f..4e4cd900 100644
--- a/Blog.Core.Tasks/QuartzNet/Jobs/JobBase.cs
+++ b/Blog.Core.Tasks/QuartzNet/Jobs/JobBase.cs
@@ -9,11 +9,7 @@ namespace Blog.Core.Tasks
{
public class JobBase
{
- public readonly ITasksQzServices _tasksQzServices;
- public JobBase(ITasksQzServices tasksQzServices)
- {
- _tasksQzServices = tasksQzServices;
- }
+ public ITasksQzServices _tasksQzServices;
///
/// 执行指定任务
///
@@ -43,22 +39,23 @@ public async Task ExecuteJob(IJobExecutionContext context, Func fu
JobExecutionException e2 = new JobExecutionException(ex);
//true 是立即重新执行任务
e2.RefireImmediately = true;
- //SerilogServer.WriteErrorLog(context.Trigger.Key.Name.Replace("-", ""), $"{context.Trigger.Key.Name}任务运行异常", ex);
-
jobHistory += $",【{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")}】【执行失败:{ex.Message}】";
}
finally
{
taskSeconds = Math.Round(stopwatch.Elapsed.TotalSeconds, 3);
jobHistory += $",【{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")}】【执行结束】(耗时:{taskSeconds}秒)";
- var model = await _tasksQzServices.QueryById(jobid);
- if (model != null)
+ if(_tasksQzServices!=null)
{
- model.RunTimes += 1;
- var separator = "
";
- model.Remark =
- $"{jobHistory}{separator}" + string.Join(separator, StringHelper.GetTopDataBySeparator(model.Remark, separator, 9));
- await _tasksQzServices.Update(model);
+ var model = await _tasksQzServices.QueryById(jobid);
+ if (model != null)
+ {
+ model.RunTimes += 1;
+ var separator = "
";
+ model.Remark =
+ $"{jobHistory}{separator}" + string.Join(separator, StringHelper.GetTopDataBySeparator(model.Remark, separator, 9));
+ await _tasksQzServices.Update(model);
+ }
}
}
diff --git a/Blog.Core.Tasks/QuartzNet/Jobs/Job_Blogs_Quartz.cs b/Blog.Core.Tasks/QuartzNet/Jobs/Job_Blogs_Quartz.cs
index 1ba85b4d..173e996e 100644
--- a/Blog.Core.Tasks/QuartzNet/Jobs/Job_Blogs_Quartz.cs
+++ b/Blog.Core.Tasks/QuartzNet/Jobs/Job_Blogs_Quartz.cs
@@ -1,7 +1,5 @@
-using Blog.Core.Common.Helper;
-using Blog.Core.IServices;
+using Blog.Core.IServices;
using Quartz;
-using System;
using System.Threading.Tasks;
///
@@ -13,32 +11,14 @@ public class Job_Blogs_Quartz : JobBase, IJob
{
private readonly IBlogArticleServices _blogArticleServices;
- public Job_Blogs_Quartz(IBlogArticleServices blogArticleServices, ITasksQzServices tasksQzServices) : base(tasksQzServices)
+ public Job_Blogs_Quartz(IBlogArticleServices blogArticleServices, ITasksQzServices tasksQzServices)
{
_blogArticleServices = blogArticleServices;
+ _tasksQzServices = tasksQzServices;
}
public async Task Execute(IJobExecutionContext context)
{
-
- //var param = context.MergedJobDataMap;
- // 可以直接获取 JobDetail 的值
- var jobKey = context.JobDetail.Key;
- var jobId = jobKey.Name;
-
var executeLog = await ExecuteJob(context, async () => await Run(context));
-
- // 也可以通过数据库配置,获取传递过来的参数
- JobDataMap data = context.JobDetail.JobDataMap;
- //int jobId = data.GetInt("JobParam");
-
- //var model = await _tasksQzServices.QueryById(jobId);
- //if (model != null)
- //{
- // model.RunTimes += 1;
- // model.Remark += $"{executeLog}
";
- // await _tasksQzServices.Update(model);
- //}
-
}
public async Task Run(IJobExecutionContext context)
{
@@ -47,27 +27,5 @@ public async Task Run(IJobExecutionContext context)
JobDataMap data = context.JobDetail.JobDataMap;
//int jobId = data.GetInt("JobParam");
}
-
- public async Task Run(IJobExecutionContext context, int jobid)
- {
- var list = await _blogArticleServices.Query();
-
- if (jobid > 0)
- {
- var model = await _tasksQzServices.QueryById(jobid);
- if (model != null)
- {
- model.RunTimes += 1;
- var separator = "
";
- model.Remark =
- $"【{DateTime.Now}】执行任务【Id:{context.JobDetail.Key.Name},组别:{context.JobDetail.Key.Group}】【执行成功】:博客数{list.Count}{separator}"
- + string.Join(separator, StringHelper.GetTopDataBySeparator(model.Remark, separator, 9));
-
- await _tasksQzServices.Update(model);
- }
- }
-
- await Console.Out.WriteLineAsync("博客总数量" + list.Count.ToString());
- }
}
}
diff --git a/Blog.Core.Tasks/QuartzNet/Jobs/Job_OperateLog_Quartz.cs b/Blog.Core.Tasks/QuartzNet/Jobs/Job_OperateLog_Quartz.cs
index bc364096..8e9b3847 100644
--- a/Blog.Core.Tasks/QuartzNet/Jobs/Job_OperateLog_Quartz.cs
+++ b/Blog.Core.Tasks/QuartzNet/Jobs/Job_OperateLog_Quartz.cs
@@ -1,5 +1,4 @@
-using Blog.Core.Common.Helper;
-using Blog.Core.Common.LogHelper;
+using Blog.Core.Common.LogHelper;
using Blog.Core.IServices;
using Blog.Core.Model.Models;
using Microsoft.AspNetCore.Hosting;
@@ -21,24 +20,25 @@ public class Job_OperateLog_Quartz : JobBase, IJob
private readonly IOperateLogServices _operateLogServices;
private readonly IWebHostEnvironment _environment;
- public Job_OperateLog_Quartz(IOperateLogServices operateLogServices, ITasksQzServices tasksQzServices, IWebHostEnvironment environment) : base(tasksQzServices)
+ public Job_OperateLog_Quartz(IOperateLogServices operateLogServices, ITasksQzServices tasksQzServices, IWebHostEnvironment environment)
{
_operateLogServices = operateLogServices;
_environment = environment;
+ _tasksQzServices = tasksQzServices;
}
public async Task Execute(IJobExecutionContext context)
{
+ var executeLog = await ExecuteJob(context, async () => await Run(context));
+ }
+ public async Task Run(IJobExecutionContext context)
+ {
+
// 可以直接获取 JobDetail 的值
var jobKey = context.JobDetail.Key;
var jobId = jobKey.Name;
-
- var executeLog = await ExecuteJob(context, async () => await Run(context, jobId.ObjToInt()));
-
// 也可以通过数据库配置,获取传递过来的参数
JobDataMap data = context.JobDetail.JobDataMap;
- }
- public async Task Run(IJobExecutionContext context, int jobid)
- {
+
List excLogs = new List();
var exclogContent = LogLock.ReadLog(Path.Combine(_environment.ContentRootPath, "Log"), $"GlobalExceptionLogs_{DateTime.Now.ToString("yyyMMdd")}.log", Encoding.UTF8);
@@ -76,22 +76,6 @@ public async Task Run(IJobExecutionContext context, int jobid)
{
var logsIds = await _operateLogServices.Add(operateLogs);
}
-
- if (jobid > 0)
- {
- var model = await _tasksQzServices.QueryById(jobid);
- if (model != null)
- {
- var list = await _operateLogServices.Query(d => d.IsDeleted == false);
- model.RunTimes += 1;
- var separator = "
";
- model.Remark =
- $"【{DateTime.Now}】执行任务【Id:{context.JobDetail.Key.Name},组别:{context.JobDetail.Key.Group}】【执行成功】:异常数{list.Count}{separator}"
- + string.Join(separator, StringHelper.GetTopDataBySeparator(model.Remark, separator, 9));
-
- await _tasksQzServices.Update(model);
- }
- }
}
}
From 224ac50ca19651102d2db2de711ba55049c42076 Mon Sep 17 00:00:00 2001
From: ansonzhang <3143422472@qq.com>
Date: Fri, 2 Apr 2021 15:38:11 +0800
Subject: [PATCH 007/456] Update CreateYourProject.bat
---
CreateYourProject.bat | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/CreateYourProject.bat b/CreateYourProject.bat
index e3a3da63..43a2a429 100644
--- a/CreateYourProject.bat
+++ b/CreateYourProject.bat
@@ -3,7 +3,7 @@ echo "if u install template error,pls use:>>dotnet new -i .template.config\Blog.
color 3
-dotnet new -i Blog.Core.Webapi.Template::2.5.2
+dotnet new -i Blog.Core.Webapi.Template::2.5.3
set /p OP=Please set your project name(for example:Baidu.Api):
@@ -23,4 +23,4 @@ dotnet new -u Blog.Core.Webapi.Template
echo "Delete Template Successfully"
-pause
\ No newline at end of file
+pause
From 0bd797792e36fb64bf404337a8394313ad8120aa Mon Sep 17 00:00:00 2001
From: hudingwen <765472804@qq.com>
Date: Thu, 8 Apr 2021 17:27:16 +0800
Subject: [PATCH 008/456] =?UTF-8?q?=E8=B0=83=E5=BA=A6=E4=BC=98=E5=8C=96?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
Blog.Core.Tasks/QuartzNet/Jobs/JobBase.cs | 48 +++++++++++++------
.../QuartzNet/Jobs/Job_Blogs_Quartz.cs | 8 ++--
.../QuartzNet/Jobs/Job_OperateLog_Quartz.cs | 6 +--
3 files changed, 41 insertions(+), 21 deletions(-)
diff --git a/Blog.Core.Tasks/QuartzNet/Jobs/JobBase.cs b/Blog.Core.Tasks/QuartzNet/Jobs/JobBase.cs
index 4e4cd900..8d16c110 100644
--- a/Blog.Core.Tasks/QuartzNet/Jobs/JobBase.cs
+++ b/Blog.Core.Tasks/QuartzNet/Jobs/JobBase.cs
@@ -1,15 +1,22 @@
-using Blog.Core.Common.Helper;
-using Blog.Core.IServices;
+using Blog.Core.IServices;
+using Microsoft.Extensions.Logging;
using Quartz;
using System;
using System.Diagnostics;
+using System.Linq;
using System.Threading.Tasks;
namespace Blog.Core.Tasks
{
public class JobBase
{
- public ITasksQzServices _tasksQzServices;
+ protected ITasksQzServices _tasksQzServices;
+ protected ILogger _logger;
+ public JobBase(ITasksQzServices tasksQzServices, ILogger logger)
+ {
+ _tasksQzServices = tasksQzServices;
+ _logger = logger;
+ }
///
/// 执行指定任务
///
@@ -43,22 +50,33 @@ public async Task ExecuteJob(IJobExecutionContext context, Func fu
}
finally
{
- taskSeconds = Math.Round(stopwatch.Elapsed.TotalSeconds, 3);
- jobHistory += $",【{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")}】【执行结束】(耗时:{taskSeconds}秒)";
- if(_tasksQzServices!=null)
+ try
{
- var model = await _tasksQzServices.QueryById(jobid);
- if (model != null)
+ taskSeconds = Math.Round(stopwatch.Elapsed.TotalSeconds, 3);
+ jobHistory += $",【{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")}】【执行结束】(耗时:{taskSeconds}秒)";
+ if (_tasksQzServices != null)
{
- model.RunTimes += 1;
- var separator = "
";
- model.Remark =
- $"{jobHistory}{separator}" + string.Join(separator, StringHelper.GetTopDataBySeparator(model.Remark, separator, 9));
- await _tasksQzServices.Update(model);
+ var model = await _tasksQzServices.QueryById(jobid);
+ if (model != null)
+ {
+ model.RunTimes += 1;
+ var separator = "
";
+ model.Remark =
+ $"{jobHistory}{separator}" + string.Join(separator, model.Remark.ObjToString().Split(separator).ToList().Take(9).ToArray());
+ await _tasksQzServices.Update(model);
+ }
}
}
- }
-
+ catch (Exception ex)
+ {
+ jobHistory += ex.Message;
+ }
+ finally
+ {
+ if(_logger!=null)
+ _logger.LogInformation(jobHistory);
+ }
+ }
Console.Out.WriteLine(jobHistory);
return jobHistory;
}
diff --git a/Blog.Core.Tasks/QuartzNet/Jobs/Job_Blogs_Quartz.cs b/Blog.Core.Tasks/QuartzNet/Jobs/Job_Blogs_Quartz.cs
index fea1e636..3d33ce23 100644
--- a/Blog.Core.Tasks/QuartzNet/Jobs/Job_Blogs_Quartz.cs
+++ b/Blog.Core.Tasks/QuartzNet/Jobs/Job_Blogs_Quartz.cs
@@ -1,5 +1,6 @@
using Blog.Core.Common.Helper;
using Blog.Core.IServices;
+using Microsoft.Extensions.Logging;
using Quartz;
using System;
using System.Threading.Tasks;
@@ -13,10 +14,11 @@ public class Job_Blogs_Quartz : JobBase, IJob
{
private readonly IBlogArticleServices _blogArticleServices;
- public Job_Blogs_Quartz(IBlogArticleServices blogArticleServices, ITasksQzServices tasksQzServices)
- {
- _blogArticleServices = blogArticleServices;
+ public Job_Blogs_Quartz(ITasksQzServices tasksQzServices, ILogger logger, IBlogArticleServices blogArticleServices):base(tasksQzServices, logger)
+ {
_tasksQzServices = tasksQzServices;
+ _logger = logger;
+ _blogArticleServices = blogArticleServices;
}
public async Task Execute(IJobExecutionContext context)
{
diff --git a/Blog.Core.Tasks/QuartzNet/Jobs/Job_OperateLog_Quartz.cs b/Blog.Core.Tasks/QuartzNet/Jobs/Job_OperateLog_Quartz.cs
index eb7aac03..5e27d17b 100644
--- a/Blog.Core.Tasks/QuartzNet/Jobs/Job_OperateLog_Quartz.cs
+++ b/Blog.Core.Tasks/QuartzNet/Jobs/Job_OperateLog_Quartz.cs
@@ -3,6 +3,7 @@
using Blog.Core.IServices;
using Blog.Core.Model.Models;
using Microsoft.AspNetCore.Hosting;
+using Microsoft.Extensions.Logging;
using Quartz;
using System;
using System.Collections.Generic;
@@ -21,11 +22,10 @@ public class Job_OperateLog_Quartz : JobBase, IJob
private readonly IOperateLogServices _operateLogServices;
private readonly IWebHostEnvironment _environment;
- public Job_OperateLog_Quartz(IOperateLogServices operateLogServices, ITasksQzServices tasksQzServices, IWebHostEnvironment environment)
+ public Job_OperateLog_Quartz(ITasksQzServices tasksQzServices, ILogger logger, IOperateLogServices operateLogServices, IWebHostEnvironment environment):base(tasksQzServices, logger)
{
_operateLogServices = operateLogServices;
- _environment = environment;
- _tasksQzServices = tasksQzServices;
+ _environment = environment;
}
public async Task Execute(IJobExecutionContext context)
{
From 9aa805af0ce573b6c63f39ad14a6f72660789b6c Mon Sep 17 00:00:00 2001
From: anjoy8 <3143422472@qq.com>
Date: Sat, 17 Apr 2021 23:20:20 +0800
Subject: [PATCH 009/456] Update JobBase.cs
---
Blog.Core.Tasks/QuartzNet/Jobs/JobBase.cs | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/Blog.Core.Tasks/QuartzNet/Jobs/JobBase.cs b/Blog.Core.Tasks/QuartzNet/Jobs/JobBase.cs
index 4e4cd900..4a71fbf5 100644
--- a/Blog.Core.Tasks/QuartzNet/Jobs/JobBase.cs
+++ b/Blog.Core.Tasks/QuartzNet/Jobs/JobBase.cs
@@ -45,13 +45,14 @@ public async Task ExecuteJob(IJobExecutionContext context, Func fu
{
taskSeconds = Math.Round(stopwatch.Elapsed.TotalSeconds, 3);
jobHistory += $",【{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")}】【执行结束】(耗时:{taskSeconds}秒)";
- if(_tasksQzServices!=null)
+ if (_tasksQzServices != null)
{
var model = await _tasksQzServices.QueryById(jobid);
if (model != null)
{
model.RunTimes += 1;
var separator = "
";
+ // 这里注意数据库字段的长度问题,超过限制,会造成数据库remark不更新问题。
model.Remark =
$"{jobHistory}{separator}" + string.Join(separator, StringHelper.GetTopDataBySeparator(model.Remark, separator, 9));
await _tasksQzServices.Update(model);
From bdea9208f699fb9aef30071172fa8d72fc7f7114 Mon Sep 17 00:00:00 2001
From: ansonzhang <3143422472@qq.com>
Date: Fri, 30 Apr 2021 10:51:12 +0800
Subject: [PATCH 010/456] Fixed #180 Bug
---
Blog.Core.Repository/MongoRepository/MongoDbContext.cs | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/Blog.Core.Repository/MongoRepository/MongoDbContext.cs b/Blog.Core.Repository/MongoRepository/MongoDbContext.cs
index 66f64704..f6a0d274 100644
--- a/Blog.Core.Repository/MongoRepository/MongoDbContext.cs
+++ b/Blog.Core.Repository/MongoRepository/MongoDbContext.cs
@@ -11,7 +11,7 @@ public class MongoDbContext
public MongoDbContext()
{
- var client = new MongoClient(Appsettings.app(new string[] { "Mongo", "ConnectString" }));
+ var client = new MongoClient(Appsettings.app(new string[] { "Mongo", "ConnectionString" }));
if (client != null)
_database = client.GetDatabase(Appsettings.app(new string[] { "Mongo", "Database" }));
}
From d385ac0a07d8a3ceb17753541eb5abcd8095ad23 Mon Sep 17 00:00:00 2001
From: anjoy8 <3143422472@qq.com>
Date: Sat, 8 May 2021 09:50:04 +0800
Subject: [PATCH 011/456] Fixed #183 bug
---
.../Blog.Core.FrameWork.Services.cs | 2 +-
.../Blog.Core.FrameWork.Services.tt | 6 +++---
2 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/Blog.Core.FrameWork/Blog.Core.FrameWork.Services/Blog.Core.FrameWork.Services.cs b/Blog.Core.FrameWork/Blog.Core.FrameWork.Services/Blog.Core.FrameWork.Services.cs
index 61b806bf..b148012a 100644
--- a/Blog.Core.FrameWork/Blog.Core.FrameWork.Services/Blog.Core.FrameWork.Services.cs
+++ b/Blog.Core.FrameWork/Blog.Core.FrameWork.Services/Blog.Core.FrameWork.Services.cs
@@ -6,7 +6,7 @@
//--------------------------------------------------------------------
// 此代码由T4模板自动生成
-// 生成时间 2019-12-10 12:14:44
+// 生成时间 2021-05-08 09:48:27
// 对此文件的更改可能会导致不正确的行为,并且如果重新生成代码,这些更改将会丢失。
//--------------------------------------------------------------------
diff --git a/Blog.Core.FrameWork/Blog.Core.FrameWork.Services/Blog.Core.FrameWork.Services.tt b/Blog.Core.FrameWork/Blog.Core.FrameWork.Services/Blog.Core.FrameWork.Services.tt
index f61c0891..943cfb88 100644
--- a/Blog.Core.FrameWork/Blog.Core.FrameWork.Services/Blog.Core.FrameWork.Services.tt
+++ b/Blog.Core.FrameWork/Blog.Core.FrameWork.Services/Blog.Core.FrameWork.Services.tt
@@ -61,7 +61,7 @@ namespace Blog.Core.Services
public <#=tableName#>Services(IBaseRepository<<#=tableName#>> dal)
{
this.dal = dal;
- base.baseDal = dal;
+ base.BaseDal = dal;
}
}
@@ -108,7 +108,7 @@ namespace Blog.Core.Services
public <#=row["TABLE_NAME"].ToString() #>Services(IBaseRepository<<#=row["TABLE_NAME"].ToString() #>> dal)
{
this.dal = dal;
- base.baseDal = dal;
+ base.BaseDal = dal;
}
}
@@ -142,7 +142,7 @@ namespace Blog.Core.Services
///
public class BaseServices : IBaseServices where TEntity : class, new()
{
- public IBaseRepository baseDal;
+ public IBaseRepository BaseDal;
}
}
From 9eecac6f27379fe2b7bacf79cd0afc8716e11daf Mon Sep 17 00:00:00 2001
From: anjoy8 <3143422472@qq.com>
Date: Sat, 8 May 2021 10:59:38 +0800
Subject: [PATCH 012/456] Update Blog.Core.sln
---
Blog.Core.sln | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/Blog.Core.sln b/Blog.Core.sln
index e35d7027..2446fd7a 100644
--- a/Blog.Core.sln
+++ b/Blog.Core.sln
@@ -51,6 +51,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Blog.Core.EventBus", "Blog.
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Blog.Core.ConsoleApp", "Blog.Core.ConsoleApp\Blog.Core.ConsoleApp.csproj", "{0B3265A9-6716-4D28-8648-C64D5E692ACA}"
EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Blog.Core.Gateway", "Blog.Core.Gateway\Blog.Core.Gateway.csproj", "{A11C0DF2-1E13-4EED-BA49-44A57136B189}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -105,6 +107,10 @@ Global
{0B3265A9-6716-4D28-8648-C64D5E692ACA}.Debug|Any CPU.Build.0 = Debug|Any CPU
{0B3265A9-6716-4D28-8648-C64D5E692ACA}.Release|Any CPU.ActiveCfg = Release|Any CPU
{0B3265A9-6716-4D28-8648-C64D5E692ACA}.Release|Any CPU.Build.0 = Release|Any CPU
+ {A11C0DF2-1E13-4EED-BA49-44A57136B189}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {A11C0DF2-1E13-4EED-BA49-44A57136B189}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {A11C0DF2-1E13-4EED-BA49-44A57136B189}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {A11C0DF2-1E13-4EED-BA49-44A57136B189}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@@ -114,6 +120,7 @@ Global
{52D318A2-F44E-4CB7-8DD4-483357D4333F} = {047A9723-9AAC-42E3-8C69-B3835F15FF96}
{17C9E9DC-E926-4C90-9025-3DAC55D7EDA3} = {A592C96A-4E44-4F2A-AC21-30683AF6C493}
{0B3265A9-6716-4D28-8648-C64D5E692ACA} = {047A9723-9AAC-42E3-8C69-B3835F15FF96}
+ {A11C0DF2-1E13-4EED-BA49-44A57136B189} = {E2BD7D4D-9ED5-41CD-8401-C3FB26F203BB}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {AB40D0C5-E3EA-4A9B-86C2-38F0BB33FC04}
From ae86a2c695b5bb325d7664f3b83edbd3c857dd6e Mon Sep 17 00:00:00 2001
From: ansonzhang <3143422472@qq.com>
Date: Mon, 10 May 2021 07:18:16 -0500
Subject: [PATCH 013/456] Update README.md
---
README.md | 7 ++++++-
1 file changed, 6 insertions(+), 1 deletion(-)
diff --git a/README.md b/README.md
index 8c8d8c40..3c312675 100644
--- a/README.md
+++ b/README.md
@@ -24,7 +24,12 @@
Blog.Core 开箱即用的企业级前后端分离【 .NET Core5.0 Api + Vue 2.x + RBAC】权限框架。
官网:http://apk.neters.club/.doc/
-已被多家公司所使用:[点击查看列表](https://github.com/anjoy8/Blog.Core/issues/75)
+已被多家公司所使用:[点击查看列表](https://github.com/anjoy8/Blog.Core/issues/75)
+
+项目单体部署,并发在400~500,一切正常(不保证自己的各种错误写法)。
+如果搭配负载,效果更好。
+
+
From fd4d45106c385a56e46864bfdc1fd5001b781fe2 Mon Sep 17 00:00:00 2001
From: ansonzhang <3143422472@qq.com>
Date: Mon, 10 May 2021 07:18:59 -0500
Subject: [PATCH 014/456] Update README.md
---
README.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/README.md b/README.md
index 3c312675..c5b54c93 100644
--- a/README.md
+++ b/README.md
@@ -26,7 +26,7 @@ Blog.Core 开箱即用的企业级前后端分离【 .NET Core5.0 Api + Vue 2.x
官网:http://apk.neters.club/.doc/
已被多家公司所使用:[点击查看列表](https://github.com/anjoy8/Blog.Core/issues/75)
-项目单体部署,并发在400~500,一切正常(不保证自己的各种错误写法)。
+项目单体部署,并发在400~500,一切正常(不保证自己的各种错误写法)。
如果搭配负载,效果更好。
From c94500ac0cf6e7fa56eb6d4922fa61e43c2821b0 Mon Sep 17 00:00:00 2001
From: anjoy8 <3143422472@qq.com>
Date: Fri, 14 May 2021 16:13:25 +0800
Subject: [PATCH 015/456] =?UTF-8?q?fix=EF=BC=9Aupdate=20the=20log=20method?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../LogHelper/Seri/SerilogServer.cs | 6 ++++--
Blog.Core.Extensions/Middlewares/IPLogMildd.cs | 10 +++++-----
.../Middlewares/RecordAccessLogsMildd.cs | 10 ++++++----
.../Middlewares/RequRespLogMildd.cs | 18 ++++++++++--------
.../ServiceExtensions/AppConfigSetup.cs | 12 +++++++++++-
5 files changed, 36 insertions(+), 20 deletions(-)
diff --git a/Blog.Core.Common/LogHelper/Seri/SerilogServer.cs b/Blog.Core.Common/LogHelper/Seri/SerilogServer.cs
index 28b00929..72dad73f 100644
--- a/Blog.Core.Common/LogHelper/Seri/SerilogServer.cs
+++ b/Blog.Core.Common/LogHelper/Seri/SerilogServer.cs
@@ -13,13 +13,15 @@ public class SerilogServer
///
///
///
- public static void WriteLog(string filename, string[] dataParas, bool IsHeader = true)
+ public static void WriteLog(string filename, string[] dataParas, bool IsHeader = true, string defaultFolder = "")
{
Log.Logger = new LoggerConfiguration()
.MinimumLevel.Debug()
.MinimumLevel.Override("Microsoft", LogEventLevel.Error)
//.WriteTo.File(Path.Combine($"log/Serilog/{filename}/", ".log"), rollingInterval: RollingInterval.Day, outputTemplate: "{Timestamp:yyyy-MM-dd HH:mm:ss.fff} [{Level}] {Message}{NewLine}{Exception}")
- .WriteTo.File(Path.Combine($"log/Serilog/", $"{filename}.log"), rollingInterval: RollingInterval.Infinite, outputTemplate: "{Message}{NewLine}{Exception}")
+ .WriteTo.File(Path.Combine("log", defaultFolder, $"{filename}.log"),
+ rollingInterval: RollingInterval.Infinite,
+ outputTemplate: "{Message}{NewLine}{Exception}")
.CreateLogger();
var now = DateTime.Now;
diff --git a/Blog.Core.Extensions/Middlewares/IPLogMildd.cs b/Blog.Core.Extensions/Middlewares/IPLogMildd.cs
index cf8418f4..b8dadbad 100644
--- a/Blog.Core.Extensions/Middlewares/IPLogMildd.cs
+++ b/Blog.Core.Extensions/Middlewares/IPLogMildd.cs
@@ -51,13 +51,13 @@ public async Task InvokeAsync(HttpContext context)
if (!string.IsNullOrEmpty(requestInfo))
{
// 自定义log输出
- Parallel.For(0, 1, e =>
- {
- LogLock.OutSql2Log("RequestIpInfoLog", new string[] { requestInfo + "," }, false);
- });
+ //Parallel.For(0, 1, e =>
+ //{
+ // LogLock.OutSql2Log("RequestIpInfoLog", new string[] { requestInfo + "," }, false);
+ //});
// 这种方案也行,用的是Serilog
- //SerilogServer.WriteLog("RequestIpInfoLog", new string[] { requestInfo + "," }, false);
+ SerilogServer.WriteLog("RequestIpInfoLog", new string[] { requestInfo + "," }, false);
request.Body.Position = 0;
}
diff --git a/Blog.Core.Extensions/Middlewares/RecordAccessLogsMildd.cs b/Blog.Core.Extensions/Middlewares/RecordAccessLogsMildd.cs
index 3c19dcf3..7180b1a5 100644
--- a/Blog.Core.Extensions/Middlewares/RecordAccessLogsMildd.cs
+++ b/Blog.Core.Extensions/Middlewares/RecordAccessLogsMildd.cs
@@ -102,10 +102,12 @@ public async Task InvokeAsync(HttpContext context)
// 自定义log输出
var requestInfo = JsonConvert.SerializeObject(userAccessModel);
- Parallel.For(0, 1, e =>
- {
- LogLock.OutSql2Log("RecordAccessLogs", new string[] { requestInfo + "," }, false);
- });
+ //Parallel.For(0, 1, e =>
+ //{
+ // LogLock.OutSql2Log("RecordAccessLogs", new string[] { requestInfo + "," }, false);
+ //});
+
+ SerilogServer.WriteLog("RecordAccessLogs", new string[] { requestInfo + "," }, false);
return Task.CompletedTask;
});
diff --git a/Blog.Core.Extensions/Middlewares/RequRespLogMildd.cs b/Blog.Core.Extensions/Middlewares/RequRespLogMildd.cs
index 1593a34e..fa5a5e31 100644
--- a/Blog.Core.Extensions/Middlewares/RequRespLogMildd.cs
+++ b/Blog.Core.Extensions/Middlewares/RequRespLogMildd.cs
@@ -91,11 +91,12 @@ private async Task RequestDataLog(HttpContext context)
if (!string.IsNullOrEmpty(content))
{
- Parallel.For(0, 1, e =>
- {
- LogLock.OutSql2Log("RequestResponseLog", new string[] { "Request Data:", content });
+ //Parallel.For(0, 1, e =>
+ //{
+ // LogLock.OutSql2Log("RequestResponseLog", new string[] { "Request Data:", content });
- });
+ //});
+ SerilogServer.WriteLog("RequestResponseLog", new string[] { "Request Data:", content });
request.Body.Position = 0;
}
@@ -112,11 +113,12 @@ private void ResponseDataLog(HttpResponse response, MemoryStream ms)
if (!string.IsNullOrEmpty(ResponseBody))
{
- Parallel.For(0, 1, e =>
- {
- LogLock.OutSql2Log("RequestResponseLog", new string[] { "Response Data:", ResponseBody });
+ //Parallel.For(0, 1, e =>
+ //{
+ // LogLock.OutSql2Log("RequestResponseLog", new string[] { "Response Data:", ResponseBody });
- });
+ //});
+ SerilogServer.WriteLog("RequestResponseLog", new string[] { "Response Data:", ResponseBody });
}
}
}
diff --git a/Blog.Core.Extensions/ServiceExtensions/AppConfigSetup.cs b/Blog.Core.Extensions/ServiceExtensions/AppConfigSetup.cs
index 0c68dd61..7da10921 100644
--- a/Blog.Core.Extensions/ServiceExtensions/AppConfigSetup.cs
+++ b/Blog.Core.Extensions/ServiceExtensions/AppConfigSetup.cs
@@ -69,6 +69,16 @@ public static void AddAppConfigSetup(this IServiceCollection services, IWebHostE
ConsoleHelper.WriteSuccessLine($"Service Log AOP: True");
}
+ // 开启的中间件日志
+ var requestResponseLogOpen = Appsettings.app(new string[] { "Middleware", "RequestResponseLog", "Enabled" }).ObjToBool();
+ var ipLogOpen = Appsettings.app(new string[] { "Middleware", "IPLog", "Enabled" }).ObjToBool();
+ var recordAccessLogsOpen = Appsettings.app(new string[] { "Middleware", "RecordAccessLogs", "Enabled" }).ObjToBool();
+ ConsoleHelper.WriteSuccessLine($"OPEN Log: " +
+ (requestResponseLogOpen ? "RequestResponseLog √," : "") +
+ (ipLogOpen ? "IPLog √," : "") +
+ (recordAccessLogsOpen ? "RecordAccessLogs √," : "")
+ );
+
// 事务AOP
if (!Appsettings.app(new string[] { "AppSettings", "TranAOP", "Enabled" }).ObjToBool())
{
@@ -118,7 +128,7 @@ public static void AddAppConfigSetup(this IServiceCollection services, IWebHostE
{
ConsoleHelper.WriteSuccessLine($"MiniProfiler: True");
}
-
+
// CORS跨域
if (!Appsettings.app("Startup", "Cors", "EnableAllIPs").ObjToBool())
{
From fa6ce50e4258904dabc29657978df91e0269ad1b Mon Sep 17 00:00:00 2001
From: anjoy8 <3143422472@qq.com>
Date: Fri, 14 May 2021 19:25:10 +0800
Subject: [PATCH 016/456] =?UTF-8?q?fix=EF=BC=9Arename=20log?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
Blog.Core.Common/Helper/FileHelper.cs | 18 ++++++++++++++++++
Blog.Core.Extensions/Middlewares/IPLogMildd.cs | 12 +++++++++---
.../Middlewares/RecordAccessLogsMildd.cs | 10 ++++++++--
3 files changed, 35 insertions(+), 5 deletions(-)
diff --git a/Blog.Core.Common/Helper/FileHelper.cs b/Blog.Core.Common/Helper/FileHelper.cs
index f2d717a0..c07c86e7 100644
--- a/Blog.Core.Common/Helper/FileHelper.cs
+++ b/Blog.Core.Common/Helper/FileHelper.cs
@@ -83,6 +83,24 @@ public static string GetAvailableFileWithPrefixOrderSize(string folderPath, stri
return Path.Combine(folderPath, $@"{prefix}_{DateTime.Now.DateToTimeStamp()}.log");
}
+ public static string GetAvailableFileNameWithPrefixOrderSize(string _contentRoot, string prefix, int size = 1 * 1024 * 1024, string ext = ".log")
+ {
+ var folderPath = Path.Combine(_contentRoot, "Log");
+ if (!Directory.Exists(folderPath))
+ {
+ Directory.CreateDirectory(folderPath);
+ }
+
+ var allFiles = new DirectoryInfo(folderPath);
+ var selectFiles = allFiles.GetFiles().Where(fi => fi.Name.ToLower().Contains(prefix.ToLower()) && fi.Extension.ToLower() == ext.ToLower() && fi.Length < size).OrderByDescending(d => d.Name).ToList();
+
+ if (selectFiles.Count > 0)
+ {
+ return selectFiles.FirstOrDefault().Name.Replace(".log","");
+ }
+
+ return $@"{prefix}_{DateTime.Now.DateToTimeStamp()}";
+ }
#endregion
#region 写文件
diff --git a/Blog.Core.Extensions/Middlewares/IPLogMildd.cs b/Blog.Core.Extensions/Middlewares/IPLogMildd.cs
index b8dadbad..aa5c4265 100644
--- a/Blog.Core.Extensions/Middlewares/IPLogMildd.cs
+++ b/Blog.Core.Extensions/Middlewares/IPLogMildd.cs
@@ -1,5 +1,7 @@
using Blog.Core.Common;
+using Blog.Core.Common.Helper;
using Blog.Core.Common.LogHelper;
+using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Newtonsoft.Json;
using System;
@@ -17,13 +19,16 @@ public class IPLogMildd
///
///
private readonly RequestDelegate _next;
+ private readonly IWebHostEnvironment _environment;
+
///
///
///
///
- public IPLogMildd(RequestDelegate next)
+ public IPLogMildd(RequestDelegate next, IWebHostEnvironment environment)
{
_next = next;
+ _environment = environment;
}
public async Task InvokeAsync(HttpContext context)
@@ -53,11 +58,12 @@ public async Task InvokeAsync(HttpContext context)
// 自定义log输出
//Parallel.For(0, 1, e =>
//{
- // LogLock.OutSql2Log("RequestIpInfoLog", new string[] { requestInfo + "," }, false);
+ LogLock.OutSql2Log("RequestIpInfoLog", new string[] { requestInfo + "," }, false);
//});
// 这种方案也行,用的是Serilog
- SerilogServer.WriteLog("RequestIpInfoLog", new string[] { requestInfo + "," }, false);
+ var logFileName = FileHelper.GetAvailableFileNameWithPrefixOrderSize(_environment.ContentRootPath, "RequestIpInfoLog");
+ SerilogServer.WriteLog(logFileName, new string[] { requestInfo + "," }, false);
request.Body.Position = 0;
}
diff --git a/Blog.Core.Extensions/Middlewares/RecordAccessLogsMildd.cs b/Blog.Core.Extensions/Middlewares/RecordAccessLogsMildd.cs
index 7180b1a5..4174a459 100644
--- a/Blog.Core.Extensions/Middlewares/RecordAccessLogsMildd.cs
+++ b/Blog.Core.Extensions/Middlewares/RecordAccessLogsMildd.cs
@@ -1,6 +1,8 @@
using Blog.Core.Common;
+using Blog.Core.Common.Helper;
using Blog.Core.Common.HttpContextUser;
using Blog.Core.Common.LogHelper;
+using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
@@ -25,17 +27,19 @@ public class RecordAccessLogsMildd
private readonly RequestDelegate _next;
private readonly IUser _user;
private readonly ILogger _logger;
+ private readonly IWebHostEnvironment _environment;
private Stopwatch _stopwatch;
///
///
///
///
- public RecordAccessLogsMildd(RequestDelegate next, IUser user, ILogger logger)
+ public RecordAccessLogsMildd(RequestDelegate next, IUser user, ILogger logger, IWebHostEnvironment environment)
{
_next = next;
_user = user;
_logger = logger;
+ _environment = environment;
_stopwatch = new Stopwatch();
}
@@ -107,7 +111,9 @@ public async Task InvokeAsync(HttpContext context)
// LogLock.OutSql2Log("RecordAccessLogs", new string[] { requestInfo + "," }, false);
//});
- SerilogServer.WriteLog("RecordAccessLogs", new string[] { requestInfo + "," }, false);
+ var logFileName = FileHelper.GetAvailableFileNameWithPrefixOrderSize(_environment.ContentRootPath, "RecordAccessLogs");
+ SerilogServer.WriteLog(logFileName, new string[] { requestInfo + "," }, false);
+
return Task.CompletedTask;
});
From eb08af94b3d45fde0cc06d99f0394bd632a7dcf5 Mon Sep 17 00:00:00 2001
From: anjoy8 <3143422472@qq.com>
Date: Fri, 14 May 2021 21:10:56 +0800
Subject: [PATCH 017/456] Update SerilogServer.cs
---
Blog.Core.Common/LogHelper/Seri/SerilogServer.cs | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/Blog.Core.Common/LogHelper/Seri/SerilogServer.cs b/Blog.Core.Common/LogHelper/Seri/SerilogServer.cs
index 72dad73f..87c3e228 100644
--- a/Blog.Core.Common/LogHelper/Seri/SerilogServer.cs
+++ b/Blog.Core.Common/LogHelper/Seri/SerilogServer.cs
@@ -19,7 +19,7 @@ public static void WriteLog(string filename, string[] dataParas, bool IsHeader =
.MinimumLevel.Debug()
.MinimumLevel.Override("Microsoft", LogEventLevel.Error)
//.WriteTo.File(Path.Combine($"log/Serilog/{filename}/", ".log"), rollingInterval: RollingInterval.Day, outputTemplate: "{Timestamp:yyyy-MM-dd HH:mm:ss.fff} [{Level}] {Message}{NewLine}{Exception}")
- .WriteTo.File(Path.Combine("log", defaultFolder, $"{filename}.log"),
+ .WriteTo.File(Path.Combine("Log", defaultFolder, $"{filename}.log"),
rollingInterval: RollingInterval.Infinite,
outputTemplate: "{Message}{NewLine}{Exception}")
.CreateLogger();
From c1715afcb03b4d0f5116fe9c8d2fafc34c2f5699 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E6=96=8C=20=E6=9D=A8?=
Date: Fri, 21 May 2021 15:20:32 +0800
Subject: [PATCH 018/456] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=20=E4=BB=BB=E5=8A=A1?=
=?UTF-8?q?=20=E7=AB=8B=E5=8D=B3=E6=89=A7=E8=A1=8C=20=E7=9A=84=E5=8A=9F?=
=?UTF-8?q?=E8=83=BD?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../Controllers/TasksQzController.cs | 22 ++++++++++
Blog.Core.Tasks/QuartzNet/ISchedulerCenter.cs | 7 +++
.../QuartzNet/SchedulerCenterServer.cs | 44 +++++++++++++++++++
3 files changed, 73 insertions(+)
diff --git a/Blog.Core.Api/Controllers/TasksQzController.cs b/Blog.Core.Api/Controllers/TasksQzController.cs
index 04d63d08..ce87203d 100644
--- a/Blog.Core.Api/Controllers/TasksQzController.cs
+++ b/Blog.Core.Api/Controllers/TasksQzController.cs
@@ -501,6 +501,28 @@ public MessageModel> GetTaskNameSpace()
var implementTypes = types.Where(x => x.IsClass).Select(item => new QuartzReflectionViewModel { nameSpace = item.Namespace, nameClass = item.Name, remark = "" }).ToList();
return MessageModel>.Success("获取成功", implementTypes);
}
+
+ ///
+ /// 立即执行任务
+ ///
+ ///
+ ///
+ [HttpGet]
+ public async Task> ExecuteJob(string jobId)
+ {
+ var data = new MessageModel();
+
+ var model = await _tasksQzServices.QueryById(jobId);
+ if (model != null)
+ {
+ return await _schedulerCenter.ExecuteJobAsync(model);
+ }
+ else
+ {
+ data.msg = "任务不存在";
+ }
+ return data;
+ }
}
}
diff --git a/Blog.Core.Tasks/QuartzNet/ISchedulerCenter.cs b/Blog.Core.Tasks/QuartzNet/ISchedulerCenter.cs
index 63190392..c8598540 100644
--- a/Blog.Core.Tasks/QuartzNet/ISchedulerCenter.cs
+++ b/Blog.Core.Tasks/QuartzNet/ISchedulerCenter.cs
@@ -66,6 +66,13 @@ public interface ISchedulerCenter
///
string GetTriggerState(string key);
+ ///
+ /// 立即执行 一个任务
+ ///
+ ///
+ ///
+ Task> ExecuteJobAsync(TasksQz tasksQz);
+
}
}
diff --git a/Blog.Core.Tasks/QuartzNet/SchedulerCenterServer.cs b/Blog.Core.Tasks/QuartzNet/SchedulerCenterServer.cs
index 623f452b..93fa001a 100644
--- a/Blog.Core.Tasks/QuartzNet/SchedulerCenterServer.cs
+++ b/Blog.Core.Tasks/QuartzNet/SchedulerCenterServer.cs
@@ -443,5 +443,49 @@ private ITrigger CreateCronTrigger(TasksQz sysSchedule)
}
#endregion
+
+ ///
+ /// 立即执行 一个任务
+ ///
+ ///
+ ///
+ public async Task> ExecuteJobAsync(TasksQz tasksQz)
+ {
+ var result = new MessageModel();
+ try
+ {
+ JobKey jobKey = new JobKey(tasksQz.Id, tasksQz.JobGroup);
+
+ //判断任务是否存在,存在则 触发一次,不存在则先添加一个任务,触发以后再 停止任务
+ if (!await _scheduler.Result.CheckExists(jobKey))
+ {
+ //不存在 则 添加一个计划任务
+ await AddScheduleJobAsync(tasksQz);
+
+ //触发执行一次
+ await _scheduler.Result.TriggerJob(jobKey);
+
+ //停止任务
+ await StopScheduleJobAsync(tasksQz);
+
+ result.success = true;
+ result.msg = $"立即执行计划任务:【{tasksQz.Name}】成功";
+ }
+ else
+ {
+ await _scheduler.Result.TriggerJob(jobKey);
+ result.success = true;
+ result.msg = $"立即执行计划任务:【{tasksQz.Name}】成功";
+ }
+ }
+ catch (Exception ex)
+ {
+ result.msg = $"立即执行计划任务失败:【{ex.Message}】";
+ }
+
+ return result;
+ }
+
+
}
}
From 946888490c02009cf492f3fda714083862072dd6 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E6=96=8C=20=E6=9D=A8?=
Date: Fri, 21 May 2021 15:33:13 +0800
Subject: [PATCH 019/456] =?UTF-8?q?=E4=BF=AE=E6=94=B9=20=E4=BB=BB=E5=8A=A1?=
=?UTF-8?q?=20=E7=AB=8B=E5=8D=B3=E6=89=A7=E8=A1=8C=20Id=20=E4=B8=BAInt?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
Blog.Core.Api/Blog.Core.xml | 7 +++++++
Blog.Core.Api/Controllers/TasksQzController.cs | 2 +-
Blog.Core.Tasks/QuartzNet/SchedulerCenterServer.cs | 2 +-
3 files changed, 9 insertions(+), 2 deletions(-)
diff --git a/Blog.Core.Api/Blog.Core.xml b/Blog.Core.Api/Blog.Core.xml
index 648902ef..e22a3841 100644
--- a/Blog.Core.Api/Blog.Core.xml
+++ b/Blog.Core.Api/Blog.Core.xml
@@ -519,6 +519,13 @@
+
+
+ 立即执行任务
+
+
+
+
类别管理【无权限】
diff --git a/Blog.Core.Api/Controllers/TasksQzController.cs b/Blog.Core.Api/Controllers/TasksQzController.cs
index ce87203d..ba9b7355 100644
--- a/Blog.Core.Api/Controllers/TasksQzController.cs
+++ b/Blog.Core.Api/Controllers/TasksQzController.cs
@@ -508,7 +508,7 @@ public MessageModel> GetTaskNameSpace()
///
///
[HttpGet]
- public async Task> ExecuteJob(string jobId)
+ public async Task> ExecuteJob(int jobId)
{
var data = new MessageModel();
diff --git a/Blog.Core.Tasks/QuartzNet/SchedulerCenterServer.cs b/Blog.Core.Tasks/QuartzNet/SchedulerCenterServer.cs
index 93fa001a..8c21115c 100644
--- a/Blog.Core.Tasks/QuartzNet/SchedulerCenterServer.cs
+++ b/Blog.Core.Tasks/QuartzNet/SchedulerCenterServer.cs
@@ -454,7 +454,7 @@ public async Task> ExecuteJobAsync(TasksQz tasksQz)
var result = new MessageModel();
try
{
- JobKey jobKey = new JobKey(tasksQz.Id, tasksQz.JobGroup);
+ JobKey jobKey = new JobKey(tasksQz.Id.ToString(), tasksQz.JobGroup);
//判断任务是否存在,存在则 触发一次,不存在则先添加一个任务,触发以后再 停止任务
if (!await _scheduler.Result.CheckExists(jobKey))
From b4674f4ace1e000b4dd692cbf9b689e082d9a366 Mon Sep 17 00:00:00 2001
From: cuno92 <58431215+cuno92@users.noreply.github.com>
Date: Sat, 22 May 2021 04:56:58 +0000
Subject: [PATCH 020/456] Update English readme link
---
README.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/README.md b/README.md
index c5b54c93..9a42483d 100644
--- a/README.md
+++ b/README.md
@@ -2,7 +2,7 @@
# Blog.Core
-[English](readme-en.md) | 简体中文
+[English](README-en.md) | 简体中文
[](#) [](https://github.com/anjoy8/Blog.Core/actions) [](https://dev.azure.com/laozhangisphi/anjoy8/_build?definitionId=1) [](https://codecov.io/gh/anjoy8/Blog.Core) [](https://github.com/anjoy8/Blog.Core/blob/master/LICENSE) [](https://github.com/boennemann/badges) [](https://github.com/boennemann/badges/fork) [](https://www.cnblogs.com/laozhang-is-phi/)
From 346fbba46e346037f26506f1db1c067d04917db8 Mon Sep 17 00:00:00 2001
From: ansonzhang <3143422472@qq.com>
Date: Sat, 22 May 2021 13:22:49 +0800
Subject: [PATCH 021/456] Update README-en.md
---
README-en.md | 121 +++++++++++++++++++++++++++++++++++++--------------
1 file changed, 89 insertions(+), 32 deletions(-)
diff --git a/README-en.md b/README-en.md
index e4e7aa5c..e5961125 100644
--- a/README-en.md
+++ b/README-en.md
@@ -1,50 +1,107 @@
[ENGLISH](https://github.com/anjoy8/Blog.Core/blob/master/README-en.md) | [中文版](https://github.com/anjoy8/Blog.Core/blob/master/README.md)
-
-Build your own front and rear end separation from scratch ". NET Core2.1 Api + Vue 2.0" framework, currently version 2.2, each version see branch.
-It's just. Netcore back-end section, Front end section, see my other engineering vue
+[](#) [](https://github.com/anjoy8/Blog.Core/actions) [](https://dev.azure.com/laozhangisphi/anjoy8/_build?definitionId=1) [](https://codecov.io/gh/anjoy8/Blog.Core) [](https://github.com/anjoy8/Blog.Core/blob/master/LICENSE) [](https://github.com/boennemann/badges) [](https://github.com/boennemann/badges/fork) [](https://www.cnblogs.com/laozhang-is-phi/)
-Https://github.com/anjoy8/Blog.Vue
-# Give a star!⭐️
+
+
-If you like this project or it helps you, please give star~ (hard Star)
-*********************************************************
-# Tips:
-1. Blog.Core.FrameWork project is a simple implementation of generating files using T4 templates.
-If there is an error, you can contact me,
-QQ Group: 867095512
-If you don't want to deal with this error, you can uninstall the project first without affecting the overall operation.
+
+
+
+Blog.Core is an enterprise-class back-to-back separation framework for.NET Core5.0 API + Vue 2.x + RBAC.
+Website: http://apk.neters.club/.doc/
+Has been used by several companies: [click to view list] (https://github.com/anjoy8/Blog.Core/issues/75)
+
+Project single deployment, concurrent at 400~500, all normal (do not guarantee their own various error writing).
+The effect is even better if the load is matched.
+
+
+
+
+
+### Features and Progress
+
+Framework module:
+- [x] adopts the form of 'warehousing + service + interface' to encapsulate the framework;
+- [X] async/await development;
+- [x] access to domestic database ORM component - SQLSUGAR, encapsulate database operation;
+- [x] support free switching multiple database, MySql/used/Sqlite/Oracle/Postgresql/reach/NPC Jin Cang dreams;
+- [x] realize project startup, automatically generate seed data ✨;
+- [X] five types of logging, audit/exception/request response/service operation/SQL logging, etc.
+- [x] Support for project transaction processing (use CAP if you want to distribute) ✨;
+- [x] Design 4 types of AOP facets programming, including: logging, caching, auditing, transaction ✨;
+- [x] Support T4 code template, automatically generate code for each layer;
+- [x] or use DbFirst one key to create their own project four layer files (support multiple libraries);
+- [x] encapsulation ` Blog. Core. Webapi. Template ` project Template, a key ✨ rebuild their projects;
+- [x] with multiple front-end cases for reference and reference: blog.vue, blog.admin, nuxt.tbug, blog.mvp. Blazor ✨;
+- [x] Uniform Integrated IdentityServer4 Authentication ✨;
+
+Component module:
+- [x] provides Redis for caching;
+- [x] API file with Swagger;
+- [x] Use Miniprofiler for interface performance analysis ✨;
+- [x] uses Automapper to handle object mapping;
+- [x] uses Autofac as a dependency injection container and provides batch service injection ✨;
+- [x] supports CORS cross-domain;
+- [x] encapsulates JWT custom policy authorization;
+- [x] uses the Log4Net logging framework and integrates the native iLogger interface for logging;
+- [x] using Signalr duplex communication ✨;
+- [x] Added iprateLimiting for API current limiting;
+- [X] Use Quartz.net for task scheduling (currently single machine multi-task, cluster scheduling is not currently supported);
+- [x] Support for database 'read/write separation' and multi-library operations ✨;
+- [x] Added Redis Message Queuing ✨;
+- [x] new RabbitMQ message queue ✨;
+- [x] New EventBus ✨;
+- [x] Debugging - Unified Aggregate Payment;
+- [] Plan - Data department authority;
+-[] plan -es search;
+
+Micro service module:
+- [x] can cooperate with Docker to achieve containerization;
+- [x] can cooperate with Jenkins to achieve CI/CD;
+- [x] enables service discovery with Consul;
+- [x] can cooperate with Ocelot to achieve gateway processing;
+- [x] can cooperate with NGINX to achieve load balancing;
+- [x] can cooperate with IDS4 certification center;
+
+
+
+
+## Give a star! ⭐ ️
+If you like this project or it helps you, please send it to STAR ~
+If your project from the project, please explain a little bit down [https://github.com/anjoy8/Blog.Core/issues/75] (https://github.com/anjoy8/Blog.Core/issues/75), Open source is not easy ✨.
+
+
+
+
+
+## Official document 📕
+
+Still in the process of sorting out, but the basic operations, including how to get started, configure data, connect to DB, and so on
+
+[the official documentation] (http://apk.neters.club/.doc/)
+[Official account important articles + video address](https://mvp.neters.club/)
+
-2. when the project is executed after downloading, the Redis server needs to be installed, installation and use of the description address:
-https://www.cnblogs.com/laozhang-is-phi/p/9554210.html#autoid-5-0-0
-3. the system new automated Generation database, and the ability to generate seed data, In the Progrm.cs in the Blog.core layer, cancel the Dbseed.seedasync (mycontext). Wait ();
-The comment can be.
-4. If you do not want to use Codefirst and seed data, you can use the database table structure SQL file to execute in the database,
+
-In the Wwwroot folder under the Blog.core project.
-*********************************************************
-### Modify Database connection string
-1, in the Blog.Core.Repository layer under the Sugar folder under the BaseDBConfig.cs, configure their own strings
-```
-public static string connectionstring = File.exists (@ "D:my-filedbCountPsw1.txt")?
-File.readalltext (@ "D:my-filedbCountPsw1.txt"). Trim (): "server=.;
-Uid=sa;pwd=sa;database=blogdb ";
-```
-2, in the Blog.Core.FrameWork layer of the dbhelper.ttinclude, configure their own strings
-```
-public static readonly String connectionstring = File.exists (@ "D:my-filedbCountPsw2.txt")?
-File.readalltext (@ "D:my-filedbCountPsw2.txt"). Trim (): "server=.;
-Uid=sa;pwd=sa;database=blogdb ";
-```
*****************************************************
From d4728831fd6112260605f4d40c0e64c34f1606b6 Mon Sep 17 00:00:00 2001
From: ansonzhang <3143422472@qq.com>
Date: Sat, 22 May 2021 13:24:49 +0800
Subject: [PATCH 022/456] Update README-en.md
---
README-en.md | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/README-en.md b/README-en.md
index e5961125..01efd58b 100644
--- a/README-en.md
+++ b/README-en.md
@@ -66,8 +66,8 @@ Component module:
- [x] new RabbitMQ message queue ✨;
- [x] New EventBus ✨;
- [x] Debugging - Unified Aggregate Payment;
-- [] Plan - Data department authority;
--[] plan -es search;
+- [ ] Plan - Data department authority;
+- [ ] plan -es search;
Micro service module:
- [x] can cooperate with Docker to achieve containerization;
From 3bd69c3839d00d763994285b4bec367aaa3eb6b5 Mon Sep 17 00:00:00 2001
From: ansonzhang <3143422472@qq.com>
Date: Sat, 22 May 2021 13:26:25 +0800
Subject: [PATCH 023/456] Update README-en.md
---
README-en.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/README-en.md b/README-en.md
index 01efd58b..33d8a749 100644
--- a/README-en.md
+++ b/README-en.md
@@ -35,7 +35,7 @@ The effect is even better if the load is matched.
### Features and Progress
Framework module:
-- [x] adopts the form of 'warehousing + service + interface' to encapsulate the framework;
+- [x] adopts the form of 'repository + service + interface' to encapsulate the framework;
- [X] async/await development;
- [x] access to domestic database ORM component - SQLSUGAR, encapsulate database operation;
- [x] support free switching multiple database, MySql/used/Sqlite/Oracle/Postgresql/reach/NPC Jin Cang dreams;
From 7aae1c6d60eb11bf93dd3f19145b4bf4bb74896f Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E5=AE=81=E9=AA=91?= <1075858260@qq.com>
Date: Mon, 31 May 2021 15:16:04 +0800
Subject: [PATCH 024/456] =?UTF-8?q?=E5=8A=A0=E4=BA=86=E4=B8=AABase?=
=?UTF-8?q?=E6=8E=A7=E5=88=B6=E5=99=A8=EF=BC=8C=E5=B0=81=E8=A3=85=E4=BA=86?=
=?UTF-8?q?=E5=B8=B8=E7=94=A8=E7=9A=84=E8=BF=94=E5=9B=9E=EF=BC=8C=E5=87=8F?=
=?UTF-8?q?=E5=B0=91=E4=BB=A3=E7=A0=81=E9=87=8F?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../Controllers/BaseApiCpntroller.cs | 86 +++++++++++++
Blog.Core.Api/Controllers/BlogController.cs | 113 +++---------------
Blog.Core.Api/Controllers/LoginController.cs | 45 ++-----
3 files changed, 111 insertions(+), 133 deletions(-)
create mode 100644 Blog.Core.Api/Controllers/BaseApiCpntroller.cs
diff --git a/Blog.Core.Api/Controllers/BaseApiCpntroller.cs b/Blog.Core.Api/Controllers/BaseApiCpntroller.cs
new file mode 100644
index 00000000..d1de099a
--- /dev/null
+++ b/Blog.Core.Api/Controllers/BaseApiCpntroller.cs
@@ -0,0 +1,86 @@
+using Blog.Core.Model;
+using Microsoft.AspNetCore.Mvc;
+using System.Collections.Generic;
+
+namespace Blog.Core.Controllers
+{
+ public class BaseApiCpntroller : Controller
+ {
+
+ public MessageModel Success(T data, string msg = "成功")
+ {
+ return new MessageModel()
+ {
+ success = true,
+ msg = msg,
+ response = data,
+ };
+ }
+
+ public MessageModel Success(string msg = "成功")
+ {
+ return new MessageModel()
+ {
+ success = true,
+ msg = msg,
+ response = null,
+ };
+ }
+
+ public MessageModel Failed(string msg = "失败", int status = 500)
+ {
+ return new MessageModel()
+ {
+ success = false,
+ status = status,
+ msg = msg,
+ response = null,
+ };
+ }
+
+ public MessageModel Failed(string msg = "失败", int status = 500)
+ {
+ return new MessageModel()
+ {
+ success = false,
+ status = status,
+ msg = msg,
+ response = default,
+ };
+ }
+
+ public MessageModel> SuccessPage(int page, int dataCount, List data, int pageCount, string msg = "获取成功")
+ {
+
+ return new MessageModel>()
+ {
+ success = true,
+ msg = msg,
+ response = new PageModel()
+ {
+ page = page,
+ dataCount = dataCount,
+ data = data,
+ pageCount = pageCount,
+ }
+ };
+ }
+
+ public MessageModel> SuccessPage(PageModel pageModel, string msg = "获取成功")
+ {
+
+ return new MessageModel>()
+ {
+ success = true,
+ msg = msg,
+ response = new PageModel()
+ {
+ page = pageModel.page,
+ dataCount = pageModel.dataCount,
+ data = pageModel.data,
+ pageCount = pageModel.pageCount,
+ }
+ };
+ }
+ }
+}
diff --git a/Blog.Core.Api/Controllers/BlogController.cs b/Blog.Core.Api/Controllers/BlogController.cs
index f36249fd..0eed83d1 100644
--- a/Blog.Core.Api/Controllers/BlogController.cs
+++ b/Blog.Core.Api/Controllers/BlogController.cs
@@ -22,7 +22,7 @@ namespace Blog.Core.Controllers
///
[Produces("application/json")]
[Route("api/Blog")]
- public class BlogController : ControllerBase
+ public class BlogController : BaseApiCpntroller
{
public IBlogArticleServices _blogArticleServices { get; set; }
private readonly ILogger _logger;
@@ -56,7 +56,7 @@ public async Task>> Get(int id, int page = 1
}
Expression> whereExpression = a => (a.bcategory == bcategory && a.IsDeleted == false) && ((a.btitle != null && a.btitle.Contains(key)) || (a.bcontent != null && a.bcontent.Contains(key)));
-
+
var testId = await _blogArticleServices.GetBlogDetails(1);
var pageModelBlog = await _blogArticleServices.QueryPage(whereExpression, page, intPageSize, " bID desc ");
@@ -77,18 +77,7 @@ public async Task>> Get(int id, int page = 1
}
}
- return new MessageModel>()
- {
- success = true,
- msg = "获取成功",
- response = new PageModel()
- {
- page = page,
- dataCount = pageModelBlog.dataCount,
- data = pageModelBlog.data,
- pageCount = pageModelBlog.pageCount,
- }
- };
+ return SuccessPage(pageModelBlog);
}
@@ -102,12 +91,7 @@ public async Task>> Get(int id, int page = 1
[Authorize]
public async Task> Get(int id)
{
- return new MessageModel()
- {
- msg = "获取成功",
- success = true,
- response = await _blogArticleServices.GetBlogDetails(id)
- };
+ return Success(await _blogArticleServices.GetBlogDetails(id));
}
@@ -121,12 +105,7 @@ public async Task> Get(int id)
public async Task> DetailNuxtNoPer(int id)
{
_logger.LogInformation("xxxxxxxxxxxxxxxxxxx");
- return new MessageModel()
- {
- msg = "获取成功",
- success = true,
- response = await _blogArticleServices.GetBlogDetails(id)
- };
+ return Success(await _blogArticleServices.GetBlogDetails(id));
}
[HttpGet]
@@ -156,15 +135,9 @@ public async Task>> GetBlogsByTypesForMVP(string
if (types.IsNotEmptyOrNull())
{
var blogs = await _blogArticleServices.Query(d => d.bcategory != null && types.Contains(d.bcategory) && d.IsDeleted == false);
- return new MessageModel>()
- {
- msg = "获取成功",
- success = true,
- response = blogs
- };
+ return Success(blogs);
}
-
- return new MessageModel>() { };
+ return Success(new List() { });
}
[HttpGet]
@@ -173,15 +146,9 @@ public async Task> GetBlogByIdForMVP(int id = 0)
{
if (id > 0)
{
- return new MessageModel()
- {
- msg = "获取成功",
- success = true,
- response = await _blogArticleServices.QueryById(id)
- };
+ return Success(await _blogArticleServices.QueryById(id));
}
-
- return new MessageModel() { };
+ return Success(new BlogArticle());
}
///
@@ -198,12 +165,7 @@ public async Task> GetBlogByIdForMVP(int id = 0)
[CustomRoute(ApiVersions.V2, "Blogtest")]
public MessageModel V2_Blogtest()
{
- return new MessageModel()
- {
- msg = "获取成功",
- success = true,
- response = "我是第二版的博客信息"
- };
+ return Success("我是第二版的博客信息");
}
///
@@ -216,22 +178,12 @@ public MessageModel V2_Blogtest()
[Authorize]
public async Task> Post([FromBody] BlogArticle blogArticle)
{
- var data = new MessageModel();
-
blogArticle.bCreateTime = DateTime.Now;
blogArticle.bUpdateTime = DateTime.Now;
blogArticle.IsDeleted = false;
blogArticle.bcategory = "技术博文";
-
var id = (await _blogArticleServices.Add(blogArticle));
- data.success = id > 0;
- if (data.success)
- {
- data.response = id.ObjToString();
- data.msg = "添加成功";
- }
-
- return data;
+ return id > 0 ? Success(id.ObjToString()) : Failed("添加失败");
}
@@ -245,21 +197,11 @@ public async Task> Post([FromBody] BlogArticle blogArticle)
[Authorize(Permissions.Name)]
public async Task> AddForMVP([FromBody] BlogArticle blogArticle)
{
- var data = new MessageModel();
-
blogArticle.bCreateTime = DateTime.Now;
blogArticle.bUpdateTime = DateTime.Now;
blogArticle.IsDeleted = false;
-
var id = (await _blogArticleServices.Add(blogArticle));
- data.success = id > 0;
- if (data.success)
- {
- data.response = id.ObjToString();
- data.msg = "添加成功";
- }
-
- return data;
+ return id > 0 ? Success(id.ObjToString()) : Failed("添加失败");
}
///
/// 更新博客信息
@@ -272,7 +214,6 @@ public async Task> AddForMVP([FromBody] BlogArticle blogArt
[Authorize(Permissions.Name)]
public async Task> Put([FromBody] BlogArticle BlogArticle)
{
- var data = new MessageModel();
if (BlogArticle != null && BlogArticle.bID > 0)
{
var model = await _blogArticleServices.QueryById(BlogArticle.bID);
@@ -285,17 +226,11 @@ public async Task> Put([FromBody] BlogArticle BlogArticle)
model.bcontent = BlogArticle.bcontent;
model.btraffic = BlogArticle.btraffic;
- data.success = await _blogArticleServices.Update(model);
- if (data.success)
- {
- data.msg = "更新成功";
- data.response = BlogArticle?.bID.ObjToString();
- }
+ if (await _blogArticleServices.Update(model))
+ Success(BlogArticle?.bID.ObjToString());
}
-
}
-
- return data;
+ return Failed("更新失败");
}
@@ -310,20 +245,13 @@ public async Task> Put([FromBody] BlogArticle BlogArticle)
[Route("Delete")]
public async Task> Delete(int id)
{
- var data = new MessageModel();
if (id > 0)
{
var blogArticle = await _blogArticleServices.QueryById(id);
blogArticle.IsDeleted = true;
- data.success = await _blogArticleServices.Update(blogArticle);
- if (data.success)
- {
- data.msg = "删除成功";
- data.response = blogArticle?.bID.ObjToString();
- }
+ return await _blogArticleServices.Update(blogArticle) ? Success(blogArticle?.bID.ObjToString(), "删除成功") : Failed("删除失败");
}
-
- return data;
+ return Failed("入参无效");
}
///
/// apache jemeter 压力测试
@@ -334,12 +262,7 @@ public async Task> Delete(int id)
[Route("ApacheTestUpdate")]
public async Task> ApacheTestUpdate()
{
- return new MessageModel()
- {
- success = true,
- msg = "更新成功",
- response = await _blogArticleServices.Update(new { bsubmitter = $"laozhang{DateTime.Now.Millisecond}", bID = 1 })
- };
+ return Success(await _blogArticleServices.Update(new { bsubmitter = $"laozhang{DateTime.Now.Millisecond}", bID = 1 }), "更新成功");
}
}
}
\ No newline at end of file
diff --git a/Blog.Core.Api/Controllers/LoginController.cs b/Blog.Core.Api/Controllers/LoginController.cs
index 67cb4cad..686c6431 100644
--- a/Blog.Core.Api/Controllers/LoginController.cs
+++ b/Blog.Core.Api/Controllers/LoginController.cs
@@ -23,7 +23,7 @@ namespace Blog.Core.Controllers
[Produces("application/json")]
[Route("api/Login")]
[AllowAnonymous]
- public class LoginController : Controller
+ public class LoginController : BaseApiCpntroller
{
readonly ISysUserInfoServices _sysUserInfoServices;
readonly IUserRoleServices _userRoleServices;
@@ -146,13 +146,7 @@ public async Task> GetJwtToken3(string name = "
string jwtStr = string.Empty;
if (string.IsNullOrEmpty(name) || string.IsNullOrEmpty(pass))
- {
- return new MessageModel()
- {
- success = false,
- msg = "用户名或密码不能为空",
- };
- }
+ return Failed("用户名或密码不能为空");
pass = MD5Helper.MD5Encrypt32(pass);
@@ -186,20 +180,11 @@ orderby item.Id
}
var token = JwtToken.BuildJwtToken(claims.ToArray(), _requirement);
- return new MessageModel()
- {
- success = true,
- msg = "获取成功",
- response = token
- };
+ return Success(token, "获取成功");
}
else
{
- return new MessageModel()
- {
- success = false,
- msg = "认证失败",
- };
+ return Failed("认证失败");
}
}
@@ -215,13 +200,7 @@ public async Task> RefreshToken(string token =
string jwtStr = string.Empty;
if (string.IsNullOrEmpty(token))
- {
- return new MessageModel()
- {
- success = false,
- msg = "token无效,请重新登录!",
- };
- }
+ return Failed("token无效,请重新登录!");
var tokenModel = JwtHelper.SerializeJwt(token);
if (tokenModel != null && tokenModel.Uid > 0)
{
@@ -241,20 +220,10 @@ public async Task> RefreshToken(string token =
identity.AddClaims(claims);
var refreshToken = JwtToken.BuildJwtToken(claims.ToArray(), _requirement);
- return new MessageModel()
- {
- success = true,
- msg = "获取成功",
- response = refreshToken
- };
+ return Success(refreshToken, "获取成功");
}
}
-
- return new MessageModel()
- {
- success = false,
- msg = "认证失败!",
- };
+ return Failed("认证失败!");
}
///
From 2b0e432e09982b4ca7707e86f9b11a25f4c3fa0c Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E5=AE=81=E9=AA=91?= <1075858260@qq.com>
Date: Mon, 31 May 2021 15:19:03 +0800
Subject: [PATCH 025/456] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E5=A4=9A=E4=B8=80?=
=?UTF-8?q?=E4=B8=AA=E9=9D=9E=E6=B3=9B=E5=9E=8B=E7=9A=84MessageModel?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
Blog.Core.Model/MessageModel.cs | 20 ++++++++++++++++++++
1 file changed, 20 insertions(+)
diff --git a/Blog.Core.Model/MessageModel.cs b/Blog.Core.Model/MessageModel.cs
index 5fa7f091..09b85360 100644
--- a/Blog.Core.Model/MessageModel.cs
+++ b/Blog.Core.Model/MessageModel.cs
@@ -71,4 +71,24 @@ public static MessageModel Message(bool success,string msg, T response )
return new MessageModel() { msg = msg, response = response, success = success };
}
}
+
+ public class MessageModel
+ {
+ ///
+ /// 状态码
+ ///
+ public int status { get; set; } = 200;
+ ///
+ /// 操作是否成功
+ ///
+ public bool success { get; set; } = false;
+ ///
+ /// 返回信息
+ ///
+ public string msg { get; set; } = "";
+ ///
+ /// 返回数据集合
+ ///
+ public object response { get; set; }
+ }
}
From aeba197ce3b52e3686f363873a5b764cd250e03e Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E5=AE=81=E9=AA=91?= <1075858260@qq.com>
Date: Mon, 31 May 2021 15:22:17 +0800
Subject: [PATCH 026/456] =?UTF-8?q?=E5=8A=A0=E4=B8=8ANoAction?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
Blog.Core.Api/Controllers/BaseApiCpntroller.cs | 12 ++++++------
1 file changed, 6 insertions(+), 6 deletions(-)
diff --git a/Blog.Core.Api/Controllers/BaseApiCpntroller.cs b/Blog.Core.Api/Controllers/BaseApiCpntroller.cs
index d1de099a..92f9db16 100644
--- a/Blog.Core.Api/Controllers/BaseApiCpntroller.cs
+++ b/Blog.Core.Api/Controllers/BaseApiCpntroller.cs
@@ -6,7 +6,7 @@ namespace Blog.Core.Controllers
{
public class BaseApiCpntroller : Controller
{
-
+ [NonAction]
public MessageModel Success(T data, string msg = "成功")
{
return new MessageModel()
@@ -16,7 +16,7 @@ public MessageModel Success(T data, string msg = "成功")
response = data,
};
}
-
+ [NonAction]
public MessageModel Success(string msg = "成功")
{
return new MessageModel()
@@ -26,7 +26,7 @@ public MessageModel Success(string msg = "成功")
response = null,
};
}
-
+ [NonAction]
public MessageModel Failed(string msg = "失败", int status = 500)
{
return new MessageModel()
@@ -37,7 +37,7 @@ public MessageModel Failed(string msg = "失败", int status = 500)
response = null,
};
}
-
+ [NonAction]
public MessageModel Failed(string msg = "失败", int status = 500)
{
return new MessageModel()
@@ -48,7 +48,7 @@ public MessageModel Failed(string msg = "失败", int status = 500)
response = default,
};
}
-
+ [NonAction]
public MessageModel> SuccessPage(int page, int dataCount, List data, int pageCount, string msg = "获取成功")
{
@@ -65,7 +65,7 @@ public MessageModel> SuccessPage(int page, int dataCount, List> SuccessPage(PageModel pageModel, string msg = "获取成功")
{
From a5779b801990deae5da870aab1f8f8ba40b8b087 Mon Sep 17 00:00:00 2001
From: anjoy8 <3143422472@qq.com>
Date: Mon, 31 May 2021 18:53:44 +0800
Subject: [PATCH 027/456] config es from serilog
---
Blog.Core.Api/Blog.Core.Model.xml | 20 +++++++++++++++++++
Blog.Core.Common/Blog.Core.Common.csproj | 1 +
.../LogHelper/Seri/SerilogServer.cs | 10 ++++++++++
3 files changed, 31 insertions(+)
diff --git a/Blog.Core.Api/Blog.Core.Model.xml b/Blog.Core.Api/Blog.Core.Model.xml
index 442aff26..ce6dd052 100644
--- a/Blog.Core.Api/Blog.Core.Model.xml
+++ b/Blog.Core.Api/Blog.Core.Model.xml
@@ -140,6 +140,26 @@
数据
+
+
+ 状态码
+
+
+
+
+ 操作是否成功
+
+
+
+
+ 返回信息
+
+
+
+
+ 返回数据集合
+
+
广告图片
diff --git a/Blog.Core.Common/Blog.Core.Common.csproj b/Blog.Core.Common/Blog.Core.Common.csproj
index 55259308..92af0184 100644
--- a/Blog.Core.Common/Blog.Core.Common.csproj
+++ b/Blog.Core.Common/Blog.Core.Common.csproj
@@ -16,6 +16,7 @@
+
diff --git a/Blog.Core.Common/LogHelper/Seri/SerilogServer.cs b/Blog.Core.Common/LogHelper/Seri/SerilogServer.cs
index 87c3e228..36d88c23 100644
--- a/Blog.Core.Common/LogHelper/Seri/SerilogServer.cs
+++ b/Blog.Core.Common/LogHelper/Seri/SerilogServer.cs
@@ -1,5 +1,6 @@
using Serilog;
using Serilog.Events;
+using Serilog.Sinks.Elasticsearch;
using System;
using System.IO;
@@ -22,6 +23,15 @@ public static void WriteLog(string filename, string[] dataParas, bool IsHeader =
.WriteTo.File(Path.Combine("Log", defaultFolder, $"{filename}.log"),
rollingInterval: RollingInterval.Infinite,
outputTemplate: "{Message}{NewLine}{Exception}")
+
+ // 将日志托送到远程ES
+ // docker run -p 9200:9200 -p 9300:9300 -e "discovery.type=single-node" -e ES_JAVA_OPTS="-Xms256m -Xmx256m" -d --name ES01 elasticsearch:7.2.0
+ //.Enrich.FromLogContext()
+ //.WriteTo.Elasticsearch(new ElasticsearchSinkOptions(new Uri("http://x.xxx.xx.xx:9200/"))
+ //{
+ // AutoRegisterTemplate = true,
+ //})
+
.CreateLogger();
var now = DateTime.Now;
From 9fdd250a45d3a90ebaf24c8c2354d922237bac31 Mon Sep 17 00:00:00 2001
From: wuare
Date: Tue, 1 Jun 2021 11:08:27 +0800
Subject: [PATCH 028/456] clean up code and formatting
---
Blog.Core.Common/Helper/StringHelper.cs | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/Blog.Core.Common/Helper/StringHelper.cs b/Blog.Core.Common/Helper/StringHelper.cs
index 4c9683e6..e77a2ef6 100644
--- a/Blog.Core.Common/Helper/StringHelper.cs
+++ b/Blog.Core.Common/Helper/StringHelper.cs
@@ -83,9 +83,9 @@ public static long GetGuidToLongID()
///
///
///
- public static string GetCusLine(string resourceStr,int length) {
+ public static string GetCusLine(string resourceStr, int length) {
string[] arrStr = resourceStr.Split("\r\n");
- return string.Join("", (from q in arrStr select q).Skip(arrStr.Length - length+1).Take(length).ToArray());
+ return string.Join("", (from q in arrStr select q).Skip(arrStr.Length - length + 1).Take(length).ToArray());
}
}
From 5bb969e1b956ec16beb0c7d21059f00ca1066ffd Mon Sep 17 00:00:00 2001
From: wuare
Date: Tue, 1 Jun 2021 11:31:55 +0800
Subject: [PATCH 029/456] fix typo and remove not needed null check
---
Blog.Core.Common/Helper/UrlHelper.cs | 2 +-
Blog.Core.Common/Helper/UtilConvert.cs | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/Blog.Core.Common/Helper/UrlHelper.cs b/Blog.Core.Common/Helper/UrlHelper.cs
index 6f54acc7..2814ec67 100644
--- a/Blog.Core.Common/Helper/UrlHelper.cs
+++ b/Blog.Core.Common/Helper/UrlHelper.cs
@@ -5,7 +5,7 @@ public class UrlHelper
///
/// UrlEncode编码
///
- /// url
+ /// url
///
public static string UrlEncode(string url) {
return System.Web.HttpUtility.UrlEncode(url, System.Text.Encoding.UTF8);
diff --git a/Blog.Core.Common/Helper/UtilConvert.cs b/Blog.Core.Common/Helper/UtilConvert.cs
index 0d1b8ee5..636e7099 100644
--- a/Blog.Core.Common/Helper/UtilConvert.cs
+++ b/Blog.Core.Common/Helper/UtilConvert.cs
@@ -15,7 +15,7 @@ public static int ObjToInt(this object thisValue)
{
int reval = 0;
if (thisValue == null) return 0;
- if (thisValue != null && thisValue != DBNull.Value && int.TryParse(thisValue.ToString(), out reval))
+ if (thisValue != DBNull.Value && int.TryParse(thisValue.ToString(), out reval))
{
return reval;
}
From 711f92d1e6d1dd1b9d6625bcaf0f9cf1f4e4bcbf Mon Sep 17 00:00:00 2001
From: anjoy8 <3143422472@qq.com>
Date: Tue, 1 Jun 2021 11:40:30 +0800
Subject: [PATCH 030/456] Resolve data anomalies in trend charts
---
.../Controllers/MonitorController.cs | 41 ++++++-------------
Blog.Core.Common/LogHelper/LogLock.cs | 10 ++++-
.../Middlewares/IPLogMildd.cs | 2 +-
3 files changed, 22 insertions(+), 31 deletions(-)
diff --git a/Blog.Core.Api/Controllers/MonitorController.cs b/Blog.Core.Api/Controllers/MonitorController.cs
index d3972639..b06af190 100644
--- a/Blog.Core.Api/Controllers/MonitorController.cs
+++ b/Blog.Core.Api/Controllers/MonitorController.cs
@@ -26,7 +26,7 @@ namespace Blog.Core.Controllers
[Route("api/[Controller]/[action]")]
[ApiController]
[AllowAnonymous]
- public class MonitorController : Controller
+ public class MonitorController : BaseApiCpntroller
{
private readonly IHubContext _hubContext;
private readonly IWebHostEnvironment _env;
@@ -48,21 +48,16 @@ public MonitorController(IHubContext hubContext, IWebHostEnvironment en
[HttpGet]
public MessageModel Server()
{
- return new MessageModel()
+ return Success(new ServerViewModel()
{
- msg = "获取成功",
- success = true,
- response = new ServerViewModel()
- {
- EnvironmentName = _env.EnvironmentName,
- OSArchitecture = RuntimeInformation.OSArchitecture.ObjToString(),
- ContentRootPath = _env.ContentRootPath,
- WebRootPath = _env.WebRootPath,
- FrameworkDescription = RuntimeInformation.FrameworkDescription,
- MemoryFootprint = (Process.GetCurrentProcess().WorkingSet64 / 1048576).ToString("N2") + " MB",
- WorkingTime = DateHelper.TimeSubTract(DateTime.Now, Process.GetCurrentProcess().StartTime)
- }
- };
+ EnvironmentName = _env.EnvironmentName,
+ OSArchitecture = RuntimeInformation.OSArchitecture.ObjToString(),
+ ContentRootPath = _env.ContentRootPath,
+ WebRootPath = _env.WebRootPath,
+ FrameworkDescription = RuntimeInformation.FrameworkDescription,
+ MemoryFootprint = (Process.GetCurrentProcess().WorkingSet64 / 1048576).ToString("N2") + " MB",
+ WorkingTime = DateHelper.TimeSubTract(DateTime.Now, Process.GetCurrentProcess().StartTime)
+ });
}
@@ -77,12 +72,7 @@ public MessageModel> Get()
_hubContext.Clients.All.SendAsync("ReceiveUpdate", LogLock.GetLogData()).Wait();
- return new MessageModel>()
- {
- msg = "获取成功",
- success = true,
- response = null
- };
+ return Success>(null);
}
@@ -90,12 +80,7 @@ public MessageModel> Get()
[HttpGet]
public MessageModel GetRequestApiinfoByWeek()
{
- return new MessageModel()
- {
- msg = "获取成功",
- success = true,
- response = LogLock.RequestApiinfoByWeek()
- };
+ return Success(LogLock.RequestApiinfoByWeek());
}
[HttpGet]
@@ -121,7 +106,7 @@ public MessageModel GetAccessApiByHour()
}
[HttpGet]
- public MessageModel GetActiveUsers([FromServices]IWebHostEnvironment environment)
+ public MessageModel GetActiveUsers([FromServices] IWebHostEnvironment environment)
{
var accessLogsToday = JsonConvert.DeserializeObject>("[" + LogLock.ReadLog(
Path.Combine(environment.ContentRootPath, "Log"), "RecordAccessLogs_", Encoding.UTF8, ReadType.PrefixLatest
diff --git a/Blog.Core.Common/LogHelper/LogLock.cs b/Blog.Core.Common/LogHelper/LogLock.cs
index deb40e96..adeb0e11 100644
--- a/Blog.Core.Common/LogHelper/LogLock.cs
+++ b/Blog.Core.Common/LogHelper/LogLock.cs
@@ -318,11 +318,17 @@ public static RequestApiWeekView RequestApiinfoByWeek()
jsonBuilder.Append(item.count);
jsonBuilder.Append("\",");
}
- jsonBuilder.Remove(jsonBuilder.Length - 1, 1);
+ if (apiweeksCurrentWeek.Count > 0)
+ {
+ jsonBuilder.Remove(jsonBuilder.Length - 1, 1);
+ }
jsonBuilder.Append("},");
}
- jsonBuilder.Remove(jsonBuilder.Length - 1, 1);
+ if (weeks.Count > 0)
+ {
+ jsonBuilder.Remove(jsonBuilder.Length - 1, 1);
+ }
jsonBuilder.Append("]");
//columns.AddRange(apiWeeks.OrderByDescending(d => d.count).Take(8).Select(d => d.url).ToList());
diff --git a/Blog.Core.Extensions/Middlewares/IPLogMildd.cs b/Blog.Core.Extensions/Middlewares/IPLogMildd.cs
index aa5c4265..8716db96 100644
--- a/Blog.Core.Extensions/Middlewares/IPLogMildd.cs
+++ b/Blog.Core.Extensions/Middlewares/IPLogMildd.cs
@@ -58,7 +58,7 @@ public async Task InvokeAsync(HttpContext context)
// 自定义log输出
//Parallel.For(0, 1, e =>
//{
- LogLock.OutSql2Log("RequestIpInfoLog", new string[] { requestInfo + "," }, false);
+ // LogLock.OutSql2Log("RequestIpInfoLog", new string[] { requestInfo + "," }, false);
//});
// 这种方案也行,用的是Serilog
From 90858c46decefa42d147eb97a5ccd2eb67300946 Mon Sep 17 00:00:00 2001
From: wuare
Date: Tue, 1 Jun 2021 12:21:55 +0800
Subject: [PATCH 031/456] use string interpolation expression
---
Blog.Core.Extensions/AOP/CacheAOPbase.cs | 14 +++++++-------
1 file changed, 7 insertions(+), 7 deletions(-)
diff --git a/Blog.Core.Extensions/AOP/CacheAOPbase.cs b/Blog.Core.Extensions/AOP/CacheAOPbase.cs
index fb19e144..04791830 100644
--- a/Blog.Core.Extensions/AOP/CacheAOPbase.cs
+++ b/Blog.Core.Extensions/AOP/CacheAOPbase.cs
@@ -44,7 +44,7 @@ protected string CustomCacheKey(IInvocation invocation)
///
protected static string GetArgumentValue(object arg)
{
- if (arg is DateTime || arg is DateTime?)
+ if (arg is DateTime)
return ((DateTime)arg).ToString("yyyyMMddHHmmss");
if (!arg.IsNotEmptyOrNull())
@@ -108,7 +108,7 @@ private static string GetOperator(ExpressionType expressiontype)
case ExpressionType.GreaterThanOrEqual:
return ">=";
default:
- throw new Exception(string.Format("不支持{0}此种运算符查找!" + expressiontype));
+ throw new Exception($"不支持{expressiontype}此种运算符查找!");
}
}
@@ -135,7 +135,7 @@ private static string ResolveLinqToObject(Expression expression, object value, E
case "LongCount":
return Len(MethodCall, value, expressiontype.Value);
default:
- throw new Exception(string.Format("不支持{0}方法的查找!", MethodName));
+ throw new Exception($"不支持{MethodName}方法的查找!");
}
}
@@ -155,7 +155,7 @@ private static string In(MethodCallExpression expression, object isTrue)
string Name = Argument2.Member.Name;
string Operator = Convert.ToBoolean(isTrue) ? "in" : " not in";
string CompName = string.Join(",", SetInPara);
- string Result = string.Format("{0} {1} ({2})", Name, Operator, CompName);
+ string Result = $"{Name} {Operator} ({CompName})";
return Result;
}
private static string Like(MethodCallExpression expression)
@@ -165,9 +165,9 @@ private static string Like(MethodCallExpression expression)
LambdaExpression lambda = Expression.Lambda(Temp);
Delegate fn = lambda.Compile();
var tempValue = Expression.Constant(fn.DynamicInvoke(null), Temp.Type);
- string Value = string.Format("%{0}%", tempValue);
+ string Value = $"%{tempValue}%";
string Name = (expression.Object as MemberExpression).Member.Name;
- string Result = string.Format("{0} like {1}", Name, Value);
+ string Result = $"{Name} like {Value}";
return Result;
}
@@ -176,7 +176,7 @@ private static string Len(MethodCallExpression expression, object value, Express
{
object Name = (expression.Arguments[0] as MemberExpression).Member.Name;
string Operator = GetOperator(expressiontype);
- string Result = string.Format("len({0}){1}{2}", Name, Operator, value.ToString());
+ string Result = $"len({Name}){Operator}{value.ToString()}";
return Result;
}
From b2ccdd84260836d738d1218b56fa9ac368efe292 Mon Sep 17 00:00:00 2001
From: wuare
Date: Tue, 1 Jun 2021 13:51:55 +0800
Subject: [PATCH 032/456] remove unused param tag
---
Blog.Core.Extensions/Redis/RedisBasketRepository.cs | 1 -
Blog.Core.Repository/BASE/BaseRepository.cs | 2 --
Blog.Core.Repository/MongoRepository/MongoDbContext.cs | 3 +--
Blog.Core.Services/BASE/BaseServices.cs | 2 --
Blog.Core.Services/BlogArticleServices.cs | 1 -
5 files changed, 1 insertion(+), 8 deletions(-)
diff --git a/Blog.Core.Extensions/Redis/RedisBasketRepository.cs b/Blog.Core.Extensions/Redis/RedisBasketRepository.cs
index 0057868e..02809bcb 100644
--- a/Blog.Core.Extensions/Redis/RedisBasketRepository.cs
+++ b/Blog.Core.Extensions/Redis/RedisBasketRepository.cs
@@ -154,7 +154,6 @@ public async Task ListRightPopAsync(string redisKey, int db = -1) where T
///
/// 移除并返回存储在该键列表的第一个元素
///
- ///
///
///
///
diff --git a/Blog.Core.Repository/BASE/BaseRepository.cs b/Blog.Core.Repository/BASE/BaseRepository.cs
index ecbcd814..55fd0e11 100644
--- a/Blog.Core.Repository/BASE/BaseRepository.cs
+++ b/Blog.Core.Repository/BASE/BaseRepository.cs
@@ -403,7 +403,6 @@ public async Task QueryTable(string strSql, SugarParameter[] paramete
/// 条件表达式
/// 页码(下标0)
/// 页大小
- /// 数据总量
/// 排序字段,如name asc,age desc
/// 数据列表
public async Task> Query(
@@ -423,7 +422,6 @@ public async Task> Query(
/// 条件
/// 页码(下标0)
/// 页大小
- /// 数据总量
/// 排序字段,如name asc,age desc
/// 数据列表
public async Task> Query(
diff --git a/Blog.Core.Repository/MongoRepository/MongoDbContext.cs b/Blog.Core.Repository/MongoRepository/MongoDbContext.cs
index f6a0d274..29357fec 100644
--- a/Blog.Core.Repository/MongoRepository/MongoDbContext.cs
+++ b/Blog.Core.Repository/MongoRepository/MongoDbContext.cs
@@ -12,8 +12,7 @@ public class MongoDbContext
public MongoDbContext()
{
var client = new MongoClient(Appsettings.app(new string[] { "Mongo", "ConnectionString" }));
- if (client != null)
- _database = client.GetDatabase(Appsettings.app(new string[] { "Mongo", "Database" }));
+ _database = client.GetDatabase(Appsettings.app(new string[] { "Mongo", "Database" }));
}
public IMongoDatabase Db
diff --git a/Blog.Core.Services/BASE/BaseServices.cs b/Blog.Core.Services/BASE/BaseServices.cs
index ebde1bf7..ba553082 100644
--- a/Blog.Core.Services/BASE/BaseServices.cs
+++ b/Blog.Core.Services/BASE/BaseServices.cs
@@ -269,7 +269,6 @@ public async Task> Query(
/// 条件表达式
/// 页码(下标0)
/// 页大小
- /// 数据总量
/// 排序字段,如name asc,age desc
/// 数据列表
public async Task> Query(
@@ -292,7 +291,6 @@ public async Task> Query(
/// 条件
/// 页码(下标0)
/// 页大小
- /// 数据总量
/// 排序字段,如name asc,age desc
/// 数据列表
public async Task> Query(
diff --git a/Blog.Core.Services/BlogArticleServices.cs b/Blog.Core.Services/BlogArticleServices.cs
index 512f4fbd..f04de9a1 100644
--- a/Blog.Core.Services/BlogArticleServices.cs
+++ b/Blog.Core.Services/BlogArticleServices.cs
@@ -63,7 +63,6 @@ public async Task GetBlogDetails(int id)
///
/// 获取博客列表
///
- ///
///
[Caching(AbsoluteExpiration = 10)]
public async Task> GetBlogs()
From 5c6260766e5ff59aec8158f1218368ddf77fc74f Mon Sep 17 00:00:00 2001
From: wuare
Date: Wed, 2 Jun 2021 10:33:02 +0800
Subject: [PATCH 033/456] Remove unused param tag
---
Blog.Core.Services/BlogArticleServices.cs | 1 -
1 file changed, 1 deletion(-)
diff --git a/Blog.Core.Services/BlogArticleServices.cs b/Blog.Core.Services/BlogArticleServices.cs
index 512f4fbd..f04de9a1 100644
--- a/Blog.Core.Services/BlogArticleServices.cs
+++ b/Blog.Core.Services/BlogArticleServices.cs
@@ -63,7 +63,6 @@ public async Task GetBlogDetails(int id)
///
/// 获取博客列表
///
- ///
///
[Caching(AbsoluteExpiration = 10)]
public async Task> GetBlogs()
From ec89745efcab8043588866fa2dcdeae304f797ce Mon Sep 17 00:00:00 2001
From: wuare
Date: Wed, 2 Jun 2021 10:57:30 +0800
Subject: [PATCH 034/456] Remove not needed null check
return string.Empty if there is no ContentEncoding, so encoding never be null, condition is always true
---
Blog.Core.Common/Helper/HttpHelper.cs | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/Blog.Core.Common/Helper/HttpHelper.cs b/Blog.Core.Common/Helper/HttpHelper.cs
index dd666c9b..54d56613 100644
--- a/Blog.Core.Common/Helper/HttpHelper.cs
+++ b/Blog.Core.Common/Helper/HttpHelper.cs
@@ -50,7 +50,7 @@ public static string Post(string serviceAddress, string strContent = null)
}
HttpWebResponse response = (HttpWebResponse)request.GetResponse();
string encoding = response.ContentEncoding;
- if (encoding == null || encoding.Length < 1)
+ if (encoding.Length < 1)
{
encoding = "UTF-8"; //默认编码
}
@@ -75,7 +75,7 @@ public static async Task PostAsync(string serviceAddress, string strCont
}
HttpWebResponse response = (HttpWebResponse)request.GetResponse();
string encoding = response.ContentEncoding;
- if (encoding == null || encoding.Length < 1)
+ if (encoding.Length < 1)
{
encoding = "UTF-8"; //默认编码
}
From 700b70373b7cdff59566bcd180659371ab121b02 Mon Sep 17 00:00:00 2001
From: anjoy8 <3143422472@qq.com>
Date: Fri, 4 Jun 2021 19:28:44 +0800
Subject: [PATCH 035/456] =?UTF-8?q?feat=EF=BC=9Aout=20sql=20log=20to=20con?=
=?UTF-8?q?sole?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
Blog.Core.Api/Blog.Core.xml | 4 +--
Blog.Core.Api/Controllers/BlogController.cs | 6 ++--
Blog.Core.Api/appsettings.json | 8 +++++-
Blog.Core.Common/Helper/ConsoleHelper.cs | 2 +-
.../ServiceExtensions/AppConfigSetup.cs | 16 +++++++++--
.../ServiceExtensions/SqlsugarSetup.cs | 28 +++++++++++++++----
.../Controller_Test/BlogController_Should.cs | 2 +-
Blog.Core.Tests/appsettings.json | 8 +++++-
8 files changed, 56 insertions(+), 18 deletions(-)
diff --git a/Blog.Core.Api/Blog.Core.xml b/Blog.Core.Api/Blog.Core.xml
index e22a3841..a510a92a 100644
--- a/Blog.Core.Api/Blog.Core.xml
+++ b/Blog.Core.Api/Blog.Core.xml
@@ -9,12 +9,12 @@
博客管理
-
+
构造函数
-
+
diff --git a/Blog.Core.Api/Controllers/BlogController.cs b/Blog.Core.Api/Controllers/BlogController.cs
index 0eed83d1..a7841874 100644
--- a/Blog.Core.Api/Controllers/BlogController.cs
+++ b/Blog.Core.Api/Controllers/BlogController.cs
@@ -30,9 +30,9 @@ public class BlogController : BaseApiCpntroller
///
/// 构造函数
///
- ///
///
- public BlogController(IBlogArticleServices blogArticleServices, ILogger logger)
+ ///
+ public BlogController(ILogger logger)
{
_logger = logger;
}
@@ -57,8 +57,6 @@ public async Task>> Get(int id, int page = 1
Expression> whereExpression = a => (a.bcategory == bcategory && a.IsDeleted == false) && ((a.btitle != null && a.btitle.Contains(key)) || (a.bcontent != null && a.bcontent.Contains(key)));
- var testId = await _blogArticleServices.GetBlogDetails(1);
-
var pageModelBlog = await _blogArticleServices.QueryPage(whereExpression, page, intPageSize, " bID desc ");
using (MiniProfiler.Current.Step("获取成功后,开始处理最终数据"))
diff --git a/Blog.Core.Api/appsettings.json b/Blog.Core.Api/appsettings.json
index 4e3e6ba6..ec80e8ad 100644
--- a/Blog.Core.Api/appsettings.json
+++ b/Blog.Core.Api/appsettings.json
@@ -50,7 +50,13 @@
"Enabled": false
},
"SqlAOP": {
- "Enabled": false
+ "Enabled": true,
+ "OutToLogFile": {
+ "Enabled": false
+ },
+ "OutToConsole": {
+ "Enabled": true
+ }
},
"Date": "2018-08-28",
"SeedDBEnabled": true, //只生成表结构
diff --git a/Blog.Core.Common/Helper/ConsoleHelper.cs b/Blog.Core.Common/Helper/ConsoleHelper.cs
index ce953b62..f0faef52 100644
--- a/Blog.Core.Common/Helper/ConsoleHelper.cs
+++ b/Blog.Core.Common/Helper/ConsoleHelper.cs
@@ -4,7 +4,7 @@ namespace Blog.Core.Common.Helper
{
public static class ConsoleHelper
{
- static void WriteColorLine(string str, ConsoleColor color)
+ public static void WriteColorLine(string str, ConsoleColor color)
{
ConsoleColor currentForeColor = Console.ForegroundColor;
Console.ForegroundColor = color;
diff --git a/Blog.Core.Extensions/ServiceExtensions/AppConfigSetup.cs b/Blog.Core.Extensions/ServiceExtensions/AppConfigSetup.cs
index 7da10921..83788535 100644
--- a/Blog.Core.Extensions/ServiceExtensions/AppConfigSetup.cs
+++ b/Blog.Core.Extensions/ServiceExtensions/AppConfigSetup.cs
@@ -90,13 +90,23 @@ public static void AddAppConfigSetup(this IServiceCollection services, IWebHostE
}
// 数据库Sql执行AOP
- if (!Appsettings.app(new string[] { "AppSettings", "SqlAOP", "Enabled" }).ObjToBool())
+ if (!Appsettings.app(new string[] { "AppSettings", "SqlAOP", "OutToLogFile", "Enabled" }).ObjToBool())
{
- Console.WriteLine($"DB Sql AOP: False");
+ Console.WriteLine($"DB Sql AOP To LogFile: False");
}
else
{
- ConsoleHelper.WriteSuccessLine($"DB Sql AOP: True");
+ ConsoleHelper.WriteSuccessLine($"DB Sql AOP To LogFile: True");
+ }
+
+ // Sql执行日志输出到控制台
+ if (!Appsettings.app(new string[] { "AppSettings", "SqlAOP", "OutToConsole", "Enabled" }).ObjToBool())
+ {
+ Console.WriteLine($"DB Sql AOP To Console: False");
+ }
+ else
+ {
+ ConsoleHelper.WriteSuccessLine($"DB Sql AOP To Console: True");
}
// SingnalR发送数据
diff --git a/Blog.Core.Extensions/ServiceExtensions/SqlsugarSetup.cs b/Blog.Core.Extensions/ServiceExtensions/SqlsugarSetup.cs
index dcbc1d58..799a80d2 100644
--- a/Blog.Core.Extensions/ServiceExtensions/SqlsugarSetup.cs
+++ b/Blog.Core.Extensions/ServiceExtensions/SqlsugarSetup.cs
@@ -1,5 +1,6 @@
using Blog.Core.Common;
using Blog.Core.Common.DB;
+using Blog.Core.Common.Helper;
using Blog.Core.Common.LogHelper;
using Microsoft.Extensions.DependencyInjection;
using SqlSugar;
@@ -54,14 +55,21 @@ public static void AddSqlsugarSetup(this IServiceCollection services)
{
if (Appsettings.app(new string[] { "AppSettings", "SqlAOP", "Enabled" }).ObjToBool())
{
- Parallel.For(0, 1, e =>
+ if (Appsettings.app(new string[] { "AppSettings", "SqlAOP", "OutToLogFile", "Enabled" }).ObjToBool())
{
- MiniProfiler.Current.CustomTiming("SQL:", GetParas(p) + "【SQL语句】:" + sql);
- LogLock.OutSql2Log("SqlLog", new string[] { GetParas(p), "【SQL语句】:" + sql });
+ Parallel.For(0, 1, e =>
+ {
+ MiniProfiler.Current.CustomTiming("SQL:", GetParas(p) + "【SQL语句】:" + sql);
+ LogLock.OutSql2Log("SqlLog", new string[] { GetParas(p), "【SQL语句】:" + sql });
- });
+ });
+ }
+ if (Appsettings.app(new string[] { "AppSettings", "SqlAOP", "OutToConsole", "Enabled" }).ObjToBool())
+ {
+ ConsoleHelper.WriteColorLine(string.Join("\r\n", new string[] { "--------", "【SQL语句】:" + GetWholeSql(p, sql) }), ConsoleColor.DarkCyan);
+ }
}
- }
+ },
},
MoreSettings = new ConnMoreSettings()
{
@@ -89,6 +97,16 @@ public static void AddSqlsugarSetup(this IServiceCollection services)
});
}
+ private static string GetWholeSql(SugarParameter[] paramArr, string sql)
+ {
+ foreach (var param in paramArr)
+ {
+ sql.Replace(param.ParameterName, param.Value.ObjToString());
+ }
+
+ return sql;
+ }
+
private static string GetParas(SugarParameter[] pars)
{
string key = "【SQL参数】:";
diff --git a/Blog.Core.Tests/Controller_Test/BlogController_Should.cs b/Blog.Core.Tests/Controller_Test/BlogController_Should.cs
index a55b2939..fce9f39e 100644
--- a/Blog.Core.Tests/Controller_Test/BlogController_Should.cs
+++ b/Blog.Core.Tests/Controller_Test/BlogController_Should.cs
@@ -27,7 +27,7 @@ public BlogController_Should()
var container = dI_Test.DICollections();
blogArticleServices = container.Resolve();
- blogController = new BlogController(blogArticleServices, mockLogger.Object);
+ blogController = new BlogController(mockLogger.Object);
}
[Fact]
diff --git a/Blog.Core.Tests/appsettings.json b/Blog.Core.Tests/appsettings.json
index 29e11768..a1edb353 100644
--- a/Blog.Core.Tests/appsettings.json
+++ b/Blog.Core.Tests/appsettings.json
@@ -34,7 +34,13 @@
"Enabled": false
},
"SqlAOP": {
- "Enabled": false
+ "Enabled": false,
+ "OutToLogFile": {
+ "Enabled": false
+ },
+ "OutToConsole": {
+ "Enabled": false
+ }
},
"Date": "2018-08-28",
"SeedDBEnabled": true, //只生成表结构
From 1083817a5c1d744ecc7cc6ffef1ea8602ec5869e Mon Sep 17 00:00:00 2001
From: ansonzhang <3143422472@qq.com>
Date: Tue, 8 Jun 2021 11:08:44 +0800
Subject: [PATCH 036/456] Update README.md
---
README.md | 12 ++++++++++++
1 file changed, 12 insertions(+)
diff --git a/README.md b/README.md
index 9a42483d..5045ad4f 100644
--- a/README.md
+++ b/README.md
@@ -85,7 +85,19 @@ Blog.Core 开箱即用的企业级前后端分离【 .NET Core5.0 Api + Vue 2.x
如果你喜欢这个项目或者它帮助你, 请给 Star~
如果你的项目中借鉴了本项目,请稍微说明下[https://github.com/anjoy8/Blog.Core/issues/75](https://github.com/anjoy8/Blog.Core/issues/75),开源不易✨。
+## 贡献者们
+Thanks goes to these wonderful people ([✨](https://github.com/anjoy8/Blog.Core/graphs/contributors)):
+
+
+| [
anjoy8](https://github.com/anjoy8)
💻📖 💡 | [
hudingwen](https://github.com/hudingwen)
💻 👀 | [
binyly ](https://github.com/binyly)
💻 👀 📖 🤔 | [
wuare ](https://github.com/wuare)
💻 🐛 🤔 | [
skang0401 ](https://github.com/skang0401)
📖| [
Jamnine](https://github.com/Jamnine)
💻 🌍|
+| :---: | :---: | :---: | :---: | :---: | :---: |
+|[
aion1998 ](https://github.com/aion1998)
🐛|[
RLei123 ](https://github.com/RLei123)
💻|[
cluyun ](https://github.com/cluyun)
🌍|[
blue20171027 ](https://github.com/blue20171027)
💻|[
anewboyz ](https://github.com/anewboyz)
💻|[
jxd728 ](https://github.com/jxd728)
🌍|
+|[
wmchuang ](https://github.com/wmchuang)
🌍|[
liuzhenyulive ](https://github.com/liuzhenyulive)
💻|[
JsonBy ](https://github.com/JsonBy)
💻 💡 🤔|[
hsxian ](https://github.com/hsxian)
🌍|[
cuno92 ](https://github.com/cuno92)
📖|[
317447880 ](https://github.com/317447880)
💻|
+
+
+This project follows the [all-contributors](https://github.com/anjoy8/Blog.Core/graphs/contributors) specification.
+Contributions of any kind are welcome!
From ddaa020d537acb829c88907897a3b2d39141bb92 Mon Sep 17 00:00:00 2001
From: anjoy8 <3143422472@qq.com>
Date: Fri, 11 Jun 2021 10:23:50 +0800
Subject: [PATCH 037/456] Update IPLogMildd.cs
---
Blog.Core.Extensions/Middlewares/IPLogMildd.cs | 18 +++++++++++++++---
1 file changed, 15 insertions(+), 3 deletions(-)
diff --git a/Blog.Core.Extensions/Middlewares/IPLogMildd.cs b/Blog.Core.Extensions/Middlewares/IPLogMildd.cs
index 8716db96..7062d49a 100644
--- a/Blog.Core.Extensions/Middlewares/IPLogMildd.cs
+++ b/Blog.Core.Extensions/Middlewares/IPLogMildd.cs
@@ -20,6 +20,7 @@ public class IPLogMildd
///
private readonly RequestDelegate _next;
private readonly IWebHostEnvironment _environment;
+ private static readonly log4net.ILog log = log4net.LogManager.GetLogger(typeof(IPLogMildd));
///
///
@@ -61,9 +62,20 @@ public async Task InvokeAsync(HttpContext context)
// LogLock.OutSql2Log("RequestIpInfoLog", new string[] { requestInfo + "," }, false);
//});
- // 这种方案也行,用的是Serilog
- var logFileName = FileHelper.GetAvailableFileNameWithPrefixOrderSize(_environment.ContentRootPath, "RequestIpInfoLog");
- SerilogServer.WriteLog(logFileName, new string[] { requestInfo + "," }, false);
+ try
+ {
+ var testLogMatchRequestInfo = JsonConvert.DeserializeObject(requestInfo);
+ if (testLogMatchRequestInfo != null)
+ {
+ var logFileName = FileHelper.GetAvailableFileNameWithPrefixOrderSize(_environment.ContentRootPath, "RequestIpInfoLog");
+ SerilogServer.WriteLog(logFileName, new string[] { requestInfo + "," }, false);
+ }
+ }
+ catch (Exception e)
+ {
+ log.Error(requestInfo + "\r\n" + e.GetBaseException().ToString());
+ }
+
request.Body.Position = 0;
}
From 70a419faa8eeb7baa2120ecf846153cd089e9d65 Mon Sep 17 00:00:00 2001
From: ansonzhang <3143422472@qq.com>
Date: Sat, 12 Jun 2021 12:16:30 +0800
Subject: [PATCH 038/456] Fixed #195 bug
---
.../LogHelper/Seri/SerilogServer.cs | 25 +++++++++++--------
1 file changed, 14 insertions(+), 11 deletions(-)
diff --git a/Blog.Core.Common/LogHelper/Seri/SerilogServer.cs b/Blog.Core.Common/LogHelper/Seri/SerilogServer.cs
index 36d88c23..249ab8b1 100644
--- a/Blog.Core.Common/LogHelper/Seri/SerilogServer.cs
+++ b/Blog.Core.Common/LogHelper/Seri/SerilogServer.cs
@@ -1,4 +1,4 @@
-using Serilog;
+using Serilog;
using Serilog.Events;
using Serilog.Sinks.Elasticsearch;
using System;
@@ -35,17 +35,20 @@ public static void WriteLog(string filename, string[] dataParas, bool IsHeader =
.CreateLogger();
var now = DateTime.Now;
- string logContent = String.Join("\r\n", dataParas);
- if (IsHeader)
+ string logJudge = String.Join("-", dataParas);
+ if (logJudge != null && logJudge.Length > 20)
{
- logContent = (
- "--------------------------------\r\n" +
- DateTime.Now + "|\r\n" +
- String.Join("\r\n", dataParas) + "\r\n"
- );
+ string logContent = String.Join("\r\n", dataParas);
+ if (IsHeader)
+ {
+ logContent = (
+ "--------------------------------\r\n" +
+ DateTime.Now + "|\r\n" +
+ String.Join("\r\n", dataParas) + "\r\n"
+ );
+ }
+ Log.Information(logContent);
}
-
- Log.Information(logContent);
Log.CloseAndFlush();
}
///
@@ -65,4 +68,4 @@ public static void WriteErrorLog(string filename, string message, Exception ex)
Log.CloseAndFlush();
}
}
-}
\ No newline at end of file
+}
From c94a397ffb9f0fca29c654ce19293f13f51a83f2 Mon Sep 17 00:00:00 2001
From: anjoy8 <3143422472@qq.com>
Date: Fri, 25 Jun 2021 23:44:06 +0800
Subject: [PATCH 039/456] =?UTF-8?q?fix=EF=BC=9Alog=20error?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
Blog.Core.Common/Helper/JsonHelper.cs | 394 ++++++++++++++++++
.../LogHelper/Seri/SerilogServer.cs | 19 +-
.../Middlewares/IPLogMildd.cs | 2 +-
3 files changed, 410 insertions(+), 5 deletions(-)
diff --git a/Blog.Core.Common/Helper/JsonHelper.cs b/Blog.Core.Common/Helper/JsonHelper.cs
index baf9b106..352cb8e1 100644
--- a/Blog.Core.Common/Helper/JsonHelper.cs
+++ b/Blog.Core.Common/Helper/JsonHelper.cs
@@ -100,5 +100,399 @@ public string JSON1(List vals)
return st.ToString();
}
+
+ private static bool IsJsonStart(ref string json)
+ {
+ if (!string.IsNullOrEmpty(json))
+ {
+ json = json.Trim('\r', '\n', ' ');
+ if (json.Length > 1)
+ {
+ char s = json[0];
+ char e = json[json.Length - 1];
+ return (s == '{' && e == '}') || (s == '[' && e == ']');
+ }
+ }
+ return false;
+ }
+ public static bool IsJson(string json)
+ {
+ int errIndex;
+ return IsJson(json, out errIndex);
+ }
+ public static bool IsJson(string json, out int errIndex)
+ {
+ errIndex = 0;
+ if (IsJsonStart(ref json))
+ {
+ CharState cs = new CharState();
+ char c;
+ for (int i = 0; i < json.Length; i++)
+ {
+ c = json[i];
+ if (SetCharState(c, ref cs) && cs.childrenStart)//设置关键符号状态。
+ {
+ string item = json.Substring(i);
+ int err;
+ int length = GetValueLength(item, true, out err);
+ cs.childrenStart = false;
+ if (err > 0)
+ {
+ errIndex = i + err;
+ return false;
+ }
+ i = i + length - 1;
+ }
+ if (cs.isError)
+ {
+ errIndex = i;
+ return false;
+ }
+ }
+
+ return !cs.arrayStart && !cs.jsonStart;
+ }
+ return false;
+ }
+
+ ///
+ /// 获取值的长度(当Json值嵌套以"{"或"["开头时)
+ ///
+ private static int GetValueLength(string json, bool breakOnErr, out int errIndex)
+ {
+ errIndex = 0;
+ int len = 0;
+ if (!string.IsNullOrEmpty(json))
+ {
+ CharState cs = new CharState();
+ char c;
+ for (int i = 0; i < json.Length; i++)
+ {
+ c = json[i];
+ if (!SetCharState(c, ref cs))//设置关键符号状态。
+ {
+ if (!cs.jsonStart && !cs.arrayStart)//json结束,又不是数组,则退出。
+ {
+ break;
+ }
+ }
+ else if (cs.childrenStart)//正常字符,值状态下。
+ {
+ int length = GetValueLength(json.Substring(i), breakOnErr, out errIndex);//递归子值,返回一个长度。。。
+ cs.childrenStart = false;
+ cs.valueStart = 0;
+ //cs.state = 0;
+ i = i + length - 1;
+ }
+ if (breakOnErr && cs.isError)
+ {
+ errIndex = i;
+ return i;
+ }
+ if (!cs.jsonStart && !cs.arrayStart)//记录当前结束位置。
+ {
+ len = i + 1;//长度比索引+1
+ break;
+ }
+ }
+ }
+ return len;
+ }
+
+ ///
+ /// 设置字符状态(返回true则为关键词,返回false则当为普通字符处理)
+ ///
+ private static bool SetCharState(char c, ref CharState cs)
+ {
+ cs.CheckIsError(c);
+ switch (c)
+ {
+ case '{'://[{ "[{A}]":[{"[{B}]":3,"m":"C"}]}]
+ #region 大括号
+ if (cs.keyStart <= 0 && cs.valueStart <= 0)
+ {
+ cs.keyStart = 0;
+ cs.valueStart = 0;
+ if (cs.jsonStart && cs.state == 1)
+ {
+ cs.childrenStart = true;
+ }
+ else
+ {
+ cs.state = 0;
+ }
+ cs.jsonStart = true;//开始。
+ return true;
+ }
+ #endregion
+ break;
+ case '}':
+ #region 大括号结束
+ if (cs.keyStart <= 0 && cs.valueStart < 2 && cs.jsonStart)
+ {
+ cs.jsonStart = false;//正常结束。
+ cs.state = 0;
+ cs.keyStart = 0;
+ cs.valueStart = 0;
+ cs.setDicValue = true;
+ return true;
+ }
+ // cs.isError = !cs.jsonStart && cs.state == 0;
+ #endregion
+ break;
+ case '[':
+ #region 中括号开始
+ if (!cs.jsonStart)
+ {
+ cs.arrayStart = true;
+ return true;
+ }
+ else if (cs.jsonStart && cs.state == 1)
+ {
+ cs.childrenStart = true;
+ return true;
+ }
+ #endregion
+ break;
+ case ']':
+ #region 中括号结束
+ if (cs.arrayStart && !cs.jsonStart && cs.keyStart <= 2 && cs.valueStart <= 0)//[{},333]//这样结束。
+ {
+ cs.keyStart = 0;
+ cs.valueStart = 0;
+ cs.arrayStart = false;
+ return true;
+ }
+ #endregion
+ break;
+ case '"':
+ case '\'':
+ #region 引号
+ if (cs.jsonStart || cs.arrayStart)
+ {
+ if (cs.state == 0)//key阶段,有可能是数组["aa",{}]
+ {
+ if (cs.keyStart <= 0)
+ {
+ cs.keyStart = (c == '"' ? 3 : 2);
+ return true;
+ }
+ else if ((cs.keyStart == 2 && c == '\'') || (cs.keyStart == 3 && c == '"'))
+ {
+ if (!cs.escapeChar)
+ {
+ cs.keyStart = -1;
+ return true;
+ }
+ else
+ {
+ cs.escapeChar = false;
+ }
+ }
+ }
+ else if (cs.state == 1 && cs.jsonStart)//值阶段必须是Json开始了。
+ {
+ if (cs.valueStart <= 0)
+ {
+ cs.valueStart = (c == '"' ? 3 : 2);
+ return true;
+ }
+ else if ((cs.valueStart == 2 && c == '\'') || (cs.valueStart == 3 && c == '"'))
+ {
+ if (!cs.escapeChar)
+ {
+ cs.valueStart = -1;
+ return true;
+ }
+ else
+ {
+ cs.escapeChar = false;
+ }
+ }
+
+ }
+ }
+ #endregion
+ break;
+ case ':':
+ #region 冒号
+ if (cs.jsonStart && cs.keyStart < 2 && cs.valueStart < 2 && cs.state == 0)
+ {
+ if (cs.keyStart == 1)
+ {
+ cs.keyStart = -1;
+ }
+ cs.state = 1;
+ return true;
+ }
+ // cs.isError = !cs.jsonStart || (cs.keyStart < 2 && cs.valueStart < 2 && cs.state == 1);
+ #endregion
+ break;
+ case ',':
+ #region 逗号 //["aa",{aa:12,}]
+
+ if (cs.jsonStart)
+ {
+ if (cs.keyStart < 2 && cs.valueStart < 2 && cs.state == 1)
+ {
+ cs.state = 0;
+ cs.keyStart = 0;
+ cs.valueStart = 0;
+ //if (cs.valueStart == 1)
+ //{
+ // cs.valueStart = 0;
+ //}
+ cs.setDicValue = true;
+ return true;
+ }
+ }
+ else if (cs.arrayStart && cs.keyStart <= 2)
+ {
+ cs.keyStart = 0;
+ //if (cs.keyStart == 1)
+ //{
+ // cs.keyStart = -1;
+ //}
+ return true;
+ }
+ #endregion
+ break;
+ case ' ':
+ case '\r':
+ case '\n'://[ "a",\r\n{} ]
+ case '\0':
+ case '\t':
+ if (cs.keyStart <= 0 && cs.valueStart <= 0) //cs.jsonStart &&
+ {
+ return true;//跳过空格。
+ }
+ break;
+ default: //值开头。。
+ if (c == '\\') //转义符号
+ {
+ if (cs.escapeChar)
+ {
+ cs.escapeChar = false;
+ }
+ else
+ {
+ cs.escapeChar = true;
+ return true;
+ }
+ }
+ else
+ {
+ cs.escapeChar = false;
+ }
+ if (cs.jsonStart || cs.arrayStart) // Json 或数组开始了。
+ {
+ if (cs.keyStart <= 0 && cs.state == 0)
+ {
+ cs.keyStart = 1;//无引号的
+ }
+ else if (cs.valueStart <= 0 && cs.state == 1 && cs.jsonStart)//只有Json开始才有值。
+ {
+ cs.valueStart = 1;//无引号的
+ }
+ }
+ break;
+ }
+ return false;
+ }
+ }
+ ///
+ /// 字符状态
+ ///
+ public class CharState
+ {
+ internal bool jsonStart = false;//以 "{"开始了...
+ internal bool setDicValue = false;// 可以设置字典值了。
+ internal bool escapeChar = false;//以"\"转义符号开始了
+ ///
+ /// 数组开始【仅第一开头才算】,值嵌套的以【childrenStart】来标识。
+ ///
+ internal bool arrayStart = false;//以"[" 符号开始了
+ internal bool childrenStart = false;//子级嵌套开始了。
+ ///
+ /// 【0 初始状态,或 遇到“,”逗号】;【1 遇到“:”冒号】
+ ///
+ internal int state = 0;
+
+ ///
+ /// 【-1 取值结束】【0 未开始】【1 无引号开始】【2 单引号开始】【3 双引号开始】
+ ///
+ internal int keyStart = 0;
+ ///
+ /// 【-1 取值结束】【0 未开始】【1 无引号开始】【2 单引号开始】【3 双引号开始】
+ ///
+ internal int valueStart = 0;
+ internal bool isError = false;//是否语法错误。
+
+ internal void CheckIsError(char c)//只当成一级处理(因为GetLength会递归到每一个子项处理)
+ {
+ if (keyStart > 1 || valueStart > 1)
+ {
+ return;
+ }
+ //示例 ["aa",{"bbbb":123,"fff","ddd"}]
+ switch (c)
+ {
+ case '{'://[{ "[{A}]":[{"[{B}]":3,"m":"C"}]}]
+ isError = jsonStart && state == 0;//重复开始错误 同时不是值处理。
+ break;
+ case '}':
+ isError = !jsonStart || (keyStart != 0 && state == 0);//重复结束错误 或者 提前结束{"aa"}。正常的有{}
+ break;
+ case '[':
+ isError = arrayStart && state == 0;//重复开始错误
+ break;
+ case ']':
+ isError = !arrayStart || jsonStart;//重复开始错误 或者 Json 未结束
+ break;
+ case '"':
+ case '\'':
+ isError = !(jsonStart || arrayStart); //json 或数组开始。
+ if (!isError)
+ {
+ //重复开始 [""",{"" "}]
+ isError = (state == 0 && keyStart == -1) || (state == 1 && valueStart == -1);
+ }
+ if (!isError && arrayStart && !jsonStart && c == '\'')//['aa',{}]
+ {
+ isError = true;
+ }
+ break;
+ case ':':
+ isError = !jsonStart || state == 1;//重复出现。
+ break;
+ case ',':
+ isError = !(jsonStart || arrayStart); //json 或数组开始。
+ if (!isError)
+ {
+ if (jsonStart)
+ {
+ isError = state == 0 || (state == 1 && valueStart > 1);//重复出现。
+ }
+ else if (arrayStart)//["aa,] [,] [{},{}]
+ {
+ isError = keyStart == 0 && !setDicValue;
+ }
+ }
+ break;
+ case ' ':
+ case '\r':
+ case '\n'://[ "a",\r\n{} ]
+ case '\0':
+ case '\t':
+ break;
+ default: //值开头。。
+ isError = (!jsonStart && !arrayStart) || (state == 0 && keyStart == -1) || (valueStart == -1 && state == 1);//
+ break;
+ }
+ //if (isError)
+ //{
+
+ //}
+ }
}
}
diff --git a/Blog.Core.Common/LogHelper/Seri/SerilogServer.cs b/Blog.Core.Common/LogHelper/Seri/SerilogServer.cs
index 249ab8b1..7cf8718e 100644
--- a/Blog.Core.Common/LogHelper/Seri/SerilogServer.cs
+++ b/Blog.Core.Common/LogHelper/Seri/SerilogServer.cs
@@ -1,3 +1,4 @@
+using Blog.Core.Common.Helper;
using Serilog;
using Serilog.Events;
using Serilog.Sinks.Elasticsearch;
@@ -14,7 +15,7 @@ public class SerilogServer
///
///
///
- public static void WriteLog(string filename, string[] dataParas, bool IsHeader = true, string defaultFolder = "")
+ public static void WriteLog(string filename, string[] dataParas, bool IsHeader = true, string defaultFolder = "", bool isJudgeJsonFormat = false)
{
Log.Logger = new LoggerConfiguration()
.MinimumLevel.Debug()
@@ -35,10 +36,16 @@ public static void WriteLog(string filename, string[] dataParas, bool IsHeader =
.CreateLogger();
var now = DateTime.Now;
- string logJudge = String.Join("-", dataParas);
- if (logJudge != null && logJudge.Length > 20)
+ string logContent = String.Join("\r\n", dataParas);
+ var isJsonFormat = true;
+ if (isJudgeJsonFormat)
+ {
+ var judCont = logContent.Substring(0, logContent.LastIndexOf(","));
+ isJsonFormat = JsonHelper.IsJson(judCont);
+ }
+
+ if (isJsonFormat)
{
- string logContent = String.Join("\r\n", dataParas);
if (IsHeader)
{
logContent = (
@@ -49,6 +56,10 @@ public static void WriteLog(string filename, string[] dataParas, bool IsHeader =
}
Log.Information(logContent);
}
+ else
+ {
+ ConsoleHelper.WriteErrorLine(logContent + now.ObjToString());
+ }
Log.CloseAndFlush();
}
///
diff --git a/Blog.Core.Extensions/Middlewares/IPLogMildd.cs b/Blog.Core.Extensions/Middlewares/IPLogMildd.cs
index 7062d49a..08791669 100644
--- a/Blog.Core.Extensions/Middlewares/IPLogMildd.cs
+++ b/Blog.Core.Extensions/Middlewares/IPLogMildd.cs
@@ -68,7 +68,7 @@ public async Task InvokeAsync(HttpContext context)
if (testLogMatchRequestInfo != null)
{
var logFileName = FileHelper.GetAvailableFileNameWithPrefixOrderSize(_environment.ContentRootPath, "RequestIpInfoLog");
- SerilogServer.WriteLog(logFileName, new string[] { requestInfo + "," }, false);
+ SerilogServer.WriteLog(logFileName, new string[] { requestInfo + "," }, false, "", true);
}
}
catch (Exception e)
From eb7043894e983b9036ce8cbd8094631b034d7673 Mon Sep 17 00:00:00 2001
From: anjoy8 <3143422472@qq.com>
Date: Mon, 28 Jun 2021 10:36:33 +0800
Subject: [PATCH 040/456] Update SerilogServer.cs
---
Blog.Core.Common/LogHelper/Seri/SerilogServer.cs | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/Blog.Core.Common/LogHelper/Seri/SerilogServer.cs b/Blog.Core.Common/LogHelper/Seri/SerilogServer.cs
index 7cf8718e..fcdbfd84 100644
--- a/Blog.Core.Common/LogHelper/Seri/SerilogServer.cs
+++ b/Blog.Core.Common/LogHelper/Seri/SerilogServer.cs
@@ -58,7 +58,7 @@ public static void WriteLog(string filename, string[] dataParas, bool IsHeader =
}
else
{
- ConsoleHelper.WriteErrorLine(logContent + now.ObjToString());
+ Console.WriteLine("【JSON格式异常:】"+logContent + now.ObjToString());
}
Log.CloseAndFlush();
}
From 01d11613c25bc4d5c76d16a4aaa0c5091198270b Mon Sep 17 00:00:00 2001
From: hudingwen <765472804@qq.com>
Date: Fri, 9 Jul 2021 23:29:43 +0800
Subject: [PATCH 041/456] =?UTF-8?q?=E6=97=A0?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
Blog.Core.Common/Helper/StringHelper.cs | 19 +++++++++++++++++++
.../QuartzNet/Jobs/Job_OperateLog_Quartz.cs | 2 +-
2 files changed, 20 insertions(+), 1 deletion(-)
diff --git a/Blog.Core.Common/Helper/StringHelper.cs b/Blog.Core.Common/Helper/StringHelper.cs
index 4c9683e6..55f9da08 100644
--- a/Blog.Core.Common/Helper/StringHelper.cs
+++ b/Blog.Core.Common/Helper/StringHelper.cs
@@ -61,6 +61,25 @@ public static string GetPars(Dictionary dic)
return urlPars;
}
///
+ /// 根据字段拼接get参数
+ ///
+ ///
+ ///
+ public static string GetPars(Dictionary dic)
+ {
+
+ StringBuilder sb = new StringBuilder();
+ string urlPars = null;
+ bool isEnter = false;
+ foreach (var item in dic)
+ {
+ sb.Append($"{(isEnter ? "&" : "")}{item.Key}={item.Value}");
+ isEnter = true;
+ }
+ urlPars = sb.ToString();
+ return urlPars;
+ }
+ ///
/// 获取一个GUID
///
/// 格式-默认为N
diff --git a/Blog.Core.Tasks/QuartzNet/Jobs/Job_OperateLog_Quartz.cs b/Blog.Core.Tasks/QuartzNet/Jobs/Job_OperateLog_Quartz.cs
index d6d969cd..87b3b213 100644
--- a/Blog.Core.Tasks/QuartzNet/Jobs/Job_OperateLog_Quartz.cs
+++ b/Blog.Core.Tasks/QuartzNet/Jobs/Job_OperateLog_Quartz.cs
@@ -21,7 +21,7 @@ public class Job_OperateLog_Quartz : JobBase, IJob
private readonly IOperateLogServices _operateLogServices;
private readonly IWebHostEnvironment _environment;
- public Job_OperateLog_Quartz(ITasksQzServices tasksQzServices, ILogger logger, IOperateLogServices operateLogServices, IWebHostEnvironment environment):base(tasksQzServices, logger)
+ public Job_OperateLog_Quartz(ITasksQzServices tasksQzServices, ILogger logger, IOperateLogServices operateLogServices, IWebHostEnvironment environment)
{
_operateLogServices = operateLogServices;
_environment = environment;
From 4a0842eb743cc04a299c1719fc8b56adbfe9b344 Mon Sep 17 00:00:00 2001
From: hudingwen <765472804@qq.com>
Date: Mon, 12 Jul 2021 00:04:08 +0800
Subject: [PATCH 042/456] =?UTF-8?q?=E7=BB=9F=E4=B8=80=E5=BC=82=E5=B8=B8?=
=?UTF-8?q?=E6=B6=88=E6=81=AF=E6=A8=A1=E5=9E=8B?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
Blog.Core.Api/Filter/GlobalExceptionFilter.cs | 26 ++++++++++++-------
Blog.Core.Api/appsettings.json | 2 +-
Blog.Core.Model/MessageModel.cs | 4 +++
.../QuartzNet/Jobs/Job_OperateLog_Quartz.cs | 5 ++--
4 files changed, 24 insertions(+), 13 deletions(-)
diff --git a/Blog.Core.Api/Filter/GlobalExceptionFilter.cs b/Blog.Core.Api/Filter/GlobalExceptionFilter.cs
index 858954f0..4a39efc2 100644
--- a/Blog.Core.Api/Filter/GlobalExceptionFilter.cs
+++ b/Blog.Core.Api/Filter/GlobalExceptionFilter.cs
@@ -1,5 +1,7 @@
-using Blog.Core.Common.LogHelper;
+using Blog.Core.Common.Helper;
+using Blog.Core.Common.LogHelper;
using Blog.Core.Hubs;
+using Blog.Core.Model;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
@@ -29,26 +31,30 @@ public GlobalExceptionsFilter(IWebHostEnvironment env, ILogger();
- json.Message = context.Exception.Message;//错误信息
+ json.msg = context.Exception.Message;//错误信息
+ json.status = 500;//500异常
var errorAudit = "Unable to resolve service for";
- if (!string.IsNullOrEmpty(json.Message)&& json.Message.Contains(errorAudit))
+ if (!string.IsNullOrEmpty(json.msg) && json.msg.Contains(errorAudit))
{
- json.Message = json.Message.Replace(errorAudit, $"(若新添加服务,需要重新编译项目){errorAudit}");
+ json.msg = json.msg.Replace(errorAudit, $"(若新添加服务,需要重新编译项目){errorAudit}");
}
- //if (_env.IsDevelopment())
+ if (_env.EnvironmentName.ObjToString().Equals("Development"))
{
- json.DevelopmentMessage = context.Exception.StackTrace;//堆栈信息
+ json.msgDev = context.Exception.StackTrace;//堆栈信息
}
- context.Result = new InternalServerErrorObjectResult(json);
+ var res = new ContentResult();
+ res.Content = JsonHelper.GetJSON>(json);
- MiniProfiler.Current.CustomTiming("Errors:", json.Message);
+ context.Result = res;
+
+ MiniProfiler.Current.CustomTiming("Errors:", json.msg);
//采用log4net 进行错误日志记录
- _loggerHelper.LogError(json.Message + WriteLog(json.Message, context.Exception));
+ _loggerHelper.LogError(json.msg + WriteLog(json.msg, context.Exception));
_hubContext.Clients.All.SendAsync("ReceiveUpdate", LogLock.GetLogData()).Wait();
diff --git a/Blog.Core.Api/appsettings.json b/Blog.Core.Api/appsettings.json
index 4e3e6ba6..9eea2027 100644
--- a/Blog.Core.Api/appsettings.json
+++ b/Blog.Core.Api/appsettings.json
@@ -240,7 +240,7 @@
"ServiceHealthCheck": "/healthcheck",
"ConsulAddress": "http://localhost:8500"
},
- "PayInfo": { //建行支付信息
+ "PayInfo": { //建行聚合支付信息
"MERCHANTID": "", //商户号
"POSID": "", //柜台号
"BRANCHID": "", //分行号
diff --git a/Blog.Core.Model/MessageModel.cs b/Blog.Core.Model/MessageModel.cs
index 5fa7f091..1ede65b4 100644
--- a/Blog.Core.Model/MessageModel.cs
+++ b/Blog.Core.Model/MessageModel.cs
@@ -18,6 +18,10 @@ public class MessageModel
///
public string msg { get; set; } = "";
///
+ /// 开发者信息
+ ///
+ public string msgDev { get; set; }
+ ///
/// 返回数据集合
///
public T response { get; set; }
diff --git a/Blog.Core.Tasks/QuartzNet/Jobs/Job_OperateLog_Quartz.cs b/Blog.Core.Tasks/QuartzNet/Jobs/Job_OperateLog_Quartz.cs
index 87b3b213..e2c479ed 100644
--- a/Blog.Core.Tasks/QuartzNet/Jobs/Job_OperateLog_Quartz.cs
+++ b/Blog.Core.Tasks/QuartzNet/Jobs/Job_OperateLog_Quartz.cs
@@ -21,10 +21,11 @@ public class Job_OperateLog_Quartz : JobBase, IJob
private readonly IOperateLogServices _operateLogServices;
private readonly IWebHostEnvironment _environment;
- public Job_OperateLog_Quartz(ITasksQzServices tasksQzServices, ILogger logger, IOperateLogServices operateLogServices, IWebHostEnvironment environment)
+ public Job_OperateLog_Quartz(IOperateLogServices operateLogServices, ITasksQzServices tasksQzServices, IWebHostEnvironment environment)
{
_operateLogServices = operateLogServices;
- _environment = environment;
+ _environment = environment;
+ _tasksQzServices = tasksQzServices;
}
public async Task Execute(IJobExecutionContext context)
{
From b6ae3b3f61707a26d886f6803de20d2a8f65b674 Mon Sep 17 00:00:00 2001
From: ansonzhang <3143422472@qq.com>
Date: Mon, 12 Jul 2021 17:18:28 +0800
Subject: [PATCH 043/456] Update README.md
---
README.md | 11 ++++++-----
1 file changed, 6 insertions(+), 5 deletions(-)
diff --git a/README.md b/README.md
index 5045ad4f..891e826a 100644
--- a/README.md
+++ b/README.md
@@ -16,15 +16,16 @@
-
-
-
+
Blog.Core 开箱即用的企业级前后端分离【 .NET Core5.0 Api + Vue 2.x + RBAC】权限框架。
-官网:http://apk.neters.club/.doc/
-已被多家公司所使用:[点击查看列表](https://github.com/anjoy8/Blog.Core/issues/75)
+官网:http://apk.neters.club/.doc/
+
+
+
+**已被多家公司所使用(70+🐱🚀):[点击查看列表](https://github.com/anjoy8/Blog.Core/issues/75)**
项目单体部署,并发在400~500,一切正常(不保证自己的各种错误写法)。
如果搭配负载,效果更好。
From fe59cc33a4255076d951f381e218eb92e11133a0 Mon Sep 17 00:00:00 2001
From: anjoy8 <3143422472@qq.com>
Date: Thu, 15 Jul 2021 15:41:45 +0800
Subject: [PATCH 044/456] =?UTF-8?q?feat=EF=BC=9Aupdate=20common=20initq?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
Blog.Core.Api/Blog.Core.Model.xml | 5 +++++
Blog.Core.Common/Blog.Core.Common.csproj | 2 +-
2 files changed, 6 insertions(+), 1 deletion(-)
diff --git a/Blog.Core.Api/Blog.Core.Model.xml b/Blog.Core.Api/Blog.Core.Model.xml
index ce6dd052..575f738b 100644
--- a/Blog.Core.Api/Blog.Core.Model.xml
+++ b/Blog.Core.Api/Blog.Core.Model.xml
@@ -96,6 +96,11 @@
返回信息
+
+
+ 开发者信息
+
+
返回数据集合
diff --git a/Blog.Core.Common/Blog.Core.Common.csproj b/Blog.Core.Common/Blog.Core.Common.csproj
index 92af0184..75d1364f 100644
--- a/Blog.Core.Common/Blog.Core.Common.csproj
+++ b/Blog.Core.Common/Blog.Core.Common.csproj
@@ -10,7 +10,7 @@
-
+
From 69f2fad40e6914d99bd38dd6c54d23a48a39c6ed Mon Sep 17 00:00:00 2001
From: anjoy8 <3143422472@qq.com>
Date: Thu, 15 Jul 2021 15:54:53 +0800
Subject: [PATCH 045/456] Update Blog.Core.Common.csproj
---
Blog.Core.Common/Blog.Core.Common.csproj | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/Blog.Core.Common/Blog.Core.Common.csproj b/Blog.Core.Common/Blog.Core.Common.csproj
index 75d1364f..8ada40a3 100644
--- a/Blog.Core.Common/Blog.Core.Common.csproj
+++ b/Blog.Core.Common/Blog.Core.Common.csproj
@@ -14,7 +14,7 @@
-
+
From f3cf974bd0730fe4cccad2cf2e01fd384773df85 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E5=AE=81=E9=AA=91?= <1075858260@qq.com>
Date: Fri, 23 Jul 2021 18:22:12 +0800
Subject: [PATCH 046/456] =?UTF-8?q?=E5=8E=BB=E6=8E=89=E4=B8=80=E4=B8=A2?=
=?UTF-8?q?=E4=B8=A2=E6=97=A0=E8=B0=93=E7=9A=84=E4=BB=A3=E7=A0=81?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
Blog.Core.Api/Controllers/BlogController.cs | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/Blog.Core.Api/Controllers/BlogController.cs b/Blog.Core.Api/Controllers/BlogController.cs
index a7841874..577e80bb 100644
--- a/Blog.Core.Api/Controllers/BlogController.cs
+++ b/Blog.Core.Api/Controllers/BlogController.cs
@@ -89,7 +89,7 @@ public async Task>> Get(int id, int page = 1
[Authorize]
public async Task> Get(int id)
{
- return Success(await _blogArticleServices.GetBlogDetails(id));
+ return Success(await _blogArticleServices.GetBlogDetails(id));
}
@@ -103,7 +103,7 @@ public async Task> Get(int id)
public async Task> DetailNuxtNoPer(int id)
{
_logger.LogInformation("xxxxxxxxxxxxxxxxxxx");
- return Success(await _blogArticleServices.GetBlogDetails(id));
+ return Success(await _blogArticleServices.GetBlogDetails(id));
}
[HttpGet]
@@ -247,7 +247,7 @@ public async Task> Delete(int id)
{
var blogArticle = await _blogArticleServices.QueryById(id);
blogArticle.IsDeleted = true;
- return await _blogArticleServices.Update(blogArticle) ? Success(blogArticle?.bID.ObjToString(), "删除成功") : Failed("删除失败");
+ return await _blogArticleServices.Update(blogArticle) ? Success(blogArticle?.bID.ObjToString(), "删除成功") : Failed("删除失败");
}
return Failed("入参无效");
}
From e81325a089d7ccf9cce549a58970b788c7939d7c Mon Sep 17 00:00:00 2001
From: ansonzhang <3143422472@qq.com>
Date: Sun, 25 Jul 2021 15:30:00 +0800
Subject: [PATCH 047/456] Update README.md
---
.docs/contents/Update/README.md | 19 ++++++++++++++++++-
1 file changed, 18 insertions(+), 1 deletion(-)
diff --git a/.docs/contents/Update/README.md b/.docs/contents/Update/README.md
index 3cc421b0..a80f7cb1 100644
--- a/.docs/contents/Update/README.md
+++ b/.docs/contents/Update/README.md
@@ -1,6 +1,23 @@
-
+
## 更新日志
+
+### 2021-05-01
+
+组件更新:多项日志中间件,由自写组件,转为使用`serilog`组件记录日志;
+
+### 2021-03-03
+
+项目目录调整:新增测试文件夹和模板文件夹;
+
+### 2021-02-09
+
+重大项目更新:新增建行聚合支付;
+
+### 2021-01-11
+
+更新:优化任务调度功能,新增暂停和停止;
+
### 2020-12-02
更新:新增调用`MongoDB`功能,功能可用待完善中;
From 6a7050b1ce6df4fc1b9871ae0c64d250358d419e Mon Sep 17 00:00:00 2001
From: ansonzhang <3143422472@qq.com>
Date: Mon, 26 Jul 2021 10:34:14 +0800
Subject: [PATCH 048/456] Update README.md
---
README.md | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/README.md b/README.md
index 891e826a..af5ee5e4 100644
--- a/README.md
+++ b/README.md
@@ -34,6 +34,12 @@ Blog.Core 开箱即用的企业级前后端分离【 .NET Core5.0 Api + Vue 2.x
+#### 联系我
+如果你对BCVP框架感兴趣,并有一定的框架设计经验,,欢迎加入架构师交流群,只要交流心得都可以进入,如果单纯提问问题的就算了哈。
+
+
+
+
### 功能与进度
框架模块:
From 654cc7a3aa3c92253a3a3b5d43e480ca0e56b750 Mon Sep 17 00:00:00 2001
From: tianyu
Date: Wed, 28 Jul 2021 11:01:28 +0800
Subject: [PATCH 049/456] =?UTF-8?q?=E7=94=B0=E9=9B=A8?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
Blog.Core.Api/Blog.Core.Api.csproj | 12 +
Blog.Core.Api/Blog.Core.xml | 85 ++++++
Blog.Core.Api/NacosListenConfigurationTask.cs | 91 ++++++
Blog.Core.Api/NacosListenNamingTask.cs | 105 +++++++
Blog.Core.Api/Program.cs | 28 +-
Blog.Core.Api/Properties/launchSettings.json | 2 +-
Blog.Core.Api/Startup.cs | 40 +++
Blog.Core.Api/appsettings.Development.json | 9 -
Blog.Core.Api/appsettings.dev.json | 267 ++++++++++++++++
Blog.Core.Api/appsettings.prod.json | 258 ++++++++++++++++
Blog.Core.Api/appsettings.test.json | 258 ++++++++++++++++
Blog.Core.Common/Helper/IpHelper.cs | 51 ++++
Blog.Core.Common/Helper/JsonConfigUtils.cs | 289 ++++++++++++++++++
13 files changed, 1484 insertions(+), 11 deletions(-)
create mode 100644 Blog.Core.Api/NacosListenConfigurationTask.cs
create mode 100644 Blog.Core.Api/NacosListenNamingTask.cs
delete mode 100644 Blog.Core.Api/appsettings.Development.json
create mode 100644 Blog.Core.Api/appsettings.dev.json
create mode 100644 Blog.Core.Api/appsettings.prod.json
create mode 100644 Blog.Core.Api/appsettings.test.json
create mode 100644 Blog.Core.Common/Helper/IpHelper.cs
create mode 100644 Blog.Core.Common/Helper/JsonConfigUtils.cs
diff --git a/Blog.Core.Api/Blog.Core.Api.csproj b/Blog.Core.Api/Blog.Core.Api.csproj
index 6da4f101..fef5e938 100644
--- a/Blog.Core.Api/Blog.Core.Api.csproj
+++ b/Blog.Core.Api/Blog.Core.Api.csproj
@@ -46,6 +46,16 @@
+
+
+
+
+
+
+
+
+
+
@@ -84,4 +94,6 @@
+
+
diff --git a/Blog.Core.Api/Blog.Core.xml b/Blog.Core.Api/Blog.Core.xml
index a510a92a..f4375977 100644
--- a/Blog.Core.Api/Blog.Core.xml
+++ b/Blog.Core.Api/Blog.Core.xml
@@ -877,5 +877,90 @@
全局路由前缀公约
+
+
+ Nacos配置文件变更事件
+
+
+
+
+ Nacos 配置文件监听事件
+
+
+
+
+ 重载方法
+
+
+
+
+
+
+ 执行
+
+
+
+
+
+
+ 停止
+
+
+
+
+
+
+ 配置监听事件
+
+
+
+
+ 收到配置文件变更
+
+
+
+
+
+
+
+
+
+
+ 监听事件
+
+
+
+
+
+
+
+
+
+
+
+
+ 订阅服务变化
+
+
+
+
+
+
+ 服务变更事件监听
+
+
+
+
+ 监听事件
+
+
+
+
+
+
+ 根据环境变量定向配置文件名称
+
+
+
diff --git a/Blog.Core.Api/NacosListenConfigurationTask.cs b/Blog.Core.Api/NacosListenConfigurationTask.cs
new file mode 100644
index 00000000..2cd949d1
--- /dev/null
+++ b/Blog.Core.Api/NacosListenConfigurationTask.cs
@@ -0,0 +1,91 @@
+using Microsoft.Extensions.Configuration;
+using Microsoft.Extensions.Hosting;
+using System;
+using System.Threading;
+using System.Threading.Tasks;
+using Nacos.V2;
+using Blog.Core.Common.Helper;
+
+namespace Blog.Core.Api
+{
+ ///
+ /// Nacos配置文件变更事件
+ ///
+ public class NacosListenConfigurationTask : BackgroundService
+ {
+ private readonly INacosConfigService _configClient;
+ ///
+ /// Nacos 配置文件监听事件
+ ///
+ private NacosConfigListener nacosConfigListener = new NacosConfigListener();
+
+ ///
+ /// 重载方法
+ ///
+ ///
+ ///
+ public NacosListenConfigurationTask(INacosConfigService configClient, IServiceProvider serviceProvider)
+ {
+ _configClient = configClient;
+ }
+
+ ///
+ /// 执行
+ ///
+ ///
+ ///
+ protected override async Task ExecuteAsync(CancellationToken stoppingToken)
+ {
+ try
+ {
+ // Add listener
+ await _configClient.AddListener("blog.Core.Api.json", "DEFAULT_GROUP", nacosConfigListener);
+ }
+ catch (Exception ex)
+ {
+ Serilog.Log.Information($"Nacos配置文件获取异常!!! " + ex.ToString());
+ }
+ }
+
+ ///
+ /// 停止
+ ///
+ ///
+ ///
+ public override async Task StopAsync(CancellationToken cancellationToken)
+ {
+ // Remove listener
+ await _configClient.RemoveListener("blog.Core.Api.json", "DEFAULT_GROUP", nacosConfigListener);
+
+ await base.StopAsync(cancellationToken);
+ }
+ }
+
+ ///
+ /// 配置监听事件
+ ///
+ public class NacosConfigListener : IListener
+ {
+ ///
+ /// 收到配置文件变更
+ ///
+ ///
+ public void ReceiveConfigInfo(string configInfo)
+ {
+
+ // Serilog.Log.Information($"Nacos配置文件更新!!! {DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")} [{configInfo}]");
+ var _configurationBuilder = new ConfigurationBuilder();
+ _configurationBuilder.Sources.Clear();
+ var buffer = System.Text.Encoding.Default.GetBytes(configInfo);
+ System.IO.MemoryStream ms = new System.IO.MemoryStream(buffer);
+ _configurationBuilder.AddJsonStream(ms);
+ var configuration = _configurationBuilder.Build();
+ ms.Dispose();
+
+ // 读取配置 将nacos配置中心读取到的配置 替换掉.net core 内存中的 configuration
+ // 当前监听到配置配置 应该重新断开 重连 刷新等一些中间件操作
+ // 比如 mq redis 等其他跟配置相关的中间件
+ JsonConfigSettings.Configuration = configuration;
+ }
+ }
+}
diff --git a/Blog.Core.Api/NacosListenNamingTask.cs b/Blog.Core.Api/NacosListenNamingTask.cs
new file mode 100644
index 00000000..ec3c13f4
--- /dev/null
+++ b/Blog.Core.Api/NacosListenNamingTask.cs
@@ -0,0 +1,105 @@
+using Blog.Core.Common.Helper;
+using Microsoft.Extensions.Configuration;
+using Microsoft.Extensions.Hosting;
+using Nacos.V2;
+using System;
+using System.Threading;
+using System.Threading.Tasks;
+
+namespace Blog.Core.Api
+{
+ ///
+ ///
+ ///
+ public class NacosListenNamingTask : BackgroundService
+ {
+ private readonly INacosNamingService _nacosNamingService;
+ IServiceProvider _serviceProvider;
+ IConfiguration _configuration;
+
+
+ ///
+ /// 监听事件
+ ///
+ private NamingServiceEventListener eventListener = new NamingServiceEventListener();
+
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ public NacosListenNamingTask(INacosNamingService nacosNamingService, IServiceProvider serviceProvider, IConfiguration configuration)
+ {
+ _nacosNamingService = nacosNamingService;
+ _serviceProvider = serviceProvider;
+ _configuration = configuration;
+
+ }
+
+ ///
+ /// 订阅服务变化
+ ///
+ ///
+ ///
+ protected override async Task ExecuteAsync(CancellationToken stoppingToken)
+ {
+ // Add listener
+ await _nacosNamingService.Subscribe(JsonConfigSettings.NacosServiceName, Nacos.V2.Common.Constants.DEFAULT_GROUP, eventListener);
+ var instance = new Nacos.V2.Naming.Dtos.Instance()
+ {
+ ServiceName = JsonConfigSettings.NacosServiceName,
+ ClusterName = Nacos.V2.Common.Constants.DEFAULT_CLUSTER_NAME,
+ Ip = IpHelper.GetCurrentIp(null),
+ Port = JsonConfigSettings.NacosPort,
+ Enabled = true,
+ Weight = 1000,// 权重 默认1000
+ Metadata = JsonConfigSettings.NacosMetadata
+ };
+ await _nacosNamingService.RegisterInstance(JsonConfigSettings.NacosServiceName, Nacos.V2.Common.Constants.DEFAULT_GROUP, instance);
+ }
+
+ // 程序停止
+ public override async Task StopAsync(CancellationToken cancellationToken)
+ {
+ // Remove listener
+ await _nacosNamingService.Unsubscribe(JsonConfigSettings.NacosServiceName, Nacos.V2.Common.Constants.DEFAULT_GROUP, eventListener);
+ await _nacosNamingService.DeregisterInstance(JsonConfigSettings.NacosServiceName, Nacos.V2.Common.Constants.DEFAULT_GROUP, IpHelper.GetCurrentIp(null), JsonConfigSettings.NacosPort);
+
+ await base.StopAsync(cancellationToken);
+ }
+ }
+
+ ///
+ /// 服务变更事件监听
+ ///
+ public class NamingServiceEventListener : IEventListener
+ {
+ ///
+ ///
+ ///
+ //public static redisHelper _redisCachqManager = new redisHelper();
+
+ ///
+ /// 监听事件
+ ///
+ ///
+ ///
+ public Task OnEvent(Nacos.V2.IEvent @event)
+ {
+ if (@event is Nacos.V2.Naming.Event.InstancesChangeEvent e)
+ {
+ Console.WriteLine($"==========收到服务变更事件=======》{Newtonsoft.Json.JsonConvert.SerializeObject(e)}");
+
+ // 配置有变动后 刷新redis配置 刷新 mq配置
+
+ //_redisCachqManager.DisposeRedisConnection();
+
+
+ Serilog.Log.Information($"收到服务变更事件!!! {DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")} [{e}]");
+ }
+
+ return Task.CompletedTask;
+ }
+ }
+}
diff --git a/Blog.Core.Api/Program.cs b/Blog.Core.Api/Program.cs
index da9a70e4..34143225 100644
--- a/Blog.Core.Api/Program.cs
+++ b/Blog.Core.Api/Program.cs
@@ -1,7 +1,9 @@
using Autofac.Extensions.DependencyInjection;
using Microsoft.AspNetCore.Hosting;
+using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
+using System;
using System.IO;
namespace Blog.Core
@@ -17,6 +19,11 @@ public static void Main(string[] args)
{
webBuilder
.UseStartup()
+ .ConfigureAppConfiguration((hostingContext, config) => {
+ config.Sources.Clear();
+ config.AddJsonFile("appsettings.json", optional: true, reloadOnChange: false)
+ .AddJsonFile($"appsettings{ GetAppSettingsConfigName() }json", optional: true, reloadOnChange: false);
+ })
.UseUrls("http://*:8081")
.ConfigureLogging((hostingContext, builder) =>
{
@@ -31,7 +38,8 @@ public static void Main(string[] args)
// 默认log4net.confg
builder.AddLog4Net(Path.Combine(Directory.GetCurrentDirectory(), "Log4net.config"));
- });
+ })
+ ;
})
// 生成承载 web 应用程序的 Microsoft.AspNetCore.Hosting.IWebHost。Build是WebHostBuilder最终的目的,将返回一个构造的WebHost,最终生成宿主。
.Build()
@@ -39,5 +47,23 @@ public static void Main(string[] args)
// ※※※※ 有异常,查看 Log 文件夹下的异常日志 ※※※※
.Run();
}
+
+
+ ///
+ /// 根据环境变量定向配置文件名称
+ ///
+ ///
+ private static string GetAppSettingsConfigName()
+ {
+ if (Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT") != null
+ && Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT") != "")
+ {
+ return $".{Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT")}.";
+ }
+ else
+ {
+ return ".";
+ }
+ }
}
}
diff --git a/Blog.Core.Api/Properties/launchSettings.json b/Blog.Core.Api/Properties/launchSettings.json
index 001e1040..75116a3b 100644
--- a/Blog.Core.Api/Properties/launchSettings.json
+++ b/Blog.Core.Api/Properties/launchSettings.json
@@ -13,7 +13,7 @@
"commandName": "Project",
"launchBrowser": true,
"environmentVariables": {
- "ASPNETCORE_ENVIRONMENT": "Development"
+ "ASPNETCORE_ENVIRONMENT": "dev"
},
"applicationUrl": "http://localhost:8081"
},
diff --git a/Blog.Core.Api/Startup.cs b/Blog.Core.Api/Startup.cs
index f75a7df5..a9e31d50 100644
--- a/Blog.Core.Api/Startup.cs
+++ b/Blog.Core.Api/Startup.cs
@@ -1,5 +1,7 @@
using Autofac;
+using Blog.Core.Api;
using Blog.Core.Common;
+using Blog.Core.Common.Helper;
using Blog.Core.Common.LogHelper;
using Blog.Core.Extensions;
using Blog.Core.Filter;
@@ -17,8 +19,12 @@
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection.Extensions;
using Microsoft.Extensions.Hosting;
+using Nacos.V2.DependencyInjection;
using Newtonsoft.Json;
using Newtonsoft.Json.Serialization;
+using System;
+using System.Collections.Generic;
+using System.Configuration;
using System.IdentityModel.Tokens.Jwt;
using System.Reflection;
using System.Text;
@@ -42,6 +48,40 @@ public Startup(IConfiguration configuration, IWebHostEnvironment env)
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
+ // 在实际生产工作中 本地开发是不需要注册nacos的 所以根据环境变量去判断
+ // 比如 开发环境 dev 测试环境 test 生产 prod 只有这几种环境变量的时候才需要去注册nacos
+ if (Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT") != null
+ && Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT") != "")
+ {
+ // 从当前配置取文件去注册naocs
+ services.AddNacosV2Config(x =>
+ {
+ x.ServerAddresses = JsonConfigSettings.NacosServerAddresses;
+ x.EndPoint = "";
+ x.Namespace = JsonConfigSettings.NacosNamespace;
+ x.DefaultTimeOut = JsonConfigSettings.NacosDefaultTimeOut;
+ x.ListenInterval = JsonConfigSettings.ListenInterval;
+ // swich to use http or rpc
+ x.ConfigUseRpc = false;
+ });
+ services.AddNacosV2Naming(x =>
+ {
+ x.ServerAddresses = JsonConfigSettings.NacosServerAddresses;
+ x.EndPoint = "";
+ x.Namespace = JsonConfigSettings.NacosNamespace;
+ x.DefaultTimeOut = JsonConfigSettings.NacosDefaultTimeOut;
+ x.ListenInterval = JsonConfigSettings.ListenInterval;
+ // swich to use http or rpc
+ x.NamingUseRpc = false;
+ });
+ services.AddHostedService(); //增加服务注入,删除事件
+ // 监听nacos中的配置中心 如果有新配置变更 执行相关逻辑
+ services.AddHostedService();//增加配置文件监听事件
+ }
+
+ services.AddSingleton(new Blog.Core.Common.Helper.ConfigurationManager((ConfigurationRoot)this.Configuration));
+ services.AddSingleton(Configuration);
+
// 以下code可能与文章中不一样,对代码做了封装,具体查看右侧 Extensions 文件夹.
services.AddSingleton(new Appsettings(Configuration));
services.AddSingleton(new LogLock(Env.ContentRootPath));
diff --git a/Blog.Core.Api/appsettings.Development.json b/Blog.Core.Api/appsettings.Development.json
deleted file mode 100644
index e203e940..00000000
--- a/Blog.Core.Api/appsettings.Development.json
+++ /dev/null
@@ -1,9 +0,0 @@
-{
- "Logging": {
- "LogLevel": {
- "Default": "Debug",
- "System": "Information",
- "Microsoft": "Information"
- }
- }
-}
diff --git a/Blog.Core.Api/appsettings.dev.json b/Blog.Core.Api/appsettings.dev.json
new file mode 100644
index 00000000..25fe0bfc
--- /dev/null
+++ b/Blog.Core.Api/appsettings.dev.json
@@ -0,0 +1,267 @@
+{
+ "urls": "http://*:8081", //web˿ڣIIS𣬰ȥ
+ "Logging": {
+ "LogLevel": {
+ "Default": "Information", //Defaultlog4netд벻־
+ "Blog.Core.AuthHelper.ApiResponseHandler": "Error"
+ },
+ "IncludeScopes": false,
+ "Debug": {
+ "LogLevel": {
+ "Default": "Warning"
+ }
+ },
+ "Console": {
+ "LogLevel": {
+ "Default": "Warning",
+ "Microsoft.Hosting.Lifetime": "Debug"
+ }
+ },
+ "Log4Net": {
+ "Name": "Blog.Core"
+ }
+ },
+ "AllowedHosts": "*",
+ "Redis": {
+ "ConnectionString": "127.0.0.1:6319,password=admin"
+ },
+ "RabbitMQ": {
+ "Enabled": false,
+ "Connection": "118.25.251.13",
+ "UserName": "",
+ "Password": "!",
+ "RetryCount": 3
+ },
+ "EventBus": {
+ "Enabled": false,
+ "SubscriptionClientName": "Blog.Core"
+ },
+ "AppSettings": {
+ "RedisCachingAOP": {
+ "Enabled": false
+ },
+ "MemoryCachingAOP": {
+ "Enabled": true
+ },
+ "LogAOP": {
+ "Enabled": false
+ },
+ "TranAOP": {
+ "Enabled": false
+ },
+ "SqlAOP": {
+ "Enabled": true,
+ "OutToLogFile": {
+ "Enabled": false
+ },
+ "OutToConsole": {
+ "Enabled": true
+ }
+ },
+ "Date": "2018-08-28",
+ "SeedDBEnabled": true, //ֻɱṹ
+ "SeedDBDataEnabled": true, //ɱ,ʼ
+ "Author": "Blog.Core",
+ "UseLoadTest": false
+ },
+
+ // MainDBΪҪConnIdֵ,öӦEnabledΪtrue
+ // *** MutiDBEnabled Ϊfalse ***
+ // *** MutiDBEnabled ΪtrueĴӿEnabledҲΪtrue **
+ // ÿƵhttps://www.bilibili.com/video/BV1BJ411B7mn?p=6
+
+ "MainDB": "WMBLOG_SQLITE", //ǰĿ⣬ӦַEnabledΪtrue
+ "MutiDBEnabled": false, //Ƿģʽ
+ "CQRSEnabled": false, //Ƿдģʽ,ǵģʽݿһ£綼SqlServer
+ "DBS": [
+ /*
+ Ӧ±ߵ DBType
+ MySql = 0,
+ SqlServer = 1,
+ Sqlite = 2,
+ Oracle = 3,
+ PostgreSQL = 4,
+ Dm = 5,//
+ Kdbndp = 6,//˴
+ */
+ {
+ "ConnId": "WMBLOG_SQLITE",
+ "DBType": 2,
+ "Enabled": true,
+ "HitRate": 50, // ֵԽȼԽ
+ "Connection": "WMBlog.db" //sqliteֻдݿ
+ },
+ {
+ "ConnId": "WMBLOG_MSSQL_1",
+ "DBType": 1,
+ "Enabled": false,
+ "HitRate": 40,
+ "Connection": "Data Source=(localdb)\\MSSQLLocalDB;Initial Catalog=WMBLOG_MSSQL_1;Integrated Security=True;Connect Timeout=30;Encrypt=False;TrustServerCertificate=False;ApplicationIntent=ReadWrite;MultiSubnetFailover=False",
+ "ProviderName": "System.Data.SqlClient"
+ },
+ {
+ "ConnId": "WMBLOG_MSSQL_2",
+ "DBType": 1,
+ "Enabled": false,
+ "HitRate": 30,
+ "Connection": "Data Source=(localdb)\\MSSQLLocalDB;Initial Catalog=WMBLOG_MSSQL_2;Integrated Security=True;Connect Timeout=30;Encrypt=False;TrustServerCertificate=False;ApplicationIntent=ReadWrite;MultiSubnetFailover=False",
+ "ProviderName": "System.Data.SqlClient"
+ },
+ {
+ "ConnId": "WMBLOG_MYSQL",
+ "DBType": 0,
+ "Enabled": false,
+ "HitRate": 20,
+ "Connection": "server=.;Database=ddd;Uid=root;Pwd=123456;Port=10060;Allow User Variables=True;"
+ },
+ {
+ "ConnId": "WMBLOG_MYSQL_2",
+ "DBType": 0,
+ "Enabled": true,
+ "HitRate": 20,
+ "Connection": "server=.;Database=blogcore001;Uid=root;Pwd=123456;Port=3096;Allow User Variables=True;"
+ },
+ {
+ "ConnId": "WMBLOG_ORACLE",
+ "DBType": 3,
+ "Enabled": false,
+ "HitRate": 10,
+ "Connection": "Data Source=127.0.0.1/ops;User ID=OPS;Password=123456;Persist Security Info=True;Connection Timeout=60;"
+ },
+ {
+ "ConnId": "WMBLOG_DM",
+ "DBType": 5,
+ "Enabled": false,
+ "HitRate": 10,
+ "Connection": "PORT=5236;DATABASE=DAMENG;HOST=localhost;PASSWORD=SYSDBA;USER ID=SYSDBA;"
+ },
+ {
+ "ConnId": "WMBLOG_KDBNDP",
+ "DBType": 6,
+ "Enabled": true,
+ "HitRate": 10,
+ "Connection": "Server=127.0.0.1;Port=54321;UID=SYSTEM;PWD=system;database=SQLSUGAR4XTEST1;"
+ }
+ ],
+ "Audience": {
+ "Secret": "sdfsdfsrty45634kkhllghtdgdfss345t678fs", //Ҫ̫̣16λ+
+ "SecretFile": "C:\\my-file\\blog.core.audience.secret.txt", //ȫݾSecret
+ "Issuer": "Blog.Core",
+ "Audience": "wr"
+ },
+ "Mongo": {
+ "ConnectionString": "mongodb://nosql.data",
+ "Database": "BlogCoreDb"
+ },
+ "Startup": {
+ "Cors": {
+ "PolicyName": "CorsIpAccess", //
+ "EnableAllIPs": false, //ΪtrueʱIPɷʡ
+ // ֶ֧˿ڣע˿ںźҪ/бˣlocalhost:8000/Ǵ
+ // ע⣬http://127.0.0.1:1818 http://localhost:1818 Dzһ
+ "IPs": "http://127.0.0.1:2364,http://localhost:2364"
+ },
+ "AppConfigAlert": {
+ "Enabled": true
+ },
+ "ApiName": "Blog.Core",
+ "IdentityServer4": {
+ "Enabled": false, // ĬfalseʾʹjwtΪtrueʾϵͳʹIds4ģʽ
+ "AuthorizationUrl": "http://localhost:5004", // ֤
+ "ApiName": "blog.core.api" // Դ
+ },
+ "RedisMq": {
+ "Enabled": false //redis Ϣ
+ },
+ "MiniProfiler": {
+ "Enabled": false //ܷ
+ }
+ },
+ "Middleware": {
+ "RequestResponseLog": {
+ "Enabled": false
+ },
+ "IPLog": {
+ "Enabled": true
+ },
+ "RecordAccessLogs": {
+ "Enabled": true,
+ "IgnoreApis": "/api/permission/getnavigationbar,/api/monitor/getids4users,/api/monitor/getaccesslogs,/api/monitor/server,/api/monitor/getactiveusers,/api/monitor/server,"
+ },
+ "SignalR": {
+ "Enabled": false
+ },
+ "QuartzNetJob": {
+ "Enabled": true
+ },
+ "Consul": {
+ "Enabled": false
+ },
+ "IpRateLimit": {
+ "Enabled": true
+ }
+ },
+ "IpRateLimiting": {
+ "EnableEndpointRateLimiting": true, //False: globally executed, true: executed for each
+ "StackBlockedRequests": false, //False: Number of rejections should be recorded on another counter
+ "RealIpHeader": "X-Real-IP",
+ "ClientIdHeader": "X-ClientId",
+ "IpWhitelist": [], //
+ "EndpointWhitelist": [ "get:/api/xxx", "*:/api/yyy" ],
+ "ClientWhitelist": [ "dev-client-1", "dev-client-2" ],
+ "QuotaExceededResponse": {
+ "Content": "{{\"status\":429,\"msg\":\"ʹƵԺ\",\"success\":false}}",
+ "ContentType": "application/json",
+ "StatusCode": 429
+ },
+ "HttpStatusCode": 429, //״̬
+ "GeneralRules": [ //api,βһҪ*
+ {
+ "Endpoint": "*:/api/blog*",
+ "Period": "1m",
+ "Limit": 20
+ },
+ {
+ "Endpoint": "*/api/*",
+ "Period": "1s",
+ "Limit": 3
+ },
+ {
+ "Endpoint": "*/api/*",
+ "Period": "1m",
+ "Limit": 30
+ },
+ {
+ "Endpoint": "*/api/*",
+ "Period": "12h",
+ "Limit": 500
+ }
+ ]
+
+ },
+ "ConsulSetting": {
+ "ServiceName": "BlogCoreService",
+ "ServiceIP": "localhost",
+ "ServicePort": "8081",
+ "ServiceHealthCheck": "/healthcheck",
+ "ConsulAddress": "http://localhost:8500"
+ },
+ "PayInfo": { //оۺ֧Ϣ
+ "MERCHANTID": "", //̻
+ "POSID": "", //̨
+ "BRANCHID": "", //к
+ "pubKey": "", //Կ
+ "USER_ID": "", //Ա
+ "PASSWORD": "", //
+ "OutAddress": "http://127.0.0.1:12345" //ַ
+ },
+ "nacos": {
+ "ServerAddresses": [ "http://ancba.neters.club:8918" ], // nacos ӵַ
+ "DefaultTimeOut": 15000, // Ĭϳʱʱ
+ "Namespace": "public", // ռ
+ "ListenInterval": 10000, // Ƶ
+ "ServiceName": "blog.Core.Api", //
+ "Port": "8081", // ˿ں
+ "RegisterEnabled": true // Ƿֱעnacos
+ }
+}
diff --git a/Blog.Core.Api/appsettings.prod.json b/Blog.Core.Api/appsettings.prod.json
new file mode 100644
index 00000000..2a10be98
--- /dev/null
+++ b/Blog.Core.Api/appsettings.prod.json
@@ -0,0 +1,258 @@
+{
+ "urls": "http://*:8081", //web˿ڣIIS𣬰ȥ
+ "Logging": {
+ "LogLevel": {
+ "Default": "Information", //Defaultlog4netд벻־
+ "Blog.Core.AuthHelper.ApiResponseHandler": "Error"
+ },
+ "IncludeScopes": false,
+ "Debug": {
+ "LogLevel": {
+ "Default": "Warning"
+ }
+ },
+ "Console": {
+ "LogLevel": {
+ "Default": "Warning",
+ "Microsoft.Hosting.Lifetime": "Debug"
+ }
+ },
+ "Log4Net": {
+ "Name": "Blog.Core"
+ }
+ },
+ "AllowedHosts": "*",
+ "Redis": {
+ "ConnectionString": "127.0.0.1:6319,password=admin"
+ },
+ "RabbitMQ": {
+ "Enabled": false,
+ "Connection": "118.25.251.13",
+ "UserName": "",
+ "Password": "!",
+ "RetryCount": 3
+ },
+ "EventBus": {
+ "Enabled": false,
+ "SubscriptionClientName": "Blog.Core"
+ },
+ "AppSettings": {
+ "RedisCachingAOP": {
+ "Enabled": false
+ },
+ "MemoryCachingAOP": {
+ "Enabled": true
+ },
+ "LogAOP": {
+ "Enabled": false
+ },
+ "TranAOP": {
+ "Enabled": false
+ },
+ "SqlAOP": {
+ "Enabled": true,
+ "OutToLogFile": {
+ "Enabled": false
+ },
+ "OutToConsole": {
+ "Enabled": true
+ }
+ },
+ "Date": "2018-08-28",
+ "SeedDBEnabled": true, //ֻɱṹ
+ "SeedDBDataEnabled": true, //ɱ,ʼ
+ "Author": "Blog.Core",
+ "UseLoadTest": false
+ },
+
+ // MainDBΪҪConnIdֵ,öӦEnabledΪtrue
+ // *** MutiDBEnabled Ϊfalse ***
+ // *** MutiDBEnabled ΪtrueĴӿEnabledҲΪtrue **
+ // ÿƵhttps://www.bilibili.com/video/BV1BJ411B7mn?p=6
+
+ "MainDB": "WMBLOG_SQLITE", //ǰĿ⣬ӦַEnabledΪtrue
+ "MutiDBEnabled": false, //Ƿģʽ
+ "CQRSEnabled": false, //Ƿдģʽ,ǵģʽݿһ£綼SqlServer
+ "DBS": [
+ /*
+ Ӧ±ߵ DBType
+ MySql = 0,
+ SqlServer = 1,
+ Sqlite = 2,
+ Oracle = 3,
+ PostgreSQL = 4,
+ Dm = 5,//
+ Kdbndp = 6,//˴
+ */
+ {
+ "ConnId": "WMBLOG_SQLITE",
+ "DBType": 2,
+ "Enabled": true,
+ "HitRate": 50, // ֵԽȼԽ
+ "Connection": "WMBlog.db" //sqliteֻдݿ
+ },
+ {
+ "ConnId": "WMBLOG_MSSQL_1",
+ "DBType": 1,
+ "Enabled": false,
+ "HitRate": 40,
+ "Connection": "Data Source=(localdb)\\MSSQLLocalDB;Initial Catalog=WMBLOG_MSSQL_1;Integrated Security=True;Connect Timeout=30;Encrypt=False;TrustServerCertificate=False;ApplicationIntent=ReadWrite;MultiSubnetFailover=False",
+ "ProviderName": "System.Data.SqlClient"
+ },
+ {
+ "ConnId": "WMBLOG_MSSQL_2",
+ "DBType": 1,
+ "Enabled": false,
+ "HitRate": 30,
+ "Connection": "Data Source=(localdb)\\MSSQLLocalDB;Initial Catalog=WMBLOG_MSSQL_2;Integrated Security=True;Connect Timeout=30;Encrypt=False;TrustServerCertificate=False;ApplicationIntent=ReadWrite;MultiSubnetFailover=False",
+ "ProviderName": "System.Data.SqlClient"
+ },
+ {
+ "ConnId": "WMBLOG_MYSQL",
+ "DBType": 0,
+ "Enabled": false,
+ "HitRate": 20,
+ "Connection": "server=.;Database=ddd;Uid=root;Pwd=123456;Port=10060;Allow User Variables=True;"
+ },
+ {
+ "ConnId": "WMBLOG_MYSQL_2",
+ "DBType": 0,
+ "Enabled": true,
+ "HitRate": 20,
+ "Connection": "server=.;Database=blogcore001;Uid=root;Pwd=123456;Port=3096;Allow User Variables=True;"
+ },
+ {
+ "ConnId": "WMBLOG_ORACLE",
+ "DBType": 3,
+ "Enabled": false,
+ "HitRate": 10,
+ "Connection": "Data Source=127.0.0.1/ops;User ID=OPS;Password=123456;Persist Security Info=True;Connection Timeout=60;"
+ },
+ {
+ "ConnId": "WMBLOG_DM",
+ "DBType": 5,
+ "Enabled": false,
+ "HitRate": 10,
+ "Connection": "PORT=5236;DATABASE=DAMENG;HOST=localhost;PASSWORD=SYSDBA;USER ID=SYSDBA;"
+ },
+ {
+ "ConnId": "WMBLOG_KDBNDP",
+ "DBType": 6,
+ "Enabled": true,
+ "HitRate": 10,
+ "Connection": "Server=127.0.0.1;Port=54321;UID=SYSTEM;PWD=system;database=SQLSUGAR4XTEST1;"
+ }
+ ],
+ "Audience": {
+ "Secret": "sdfsdfsrty45634kkhllghtdgdfss345t678fs", //Ҫ̫̣16λ+
+ "SecretFile": "C:\\my-file\\blog.core.audience.secret.txt", //ȫݾSecret
+ "Issuer": "Blog.Core",
+ "Audience": "wr"
+ },
+ "Mongo": {
+ "ConnectionString": "mongodb://nosql.data",
+ "Database": "BlogCoreDb"
+ },
+ "Startup": {
+ "Cors": {
+ "PolicyName": "CorsIpAccess", //
+ "EnableAllIPs": false, //ΪtrueʱIPɷʡ
+ // ֶ֧˿ڣע˿ںźҪ/бˣlocalhost:8000/Ǵ
+ // ע⣬http://127.0.0.1:1818 http://localhost:1818 Dzһ
+ "IPs": "http://127.0.0.1:2364,http://localhost:2364"
+ },
+ "AppConfigAlert": {
+ "Enabled": true
+ },
+ "ApiName": "Blog.Core",
+ "IdentityServer4": {
+ "Enabled": false, // ĬfalseʾʹjwtΪtrueʾϵͳʹIds4ģʽ
+ "AuthorizationUrl": "http://localhost:5004", // ֤
+ "ApiName": "blog.core.api" // Դ
+ },
+ "RedisMq": {
+ "Enabled": false //redis Ϣ
+ },
+ "MiniProfiler": {
+ "Enabled": false //ܷ
+ }
+ },
+ "Middleware": {
+ "RequestResponseLog": {
+ "Enabled": false
+ },
+ "IPLog": {
+ "Enabled": true
+ },
+ "RecordAccessLogs": {
+ "Enabled": true,
+ "IgnoreApis": "/api/permission/getnavigationbar,/api/monitor/getids4users,/api/monitor/getaccesslogs,/api/monitor/server,/api/monitor/getactiveusers,/api/monitor/server,"
+ },
+ "SignalR": {
+ "Enabled": false
+ },
+ "QuartzNetJob": {
+ "Enabled": true
+ },
+ "Consul": {
+ "Enabled": false
+ },
+ "IpRateLimit": {
+ "Enabled": true
+ }
+ },
+ "IpRateLimiting": {
+ "EnableEndpointRateLimiting": true, //False: globally executed, true: executed for each
+ "StackBlockedRequests": false, //False: Number of rejections should be recorded on another counter
+ "RealIpHeader": "X-Real-IP",
+ "ClientIdHeader": "X-ClientId",
+ "IpWhitelist": [], //
+ "EndpointWhitelist": [ "get:/api/xxx", "*:/api/yyy" ],
+ "ClientWhitelist": [ "dev-client-1", "dev-client-2" ],
+ "QuotaExceededResponse": {
+ "Content": "{{\"status\":429,\"msg\":\"ʹƵԺ\",\"success\":false}}",
+ "ContentType": "application/json",
+ "StatusCode": 429
+ },
+ "HttpStatusCode": 429, //״̬
+ "GeneralRules": [ //api,βһҪ*
+ {
+ "Endpoint": "*:/api/blog*",
+ "Period": "1m",
+ "Limit": 20
+ },
+ {
+ "Endpoint": "*/api/*",
+ "Period": "1s",
+ "Limit": 3
+ },
+ {
+ "Endpoint": "*/api/*",
+ "Period": "1m",
+ "Limit": 30
+ },
+ {
+ "Endpoint": "*/api/*",
+ "Period": "12h",
+ "Limit": 500
+ }
+ ]
+
+ },
+ "ConsulSetting": {
+ "ServiceName": "BlogCoreService",
+ "ServiceIP": "localhost",
+ "ServicePort": "8081",
+ "ServiceHealthCheck": "/healthcheck",
+ "ConsulAddress": "http://localhost:8500"
+ },
+ "PayInfo": { //оۺ֧Ϣ
+ "MERCHANTID": "", //̻
+ "POSID": "", //̨
+ "BRANCHID": "", //к
+ "pubKey": "", //Կ
+ "USER_ID": "", //Ա
+ "PASSWORD": "", //
+ "OutAddress": "http://127.0.0.1:12345" //ַ
+ }
+}
diff --git a/Blog.Core.Api/appsettings.test.json b/Blog.Core.Api/appsettings.test.json
new file mode 100644
index 00000000..2a10be98
--- /dev/null
+++ b/Blog.Core.Api/appsettings.test.json
@@ -0,0 +1,258 @@
+{
+ "urls": "http://*:8081", //web˿ڣIIS𣬰ȥ
+ "Logging": {
+ "LogLevel": {
+ "Default": "Information", //Defaultlog4netд벻־
+ "Blog.Core.AuthHelper.ApiResponseHandler": "Error"
+ },
+ "IncludeScopes": false,
+ "Debug": {
+ "LogLevel": {
+ "Default": "Warning"
+ }
+ },
+ "Console": {
+ "LogLevel": {
+ "Default": "Warning",
+ "Microsoft.Hosting.Lifetime": "Debug"
+ }
+ },
+ "Log4Net": {
+ "Name": "Blog.Core"
+ }
+ },
+ "AllowedHosts": "*",
+ "Redis": {
+ "ConnectionString": "127.0.0.1:6319,password=admin"
+ },
+ "RabbitMQ": {
+ "Enabled": false,
+ "Connection": "118.25.251.13",
+ "UserName": "",
+ "Password": "!",
+ "RetryCount": 3
+ },
+ "EventBus": {
+ "Enabled": false,
+ "SubscriptionClientName": "Blog.Core"
+ },
+ "AppSettings": {
+ "RedisCachingAOP": {
+ "Enabled": false
+ },
+ "MemoryCachingAOP": {
+ "Enabled": true
+ },
+ "LogAOP": {
+ "Enabled": false
+ },
+ "TranAOP": {
+ "Enabled": false
+ },
+ "SqlAOP": {
+ "Enabled": true,
+ "OutToLogFile": {
+ "Enabled": false
+ },
+ "OutToConsole": {
+ "Enabled": true
+ }
+ },
+ "Date": "2018-08-28",
+ "SeedDBEnabled": true, //ֻɱṹ
+ "SeedDBDataEnabled": true, //ɱ,ʼ
+ "Author": "Blog.Core",
+ "UseLoadTest": false
+ },
+
+ // MainDBΪҪConnIdֵ,öӦEnabledΪtrue
+ // *** MutiDBEnabled Ϊfalse ***
+ // *** MutiDBEnabled ΪtrueĴӿEnabledҲΪtrue **
+ // ÿƵhttps://www.bilibili.com/video/BV1BJ411B7mn?p=6
+
+ "MainDB": "WMBLOG_SQLITE", //ǰĿ⣬ӦַEnabledΪtrue
+ "MutiDBEnabled": false, //Ƿģʽ
+ "CQRSEnabled": false, //Ƿдģʽ,ǵģʽݿһ£綼SqlServer
+ "DBS": [
+ /*
+ Ӧ±ߵ DBType
+ MySql = 0,
+ SqlServer = 1,
+ Sqlite = 2,
+ Oracle = 3,
+ PostgreSQL = 4,
+ Dm = 5,//
+ Kdbndp = 6,//˴
+ */
+ {
+ "ConnId": "WMBLOG_SQLITE",
+ "DBType": 2,
+ "Enabled": true,
+ "HitRate": 50, // ֵԽȼԽ
+ "Connection": "WMBlog.db" //sqliteֻдݿ
+ },
+ {
+ "ConnId": "WMBLOG_MSSQL_1",
+ "DBType": 1,
+ "Enabled": false,
+ "HitRate": 40,
+ "Connection": "Data Source=(localdb)\\MSSQLLocalDB;Initial Catalog=WMBLOG_MSSQL_1;Integrated Security=True;Connect Timeout=30;Encrypt=False;TrustServerCertificate=False;ApplicationIntent=ReadWrite;MultiSubnetFailover=False",
+ "ProviderName": "System.Data.SqlClient"
+ },
+ {
+ "ConnId": "WMBLOG_MSSQL_2",
+ "DBType": 1,
+ "Enabled": false,
+ "HitRate": 30,
+ "Connection": "Data Source=(localdb)\\MSSQLLocalDB;Initial Catalog=WMBLOG_MSSQL_2;Integrated Security=True;Connect Timeout=30;Encrypt=False;TrustServerCertificate=False;ApplicationIntent=ReadWrite;MultiSubnetFailover=False",
+ "ProviderName": "System.Data.SqlClient"
+ },
+ {
+ "ConnId": "WMBLOG_MYSQL",
+ "DBType": 0,
+ "Enabled": false,
+ "HitRate": 20,
+ "Connection": "server=.;Database=ddd;Uid=root;Pwd=123456;Port=10060;Allow User Variables=True;"
+ },
+ {
+ "ConnId": "WMBLOG_MYSQL_2",
+ "DBType": 0,
+ "Enabled": true,
+ "HitRate": 20,
+ "Connection": "server=.;Database=blogcore001;Uid=root;Pwd=123456;Port=3096;Allow User Variables=True;"
+ },
+ {
+ "ConnId": "WMBLOG_ORACLE",
+ "DBType": 3,
+ "Enabled": false,
+ "HitRate": 10,
+ "Connection": "Data Source=127.0.0.1/ops;User ID=OPS;Password=123456;Persist Security Info=True;Connection Timeout=60;"
+ },
+ {
+ "ConnId": "WMBLOG_DM",
+ "DBType": 5,
+ "Enabled": false,
+ "HitRate": 10,
+ "Connection": "PORT=5236;DATABASE=DAMENG;HOST=localhost;PASSWORD=SYSDBA;USER ID=SYSDBA;"
+ },
+ {
+ "ConnId": "WMBLOG_KDBNDP",
+ "DBType": 6,
+ "Enabled": true,
+ "HitRate": 10,
+ "Connection": "Server=127.0.0.1;Port=54321;UID=SYSTEM;PWD=system;database=SQLSUGAR4XTEST1;"
+ }
+ ],
+ "Audience": {
+ "Secret": "sdfsdfsrty45634kkhllghtdgdfss345t678fs", //Ҫ̫̣16λ+
+ "SecretFile": "C:\\my-file\\blog.core.audience.secret.txt", //ȫݾSecret
+ "Issuer": "Blog.Core",
+ "Audience": "wr"
+ },
+ "Mongo": {
+ "ConnectionString": "mongodb://nosql.data",
+ "Database": "BlogCoreDb"
+ },
+ "Startup": {
+ "Cors": {
+ "PolicyName": "CorsIpAccess", //
+ "EnableAllIPs": false, //ΪtrueʱIPɷʡ
+ // ֶ֧˿ڣע˿ںźҪ/бˣlocalhost:8000/Ǵ
+ // ע⣬http://127.0.0.1:1818 http://localhost:1818 Dzһ
+ "IPs": "http://127.0.0.1:2364,http://localhost:2364"
+ },
+ "AppConfigAlert": {
+ "Enabled": true
+ },
+ "ApiName": "Blog.Core",
+ "IdentityServer4": {
+ "Enabled": false, // ĬfalseʾʹjwtΪtrueʾϵͳʹIds4ģʽ
+ "AuthorizationUrl": "http://localhost:5004", // ֤
+ "ApiName": "blog.core.api" // Դ
+ },
+ "RedisMq": {
+ "Enabled": false //redis Ϣ
+ },
+ "MiniProfiler": {
+ "Enabled": false //ܷ
+ }
+ },
+ "Middleware": {
+ "RequestResponseLog": {
+ "Enabled": false
+ },
+ "IPLog": {
+ "Enabled": true
+ },
+ "RecordAccessLogs": {
+ "Enabled": true,
+ "IgnoreApis": "/api/permission/getnavigationbar,/api/monitor/getids4users,/api/monitor/getaccesslogs,/api/monitor/server,/api/monitor/getactiveusers,/api/monitor/server,"
+ },
+ "SignalR": {
+ "Enabled": false
+ },
+ "QuartzNetJob": {
+ "Enabled": true
+ },
+ "Consul": {
+ "Enabled": false
+ },
+ "IpRateLimit": {
+ "Enabled": true
+ }
+ },
+ "IpRateLimiting": {
+ "EnableEndpointRateLimiting": true, //False: globally executed, true: executed for each
+ "StackBlockedRequests": false, //False: Number of rejections should be recorded on another counter
+ "RealIpHeader": "X-Real-IP",
+ "ClientIdHeader": "X-ClientId",
+ "IpWhitelist": [], //
+ "EndpointWhitelist": [ "get:/api/xxx", "*:/api/yyy" ],
+ "ClientWhitelist": [ "dev-client-1", "dev-client-2" ],
+ "QuotaExceededResponse": {
+ "Content": "{{\"status\":429,\"msg\":\"ʹƵԺ\",\"success\":false}}",
+ "ContentType": "application/json",
+ "StatusCode": 429
+ },
+ "HttpStatusCode": 429, //״̬
+ "GeneralRules": [ //api,βһҪ*
+ {
+ "Endpoint": "*:/api/blog*",
+ "Period": "1m",
+ "Limit": 20
+ },
+ {
+ "Endpoint": "*/api/*",
+ "Period": "1s",
+ "Limit": 3
+ },
+ {
+ "Endpoint": "*/api/*",
+ "Period": "1m",
+ "Limit": 30
+ },
+ {
+ "Endpoint": "*/api/*",
+ "Period": "12h",
+ "Limit": 500
+ }
+ ]
+
+ },
+ "ConsulSetting": {
+ "ServiceName": "BlogCoreService",
+ "ServiceIP": "localhost",
+ "ServicePort": "8081",
+ "ServiceHealthCheck": "/healthcheck",
+ "ConsulAddress": "http://localhost:8500"
+ },
+ "PayInfo": { //оۺ֧Ϣ
+ "MERCHANTID": "", //̻
+ "POSID": "", //̨
+ "BRANCHID": "", //к
+ "pubKey": "", //Կ
+ "USER_ID": "", //Ա
+ "PASSWORD": "", //
+ "OutAddress": "http://127.0.0.1:12345" //ַ
+ }
+}
diff --git a/Blog.Core.Common/Helper/IpHelper.cs b/Blog.Core.Common/Helper/IpHelper.cs
new file mode 100644
index 00000000..3f391e3b
--- /dev/null
+++ b/Blog.Core.Common/Helper/IpHelper.cs
@@ -0,0 +1,51 @@
+using System.Linq;
+using System.Net;
+using System.Net.NetworkInformation;
+using System.Net.Sockets;
+
+namespace Blog.Core.Common.Helper
+{
+ public class IpHelper
+ {
+ ///
+ /// 获取当前IP地址
+ ///
+ ///
+ ///
+ public static string GetCurrentIp(string preferredNetworks)
+ {
+ var instanceIp = "127.0.0.1";
+
+ try
+ {
+ // 获取可用网卡
+ var nics = NetworkInterface.GetAllNetworkInterfaces()?.Where(network => network.OperationalStatus == OperationalStatus.Up);
+
+ // 获取所有可用网卡IP信息
+ var ipCollection = nics?.Select(x => x.GetIPProperties())?.SelectMany(x => x.UnicastAddresses);
+
+ foreach (var ipadd in ipCollection)
+ {
+ if (!IPAddress.IsLoopback(ipadd.Address) && ipadd.Address.AddressFamily == AddressFamily.InterNetwork)
+ {
+ if (string.IsNullOrEmpty(preferredNetworks))
+ {
+ instanceIp = ipadd.Address.ToString();
+ break;
+ }
+
+ if (!ipadd.Address.ToString().StartsWith(preferredNetworks)) continue;
+ instanceIp = ipadd.Address.ToString();
+ break;
+ }
+ }
+ }
+ catch
+ {
+ // ignored
+ }
+
+ return instanceIp;
+ }
+ }
+}
diff --git a/Blog.Core.Common/Helper/JsonConfigUtils.cs b/Blog.Core.Common/Helper/JsonConfigUtils.cs
new file mode 100644
index 00000000..f04fff19
--- /dev/null
+++ b/Blog.Core.Common/Helper/JsonConfigUtils.cs
@@ -0,0 +1,289 @@
+using Microsoft.Extensions.Configuration;
+using Microsoft.Extensions.Configuration.Json;
+using Microsoft.Extensions.DependencyInjection;
+using Microsoft.Extensions.Options;
+using System;
+using System.Collections.Generic;
+
+namespace Blog.Core.Common.Helper
+{
+ ///
+ /// Json 配置文件通用类
+ ///
+ public static class JsonConfigUtils
+ {
+ #region 变量
+
+ ///
+ /// 锁
+ ///
+ private static object __Lock__ = new object();
+
+ #endregion
+
+ ///
+ /// 读取配置文件的信息
+ ///
+ ///
+ /// 要读取json的名称
+ /// 要读取的json节点名称
+ ///
+ public static T GetAppSettings(IConfiguration config, string AppSettingsFileName, string key) where T : class, new()
+ {
+ lock (__Lock__)
+ {
+ if (config == null)
+ {
+ config = new ConfigurationBuilder()
+ .Add(new JsonConfigurationSource
+ {
+ Path = AppSettingsFileName,
+ Optional = false,
+ ReloadOnChange = true
+ })
+ .Build();
+ }
+ var appconfig = new ServiceCollection()
+ .AddOptions()
+ .Configure(config.GetSection(key))
+ .BuildServiceProvider()
+ .GetService>()
+ .Value;
+
+ return appconfig;
+ }
+ }
+
+
+ public static string GetJson(string jsonPath, string key)
+ {
+ IConfiguration config = new ConfigurationBuilder().AddJsonFile(jsonPath).Build(); //json文件地址
+ string s = config.GetSection(key).Value; //json某个对象
+ return s;
+ }
+ }
+
+
+ ///
+ /// 配置文件管理器
+ ///
+ public interface IConfigurationManager
+ {
+ T GetAppConfig(string key, T defaultValue = default(T));
+ }
+
+ ///
+ /// 配置读取 根据环境变量
+ ///
+ public class ConfigurationManager : IConfigurationManager
+ {
+ private readonly IConfigurationRoot config;
+
+ public ConfigurationManager(IConfigurationRoot _config)
+ {
+ config = _config;
+ }
+
+ public T GetAppConfig(string key, T defaultValue = default(T))
+ {
+ T value = default(T);
+ try
+ {
+ var env = Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT");
+ var builder = new ConfigurationBuilder().AddJsonFile("appsettings.json", true, false)
+ .AddJsonFile($"appsettings.{env}.json", true, false)
+ .AddEnvironmentVariables();
+
+ var configuration = builder.Build();
+ value = (T)Convert.ChangeType(configuration[key], typeof(T));
+ if (value == null)
+ value = defaultValue;
+ }
+ catch (Exception ex)
+ {
+ Serilog.Log.Information($"配置文件管理器异常:,{ ex.ToString() }");
+ value = defaultValue;
+ }
+
+ return value;
+ }
+ }
+
+
+ #region Nacos 配置清单
+ public class JsonConfigSettings
+ {
+ // 从nacos 读取到的系统配置信息
+ public static IConfiguration Configuration { get; set; }
+
+
+ ///
+ /// 配置文件名称常量
+ ///
+ private static string AppSettingsFileName = $"appsettings{ GetAppSettingsConfigName() }json";
+
+ ///
+ /// 根据环境变量定向配置文件名称
+ ///
+ ///
+ private static string GetAppSettingsConfigName()
+ {
+ if (Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT") != null
+ && Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT") != "")
+ {
+ return $".{Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT")}.";
+ }
+ else
+ {
+ return ".";
+ }
+ }
+ ///
+ /// 获取Nacos配置
+ ///
+ public static List NacosServerAddresses
+ {
+ get
+ {
+ return JsonConfigUtils.GetAppSettings(Configuration, AppSettingsFileName, "nacos").ServerAddresses;
+ }
+ }
+
+ ///
+ /// 获取Nacos配置
+ ///
+ public static int NacosDefaultTimeOut
+ {
+ get
+ {
+ return JsonConfigUtils.GetAppSettings(Configuration, AppSettingsFileName, "nacos").DefaultTimeOut;
+ }
+ }
+
+ ///
+ /// 获取Nacos配置
+ ///
+ public static string NacosNamespace
+ {
+ get
+ {
+ return JsonConfigUtils.GetAppSettings(Configuration, AppSettingsFileName, "nacos").Namespace;
+ }
+ }
+ ///
+ /// 获取Nacos配置
+ ///
+ public static string NacosServiceName
+ {
+ get
+ {
+ return JsonConfigUtils.GetAppSettings(Configuration, AppSettingsFileName, "nacos").ServiceName;
+ }
+ }
+
+ ///
+ /// 获取Nacos配置
+ ///
+ public static int ListenInterval
+ {
+ get
+ {
+ return JsonConfigUtils.GetAppSettings(Configuration, AppSettingsFileName, "nacos").ListenInterval;
+ }
+ }
+
+ ///
+ /// 获取Nacos配置
+ ///
+ public static string NacosIp
+ {
+ get
+ {
+ return JsonConfigUtils.GetAppSettings(Configuration, AppSettingsFileName, "nacos").Ip;
+
+ }
+ }
+ ///
+ /// 获取Nacos配置
+ ///
+ public static int NacosPort
+ {
+ get
+ {
+ return int.Parse(JsonConfigUtils.GetAppSettings(Configuration, AppSettingsFileName, "nacos").Port);
+ }
+ }
+ ///
+ /// 获取Nacos配置
+ ///
+ public static bool NacosRegisterEnabled
+ {
+ get
+ {
+ return JsonConfigUtils.GetAppSettings(Configuration, AppSettingsFileName, "nacos").RegisterEnabled;
+ }
+ }
+
+ ///
+ /// 获取Nacos配置
+ ///
+ public static Dictionary NacosMetadata
+ {
+ get
+ {
+ return JsonConfigUtils.GetAppSettings(Configuration, AppSettingsFileName, "nacos").Metadata;
+ }
+ }
+
+ #endregion
+
+ #region Nacos配置
+
+ ///
+ /// Nacos配置实体
+ ///
+ public class NacosConfigDTO
+ {
+ ///
+ /// 服务IP地址
+ ///
+ public List ServerAddresses { get; set; }
+ ///
+ /// 默认超时时间
+ ///
+ public int DefaultTimeOut { get; set; }
+ ///
+ /// 监听间隔
+ ///
+ public int ListenInterval { get; set; }
+ ///
+ /// 服务命名空间
+ ///
+ public string Namespace { get; set; }
+ ///
+ /// 服务名称
+ ///
+ public string ServiceName { get; set; }
+ ///
+ /// IP地址
+ ///
+ public string Ip { get; set; }
+ ///
+ /// 端口
+ ///
+ public string Port { get; set; }
+ ///
+ /// 服务命名空间
+ ///
+ public bool RegisterEnabled { get; set; }
+ ///
+ /// 其他配置
+ ///
+ public Dictionary Metadata { get; set; }
+ }
+
+ #endregion
+
+ }
+
+}
From ef935c0f554140a21fdce69191e5682a6a14db1b Mon Sep 17 00:00:00 2001
From: tianyu
Date: Wed, 28 Jul 2021 12:32:44 +0800
Subject: [PATCH 050/456] bhsw
---
Blog.Core.Api/Controllers/NacosController.cs | 124 +++++++++++++++++++
1 file changed, 124 insertions(+)
create mode 100644 Blog.Core.Api/Controllers/NacosController.cs
diff --git a/Blog.Core.Api/Controllers/NacosController.cs b/Blog.Core.Api/Controllers/NacosController.cs
new file mode 100644
index 00000000..5c037435
--- /dev/null
+++ b/Blog.Core.Api/Controllers/NacosController.cs
@@ -0,0 +1,124 @@
+using Blog.Core.Common.Helper;
+using Blog.Core.Controllers;
+using Blog.Core.Model;
+using Microsoft.AspNetCore.Authorization;
+using Microsoft.AspNetCore.Mvc;
+using Nacos.V2;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading.Tasks;
+
+namespace Blog.Core.Api.Controllers
+{
+ ///
+ /// nacos
+ ///
+ [Produces("application/json")]
+ [Route("api/Login")]
+ [AllowAnonymous]
+ public class NacosController : BaseApiCpntroller
+ {
+
+ #region 变量
+
+ ///
+ /// INacosNamingService
+ ///
+ private readonly INacosNamingService NacosNamingService;
+
+ #endregion
+
+ #region 重载
+ ///
+ ///
+ ///
+ ///
+ public NacosController(INacosNamingService nacosNamingService)
+ {
+ NacosNamingService = nacosNamingService;
+ }
+
+ #endregion
+
+ ///
+ /// 获取Nacos 状态
+ ///
+ ///
+ [HttpGet]
+ public async Task> GetStatus()
+ {
+ var data = new MessageModel();
+ var instances = await NacosNamingService.GetAllInstances(JsonConfigSettings.NacosServiceName);
+ if (instances == null || instances.Count == 0)
+ {
+ data.status = 406;
+ data.msg = "DOWN";
+ data.success = false;
+ return data;
+ }
+ // 获取当前程序IP
+ var currentIp = IpHelper.GetCurrentIp(null);
+ bool isUp = false;
+ instances.ForEach(item =>
+ {
+ if (item.Ip == currentIp)
+ isUp = true;
+ });
+ // var baseUrl = await NacosNamingService.GetServerStatus();
+ if (isUp)
+ {
+ data.status = 200;
+ data.msg = "UP";
+ data.success = true;
+ return data;
+ }
+ else
+ {
+ data.status = 406;
+ data.msg = "DOWN";
+ data.success = false;
+ return data;
+ }
+ }
+
+ ///
+ /// 服务上线
+ ///
+ ///
+
+ [HttpGet]
+ public async Task> Register()
+ {
+ var data = new MessageModel();
+ var instance = new Nacos.V2.Naming.Dtos.Instance()
+ {
+ ServiceName = JsonConfigSettings.NacosServiceName,
+ ClusterName = Nacos.V2.Common.Constants.DEFAULT_CLUSTER_NAME,
+ Ip = IpHelper.GetCurrentIp(null),
+ Port = JsonConfigSettings.NacosPort,
+ Enabled = true,
+ Weight = 100,
+ Metadata = JsonConfigSettings.NacosMetadata
+ };
+ await NacosNamingService.RegisterInstance(JsonConfigSettings.NacosServiceName, Nacos.V2.Common.Constants.DEFAULT_GROUP, instance);
+ data.success = true;
+ data.msg = "SUCCESS";
+ return data;
+ }
+
+ ///
+ /// 服务下线
+ ///
+ ///
+ [HttpGet]
+ public async Task> Deregister()
+ {
+ var data = new MessageModel();
+ await NacosNamingService.DeregisterInstance(JsonConfigSettings.NacosServiceName, Nacos.V2.Common.Constants.DEFAULT_GROUP, IpHelper.GetCurrentIp(null), JsonConfigSettings.NacosPort);
+ data.success = true;
+ data.msg = "SUCCESS";
+ return data;
+ }
+ }
+}
From 4118ec293026aea8bb7b992b6d84320976de1496 Mon Sep 17 00:00:00 2001
From: anjoy8 <3143422472@qq.com>
Date: Wed, 28 Jul 2021 13:59:43 +0800
Subject: [PATCH 051/456] fix: config nacos is use
---
Blog.Core.Api/Blog.Core.Api.csproj | 158 +++++++++---------
Blog.Core.Api/Blog.Core.xml | 113 ++++---------
Blog.Core.Api/Startup.cs | 43 +----
Blog.Core.Api/appsettings.dev.json | 92 +++++-----
Blog.Core.Api/appsettings.json | 3 +
Blog.Core.Api/appsettings.prod.json | 78 ++++-----
Blog.Core.Api/appsettings.test.json | 78 ++++-----
.../Blog.Core.Extensions.csproj | 6 +
.../NacosListenConfigurationTask.cs | 10 +-
.../NacosConfig}/NacosListenNamingTask.cs | 13 +-
.../ServiceExtensions/NacosSetup.cs | 57 +++++++
.../DependencyInjection/DI_Test.cs | 4 +-
12 files changed, 311 insertions(+), 344 deletions(-)
rename {Blog.Core.Api => Blog.Core.Extensions/NacosConfig}/NacosListenConfigurationTask.cs (92%)
rename {Blog.Core.Api => Blog.Core.Extensions/NacosConfig}/NacosListenNamingTask.cs (91%)
create mode 100644 Blog.Core.Extensions/ServiceExtensions/NacosSetup.cs
diff --git a/Blog.Core.Api/Blog.Core.Api.csproj b/Blog.Core.Api/Blog.Core.Api.csproj
index fef5e938..da5c4e05 100644
--- a/Blog.Core.Api/Blog.Core.Api.csproj
+++ b/Blog.Core.Api/Blog.Core.Api.csproj
@@ -1,99 +1,91 @@
-
+
- Exe
+ Exe
- net5.0
-
- OutOfProcess
- Linux
- true
-
+ net5.0
+
+ OutOfProcess
+ Linux
+ true
+
-
- ..\Blog.Core.Api\Blog.Core.xml
- 1701;1702;1591
-
+
+ ..\Blog.Core.Api\Blog.Core.xml
+ 1701;1702;1591
+
-
- ..\Blog.Core\Blog.Core.xml
- 1701;1702;1591
-
-
- false
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+ ..\Blog.Core\Blog.Core.xml
+ 1701;1702;1591
+
+
+ false
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
-
-
-
+
+
+
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
-
-
-
+
+
+
-
-
- Always
-
-
+
+
+ Always
+
+
-
-
- Always
-
-
- Always
-
-
+
+
+ Always
+
+
+ Always
+
+
-
+
+
+
+
+
diff --git a/Blog.Core.Api/Blog.Core.xml b/Blog.Core.Api/Blog.Core.xml
index f4375977..128153b6 100644
--- a/Blog.Core.Api/Blog.Core.xml
+++ b/Blog.Core.Api/Blog.Core.xml
@@ -813,6 +813,40 @@
+
+
+ nacos
+
+
+
+
+ INacosNamingService
+
+
+
+
+
+
+
+
+
+
+ 获取Nacos 状态
+
+
+
+
+
+ 服务上线
+
+
+
+
+
+ 服务下线
+
+
+
自定义路由 /api/{version}/[controler]/[action]
@@ -877,85 +911,6 @@
全局路由前缀公约
-
-
- Nacos配置文件变更事件
-
-
-
-
- Nacos 配置文件监听事件
-
-
-
-
- 重载方法
-
-
-
-
-
-
- 执行
-
-
-
-
-
-
- 停止
-
-
-
-
-
-
- 配置监听事件
-
-
-
-
- 收到配置文件变更
-
-
-
-
-
-
-
-
-
-
- 监听事件
-
-
-
-
-
-
-
-
-
-
-
-
- 订阅服务变化
-
-
-
-
-
-
- 服务变更事件监听
-
-
-
-
- 监听事件
-
-
-
-
根据环境变量定向配置文件名称
diff --git a/Blog.Core.Api/Startup.cs b/Blog.Core.Api/Startup.cs
index a9e31d50..36969a92 100644
--- a/Blog.Core.Api/Startup.cs
+++ b/Blog.Core.Api/Startup.cs
@@ -1,7 +1,5 @@
using Autofac;
-using Blog.Core.Api;
using Blog.Core.Common;
-using Blog.Core.Common.Helper;
using Blog.Core.Common.LogHelper;
using Blog.Core.Extensions;
using Blog.Core.Filter;
@@ -19,12 +17,8 @@
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection.Extensions;
using Microsoft.Extensions.Hosting;
-using Nacos.V2.DependencyInjection;
using Newtonsoft.Json;
using Newtonsoft.Json.Serialization;
-using System;
-using System.Collections.Generic;
-using System.Configuration;
using System.IdentityModel.Tokens.Jwt;
using System.Reflection;
using System.Text;
@@ -48,44 +42,11 @@ public Startup(IConfiguration configuration, IWebHostEnvironment env)
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
- // 在实际生产工作中 本地开发是不需要注册nacos的 所以根据环境变量去判断
- // 比如 开发环境 dev 测试环境 test 生产 prod 只有这几种环境变量的时候才需要去注册nacos
- if (Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT") != null
- && Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT") != "")
- {
- // 从当前配置取文件去注册naocs
- services.AddNacosV2Config(x =>
- {
- x.ServerAddresses = JsonConfigSettings.NacosServerAddresses;
- x.EndPoint = "";
- x.Namespace = JsonConfigSettings.NacosNamespace;
- x.DefaultTimeOut = JsonConfigSettings.NacosDefaultTimeOut;
- x.ListenInterval = JsonConfigSettings.ListenInterval;
- // swich to use http or rpc
- x.ConfigUseRpc = false;
- });
- services.AddNacosV2Naming(x =>
- {
- x.ServerAddresses = JsonConfigSettings.NacosServerAddresses;
- x.EndPoint = "";
- x.Namespace = JsonConfigSettings.NacosNamespace;
- x.DefaultTimeOut = JsonConfigSettings.NacosDefaultTimeOut;
- x.ListenInterval = JsonConfigSettings.ListenInterval;
- // swich to use http or rpc
- x.NamingUseRpc = false;
- });
- services.AddHostedService(); //增加服务注入,删除事件
- // 监听nacos中的配置中心 如果有新配置变更 执行相关逻辑
- services.AddHostedService();//增加配置文件监听事件
- }
-
- services.AddSingleton(new Blog.Core.Common.Helper.ConfigurationManager((ConfigurationRoot)this.Configuration));
- services.AddSingleton(Configuration);
-
// 以下code可能与文章中不一样,对代码做了封装,具体查看右侧 Extensions 文件夹.
services.AddSingleton(new Appsettings(Configuration));
services.AddSingleton(new LogLock(Env.ContentRootPath));
+
Permissions.IsUseIds4 = Appsettings.app(new string[] { "Startup", "IdentityServer4", "Enabled" }).ObjToBool();
// 确保从认证中心返回的ClaimType不被更改,不使用Map映射
@@ -109,6 +70,8 @@ public void ConfigureServices(IServiceCollection services)
services.AddRabbitMQSetup();
services.AddEventBusSetup();
+ services.AddNacosSetup(Configuration);
+
// 授权+认证 (jwt or ids4)
services.AddAuthorizationSetup();
if (Permissions.IsUseIds4)
diff --git a/Blog.Core.Api/appsettings.dev.json b/Blog.Core.Api/appsettings.dev.json
index 25fe0bfc..fa948eaa 100644
--- a/Blog.Core.Api/appsettings.dev.json
+++ b/Blog.Core.Api/appsettings.dev.json
@@ -1,8 +1,8 @@
{
- "urls": "http://*:8081", //web˿ڣIIS𣬰ȥ
+ "urls": "http://*:8081", //web服务端口,如果用IIS部署,把这个去掉
"Logging": {
"LogLevel": {
- "Default": "Information", //Defaultlog4netд벻־
+ "Default": "Information", //加入Default否则log4net本地写入不了日志
"Blog.Core.AuthHelper.ApiResponseHandler": "Error"
},
"IncludeScopes": false,
@@ -59,37 +59,37 @@
}
},
"Date": "2018-08-28",
- "SeedDBEnabled": true, //ֻɱṹ
- "SeedDBDataEnabled": true, //ɱ,ʼ
+ "SeedDBEnabled": true, //只生成表结构
+ "SeedDBDataEnabled": true, //生成表,并初始化数据
"Author": "Blog.Core",
"UseLoadTest": false
},
- // MainDBΪҪConnIdֵ,öӦEnabledΪtrue
- // *** MutiDBEnabled Ϊfalse ***
- // *** MutiDBEnabled ΪtrueĴӿEnabledҲΪtrue **
- // ÿƵhttps://www.bilibili.com/video/BV1BJ411B7mn?p=6
+ // 请配置MainDB为你想要的主库的ConnId值,并设置对应的Enabled为true;
+ // *** 单库操作,把 MutiDBEnabled 设为false ***;
+ // *** 多库操作,把 MutiDBEnabled 设为true,其他的从库Enabled也为true **;
+ // 具体配置看视频:https://www.bilibili.com/video/BV1BJ411B7mn?p=6
- "MainDB": "WMBLOG_SQLITE", //ǰĿ⣬ӦַEnabledΪtrue
- "MutiDBEnabled": false, //Ƿģʽ
- "CQRSEnabled": false, //Ƿдģʽ,ǵģʽݿһ£綼SqlServer
+ "MainDB": "WMBLOG_SQLITE", //当前项目的主库,所对应的连接字符串的Enabled必须为true
+ "MutiDBEnabled": false, //是否开启多库模式
+ "CQRSEnabled": false, //是否开启读写分离模式,必须是单库模式,且数据库类型一致,比如都是SqlServer
"DBS": [
/*
- Ӧ±ߵ DBType
+ 对应下边的 DBType
MySql = 0,
SqlServer = 1,
Sqlite = 2,
Oracle = 3,
PostgreSQL = 4,
- Dm = 5,//
- Kdbndp = 6,//˴
+ Dm = 5,//达梦
+ Kdbndp = 6,//人大金仓
*/
{
"ConnId": "WMBLOG_SQLITE",
"DBType": 2,
"Enabled": true,
- "HitRate": 50, // ֵԽȼԽ
- "Connection": "WMBlog.db" //sqliteֻдݿ
+ "HitRate": 50, // 值越大,优先级越高
+ "Connection": "WMBlog.db" //sqlite只写数据库名就行
},
{
"ConnId": "WMBLOG_MSSQL_1",
@@ -144,8 +144,8 @@
}
],
"Audience": {
- "Secret": "sdfsdfsrty45634kkhllghtdgdfss345t678fs", //Ҫ̫̣16λ+
- "SecretFile": "C:\\my-file\\blog.core.audience.secret.txt", //ȫݾSecret
+ "Secret": "sdfsdfsrty45634kkhllghtdgdfss345t678fs", //不要太短,16位+
+ "SecretFile": "C:\\my-file\\blog.core.audience.secret.txt", //安全。内容就是Secret
"Issuer": "Blog.Core",
"Audience": "wr"
},
@@ -155,10 +155,10 @@
},
"Startup": {
"Cors": {
- "PolicyName": "CorsIpAccess", //
- "EnableAllIPs": false, //ΪtrueʱIPɷʡ
- // ֶ֧˿ڣע˿ںźҪ/бˣlocalhost:8000/Ǵ
- // ע⣬http://127.0.0.1:1818 http://localhost:1818 Dzһ
+ "PolicyName": "CorsIpAccess", //策略名称
+ "EnableAllIPs": false, //当为true时,开放所有IP均可访问。
+ // 支持多个域名端口,注意端口号后不要带/斜杆:比如localhost:8000/,是错的
+ // 注意,http://127.0.0.1:1818 和 http://localhost:1818 是不一样的
"IPs": "http://127.0.0.1:2364,http://localhost:2364"
},
"AppConfigAlert": {
@@ -166,15 +166,15 @@
},
"ApiName": "Blog.Core",
"IdentityServer4": {
- "Enabled": false, // ĬfalseʾʹjwtΪtrueʾϵͳʹIds4ģʽ
- "AuthorizationUrl": "http://localhost:5004", // ֤
- "ApiName": "blog.core.api" // Դ
+ "Enabled": false, // 这里默认是false,表示使用jwt,如果设置为true,则表示系统使用Ids4模式
+ "AuthorizationUrl": "http://localhost:5004", // 认证中心域名
+ "ApiName": "blog.core.api" // 资源服务器
},
"RedisMq": {
- "Enabled": false //redis Ϣ
+ "Enabled": false //redis 消息队列
},
"MiniProfiler": {
- "Enabled": false //ܷ
+ "Enabled": false //性能分析开启
}
},
"Middleware": {
@@ -206,16 +206,16 @@
"StackBlockedRequests": false, //False: Number of rejections should be recorded on another counter
"RealIpHeader": "X-Real-IP",
"ClientIdHeader": "X-ClientId",
- "IpWhitelist": [], //
+ "IpWhitelist": [], //白名单
"EndpointWhitelist": [ "get:/api/xxx", "*:/api/yyy" ],
"ClientWhitelist": [ "dev-client-1", "dev-client-2" ],
"QuotaExceededResponse": {
- "Content": "{{\"status\":429,\"msg\":\"ʹƵԺ\",\"success\":false}}",
+ "Content": "{{\"status\":429,\"msg\":\"访问过于频繁,请稍后重试\",\"success\":false}}",
"ContentType": "application/json",
"StatusCode": 429
},
- "HttpStatusCode": 429, //״̬
- "GeneralRules": [ //api,βһҪ*
+ "HttpStatusCode": 429, //返回状态码
+ "GeneralRules": [ //api规则,结尾一定要带*
{
"Endpoint": "*:/api/blog*",
"Period": "1m",
@@ -246,22 +246,22 @@
"ServiceHealthCheck": "/healthcheck",
"ConsulAddress": "http://localhost:8500"
},
- "PayInfo": { //оۺ֧Ϣ
- "MERCHANTID": "", //̻
- "POSID": "", //̨
- "BRANCHID": "", //к
- "pubKey": "", //Կ
- "USER_ID": "", //Ա
- "PASSWORD": "", //
- "OutAddress": "http://127.0.0.1:12345" //ַ
+ "PayInfo": { //建行聚合支付信息
+ "MERCHANTID": "", //商户号
+ "POSID": "", //柜台号
+ "BRANCHID": "", //分行号
+ "pubKey": "", //公钥
+ "USER_ID": "", //操作员号
+ "PASSWORD": "", //密码
+ "OutAddress": "http://127.0.0.1:12345" //外联地址
},
"nacos": {
- "ServerAddresses": [ "http://ancba.neters.club:8918" ], // nacos ӵַ
- "DefaultTimeOut": 15000, // Ĭϳʱʱ
- "Namespace": "public", // ռ
- "ListenInterval": 10000, // Ƶ
- "ServiceName": "blog.Core.Api", //
- "Port": "8081", // ˿ں
- "RegisterEnabled": true // Ƿֱעnacos
+ "ServerAddresses": [ "http://localhost:8848" ], // nacos 连接地址
+ "DefaultTimeOut": 15000, // 默认超时时间
+ "Namespace": "public", // 命名空间
+ "ListenInterval": 10000, // 监听的频率
+ "ServiceName": "blog.Core.Api", // 服务名
+ "Port": "8081", // 服务端口号
+ "RegisterEnabled": true // 是否直接注册nacos
}
}
diff --git a/Blog.Core.Api/appsettings.json b/Blog.Core.Api/appsettings.json
index 02a6c25e..f41ed9c3 100644
--- a/Blog.Core.Api/appsettings.json
+++ b/Blog.Core.Api/appsettings.json
@@ -175,6 +175,9 @@
},
"MiniProfiler": {
"Enabled": false //性能分析开启
+ },
+ "Nacos": {
+ "Enabled": false //Nacos注册中心
}
},
"Middleware": {
diff --git a/Blog.Core.Api/appsettings.prod.json b/Blog.Core.Api/appsettings.prod.json
index 2a10be98..02a6c25e 100644
--- a/Blog.Core.Api/appsettings.prod.json
+++ b/Blog.Core.Api/appsettings.prod.json
@@ -1,8 +1,8 @@
{
- "urls": "http://*:8081", //web˿ڣIIS𣬰ȥ
+ "urls": "http://*:8081", //web服务端口,如果用IIS部署,把这个去掉
"Logging": {
"LogLevel": {
- "Default": "Information", //Defaultlog4netд벻־
+ "Default": "Information", //加入Default否则log4net本地写入不了日志
"Blog.Core.AuthHelper.ApiResponseHandler": "Error"
},
"IncludeScopes": false,
@@ -59,37 +59,37 @@
}
},
"Date": "2018-08-28",
- "SeedDBEnabled": true, //ֻɱṹ
- "SeedDBDataEnabled": true, //ɱ,ʼ
+ "SeedDBEnabled": true, //只生成表结构
+ "SeedDBDataEnabled": true, //生成表,并初始化数据
"Author": "Blog.Core",
"UseLoadTest": false
},
- // MainDBΪҪConnIdֵ,öӦEnabledΪtrue
- // *** MutiDBEnabled Ϊfalse ***
- // *** MutiDBEnabled ΪtrueĴӿEnabledҲΪtrue **
- // ÿƵhttps://www.bilibili.com/video/BV1BJ411B7mn?p=6
+ // 请配置MainDB为你想要的主库的ConnId值,并设置对应的Enabled为true;
+ // *** 单库操作,把 MutiDBEnabled 设为false ***;
+ // *** 多库操作,把 MutiDBEnabled 设为true,其他的从库Enabled也为true **;
+ // 具体配置看视频:https://www.bilibili.com/video/BV1BJ411B7mn?p=6
- "MainDB": "WMBLOG_SQLITE", //ǰĿ⣬ӦַEnabledΪtrue
- "MutiDBEnabled": false, //Ƿģʽ
- "CQRSEnabled": false, //Ƿдģʽ,ǵģʽݿһ£綼SqlServer
+ "MainDB": "WMBLOG_SQLITE", //当前项目的主库,所对应的连接字符串的Enabled必须为true
+ "MutiDBEnabled": false, //是否开启多库模式
+ "CQRSEnabled": false, //是否开启读写分离模式,必须是单库模式,且数据库类型一致,比如都是SqlServer
"DBS": [
/*
- Ӧ±ߵ DBType
+ 对应下边的 DBType
MySql = 0,
SqlServer = 1,
Sqlite = 2,
Oracle = 3,
PostgreSQL = 4,
- Dm = 5,//
- Kdbndp = 6,//˴
+ Dm = 5,//达梦
+ Kdbndp = 6,//人大金仓
*/
{
"ConnId": "WMBLOG_SQLITE",
"DBType": 2,
"Enabled": true,
- "HitRate": 50, // ֵԽȼԽ
- "Connection": "WMBlog.db" //sqliteֻдݿ
+ "HitRate": 50, // 值越大,优先级越高
+ "Connection": "WMBlog.db" //sqlite只写数据库名就行
},
{
"ConnId": "WMBLOG_MSSQL_1",
@@ -144,8 +144,8 @@
}
],
"Audience": {
- "Secret": "sdfsdfsrty45634kkhllghtdgdfss345t678fs", //Ҫ̫̣16λ+
- "SecretFile": "C:\\my-file\\blog.core.audience.secret.txt", //ȫݾSecret
+ "Secret": "sdfsdfsrty45634kkhllghtdgdfss345t678fs", //不要太短,16位+
+ "SecretFile": "C:\\my-file\\blog.core.audience.secret.txt", //安全。内容就是Secret
"Issuer": "Blog.Core",
"Audience": "wr"
},
@@ -155,10 +155,10 @@
},
"Startup": {
"Cors": {
- "PolicyName": "CorsIpAccess", //
- "EnableAllIPs": false, //ΪtrueʱIPɷʡ
- // ֶ֧˿ڣע˿ںźҪ/бˣlocalhost:8000/Ǵ
- // ע⣬http://127.0.0.1:1818 http://localhost:1818 Dzһ
+ "PolicyName": "CorsIpAccess", //策略名称
+ "EnableAllIPs": false, //当为true时,开放所有IP均可访问。
+ // 支持多个域名端口,注意端口号后不要带/斜杆:比如localhost:8000/,是错的
+ // 注意,http://127.0.0.1:1818 和 http://localhost:1818 是不一样的
"IPs": "http://127.0.0.1:2364,http://localhost:2364"
},
"AppConfigAlert": {
@@ -166,15 +166,15 @@
},
"ApiName": "Blog.Core",
"IdentityServer4": {
- "Enabled": false, // ĬfalseʾʹjwtΪtrueʾϵͳʹIds4ģʽ
- "AuthorizationUrl": "http://localhost:5004", // ֤
- "ApiName": "blog.core.api" // Դ
+ "Enabled": false, // 这里默认是false,表示使用jwt,如果设置为true,则表示系统使用Ids4模式
+ "AuthorizationUrl": "http://localhost:5004", // 认证中心域名
+ "ApiName": "blog.core.api" // 资源服务器
},
"RedisMq": {
- "Enabled": false //redis Ϣ
+ "Enabled": false //redis 消息队列
},
"MiniProfiler": {
- "Enabled": false //ܷ
+ "Enabled": false //性能分析开启
}
},
"Middleware": {
@@ -206,16 +206,16 @@
"StackBlockedRequests": false, //False: Number of rejections should be recorded on another counter
"RealIpHeader": "X-Real-IP",
"ClientIdHeader": "X-ClientId",
- "IpWhitelist": [], //
+ "IpWhitelist": [], //白名单
"EndpointWhitelist": [ "get:/api/xxx", "*:/api/yyy" ],
"ClientWhitelist": [ "dev-client-1", "dev-client-2" ],
"QuotaExceededResponse": {
- "Content": "{{\"status\":429,\"msg\":\"ʹƵԺ\",\"success\":false}}",
+ "Content": "{{\"status\":429,\"msg\":\"访问过于频繁,请稍后重试\",\"success\":false}}",
"ContentType": "application/json",
"StatusCode": 429
},
- "HttpStatusCode": 429, //״̬
- "GeneralRules": [ //api,βһҪ*
+ "HttpStatusCode": 429, //返回状态码
+ "GeneralRules": [ //api规则,结尾一定要带*
{
"Endpoint": "*:/api/blog*",
"Period": "1m",
@@ -246,13 +246,13 @@
"ServiceHealthCheck": "/healthcheck",
"ConsulAddress": "http://localhost:8500"
},
- "PayInfo": { //оۺ֧Ϣ
- "MERCHANTID": "", //̻
- "POSID": "", //̨
- "BRANCHID": "", //к
- "pubKey": "", //Կ
- "USER_ID": "", //Ա
- "PASSWORD": "", //
- "OutAddress": "http://127.0.0.1:12345" //ַ
+ "PayInfo": { //建行聚合支付信息
+ "MERCHANTID": "", //商户号
+ "POSID": "", //柜台号
+ "BRANCHID": "", //分行号
+ "pubKey": "", //公钥
+ "USER_ID": "", //操作员号
+ "PASSWORD": "", //密码
+ "OutAddress": "http://127.0.0.1:12345" //外联地址
}
}
diff --git a/Blog.Core.Api/appsettings.test.json b/Blog.Core.Api/appsettings.test.json
index 2a10be98..02a6c25e 100644
--- a/Blog.Core.Api/appsettings.test.json
+++ b/Blog.Core.Api/appsettings.test.json
@@ -1,8 +1,8 @@
{
- "urls": "http://*:8081", //web˿ڣIIS𣬰ȥ
+ "urls": "http://*:8081", //web服务端口,如果用IIS部署,把这个去掉
"Logging": {
"LogLevel": {
- "Default": "Information", //Defaultlog4netд벻־
+ "Default": "Information", //加入Default否则log4net本地写入不了日志
"Blog.Core.AuthHelper.ApiResponseHandler": "Error"
},
"IncludeScopes": false,
@@ -59,37 +59,37 @@
}
},
"Date": "2018-08-28",
- "SeedDBEnabled": true, //ֻɱṹ
- "SeedDBDataEnabled": true, //ɱ,ʼ
+ "SeedDBEnabled": true, //只生成表结构
+ "SeedDBDataEnabled": true, //生成表,并初始化数据
"Author": "Blog.Core",
"UseLoadTest": false
},
- // MainDBΪҪConnIdֵ,öӦEnabledΪtrue
- // *** MutiDBEnabled Ϊfalse ***
- // *** MutiDBEnabled ΪtrueĴӿEnabledҲΪtrue **
- // ÿƵhttps://www.bilibili.com/video/BV1BJ411B7mn?p=6
+ // 请配置MainDB为你想要的主库的ConnId值,并设置对应的Enabled为true;
+ // *** 单库操作,把 MutiDBEnabled 设为false ***;
+ // *** 多库操作,把 MutiDBEnabled 设为true,其他的从库Enabled也为true **;
+ // 具体配置看视频:https://www.bilibili.com/video/BV1BJ411B7mn?p=6
- "MainDB": "WMBLOG_SQLITE", //ǰĿ⣬ӦַEnabledΪtrue
- "MutiDBEnabled": false, //Ƿģʽ
- "CQRSEnabled": false, //Ƿдģʽ,ǵģʽݿһ£綼SqlServer
+ "MainDB": "WMBLOG_SQLITE", //当前项目的主库,所对应的连接字符串的Enabled必须为true
+ "MutiDBEnabled": false, //是否开启多库模式
+ "CQRSEnabled": false, //是否开启读写分离模式,必须是单库模式,且数据库类型一致,比如都是SqlServer
"DBS": [
/*
- Ӧ±ߵ DBType
+ 对应下边的 DBType
MySql = 0,
SqlServer = 1,
Sqlite = 2,
Oracle = 3,
PostgreSQL = 4,
- Dm = 5,//
- Kdbndp = 6,//˴
+ Dm = 5,//达梦
+ Kdbndp = 6,//人大金仓
*/
{
"ConnId": "WMBLOG_SQLITE",
"DBType": 2,
"Enabled": true,
- "HitRate": 50, // ֵԽȼԽ
- "Connection": "WMBlog.db" //sqliteֻдݿ
+ "HitRate": 50, // 值越大,优先级越高
+ "Connection": "WMBlog.db" //sqlite只写数据库名就行
},
{
"ConnId": "WMBLOG_MSSQL_1",
@@ -144,8 +144,8 @@
}
],
"Audience": {
- "Secret": "sdfsdfsrty45634kkhllghtdgdfss345t678fs", //Ҫ̫̣16λ+
- "SecretFile": "C:\\my-file\\blog.core.audience.secret.txt", //ȫݾSecret
+ "Secret": "sdfsdfsrty45634kkhllghtdgdfss345t678fs", //不要太短,16位+
+ "SecretFile": "C:\\my-file\\blog.core.audience.secret.txt", //安全。内容就是Secret
"Issuer": "Blog.Core",
"Audience": "wr"
},
@@ -155,10 +155,10 @@
},
"Startup": {
"Cors": {
- "PolicyName": "CorsIpAccess", //
- "EnableAllIPs": false, //ΪtrueʱIPɷʡ
- // ֶ֧˿ڣע˿ںźҪ/бˣlocalhost:8000/Ǵ
- // ע⣬http://127.0.0.1:1818 http://localhost:1818 Dzһ
+ "PolicyName": "CorsIpAccess", //策略名称
+ "EnableAllIPs": false, //当为true时,开放所有IP均可访问。
+ // 支持多个域名端口,注意端口号后不要带/斜杆:比如localhost:8000/,是错的
+ // 注意,http://127.0.0.1:1818 和 http://localhost:1818 是不一样的
"IPs": "http://127.0.0.1:2364,http://localhost:2364"
},
"AppConfigAlert": {
@@ -166,15 +166,15 @@
},
"ApiName": "Blog.Core",
"IdentityServer4": {
- "Enabled": false, // ĬfalseʾʹjwtΪtrueʾϵͳʹIds4ģʽ
- "AuthorizationUrl": "http://localhost:5004", // ֤
- "ApiName": "blog.core.api" // Դ
+ "Enabled": false, // 这里默认是false,表示使用jwt,如果设置为true,则表示系统使用Ids4模式
+ "AuthorizationUrl": "http://localhost:5004", // 认证中心域名
+ "ApiName": "blog.core.api" // 资源服务器
},
"RedisMq": {
- "Enabled": false //redis Ϣ
+ "Enabled": false //redis 消息队列
},
"MiniProfiler": {
- "Enabled": false //ܷ
+ "Enabled": false //性能分析开启
}
},
"Middleware": {
@@ -206,16 +206,16 @@
"StackBlockedRequests": false, //False: Number of rejections should be recorded on another counter
"RealIpHeader": "X-Real-IP",
"ClientIdHeader": "X-ClientId",
- "IpWhitelist": [], //
+ "IpWhitelist": [], //白名单
"EndpointWhitelist": [ "get:/api/xxx", "*:/api/yyy" ],
"ClientWhitelist": [ "dev-client-1", "dev-client-2" ],
"QuotaExceededResponse": {
- "Content": "{{\"status\":429,\"msg\":\"ʹƵԺ\",\"success\":false}}",
+ "Content": "{{\"status\":429,\"msg\":\"访问过于频繁,请稍后重试\",\"success\":false}}",
"ContentType": "application/json",
"StatusCode": 429
},
- "HttpStatusCode": 429, //״̬
- "GeneralRules": [ //api,βһҪ*
+ "HttpStatusCode": 429, //返回状态码
+ "GeneralRules": [ //api规则,结尾一定要带*
{
"Endpoint": "*:/api/blog*",
"Period": "1m",
@@ -246,13 +246,13 @@
"ServiceHealthCheck": "/healthcheck",
"ConsulAddress": "http://localhost:8500"
},
- "PayInfo": { //оۺ֧Ϣ
- "MERCHANTID": "", //̻
- "POSID": "", //̨
- "BRANCHID": "", //к
- "pubKey": "", //Կ
- "USER_ID": "", //Ա
- "PASSWORD": "", //
- "OutAddress": "http://127.0.0.1:12345" //ַ
+ "PayInfo": { //建行聚合支付信息
+ "MERCHANTID": "", //商户号
+ "POSID": "", //柜台号
+ "BRANCHID": "", //分行号
+ "pubKey": "", //公钥
+ "USER_ID": "", //操作员号
+ "PASSWORD": "", //密码
+ "OutAddress": "http://127.0.0.1:12345" //外联地址
}
}
diff --git a/Blog.Core.Extensions/Blog.Core.Extensions.csproj b/Blog.Core.Extensions/Blog.Core.Extensions.csproj
index e0a705a1..e10b8f57 100644
--- a/Blog.Core.Extensions/Blog.Core.Extensions.csproj
+++ b/Blog.Core.Extensions/Blog.Core.Extensions.csproj
@@ -19,6 +19,12 @@
+
+
+
+
+
+
diff --git a/Blog.Core.Api/NacosListenConfigurationTask.cs b/Blog.Core.Extensions/NacosConfig/NacosListenConfigurationTask.cs
similarity index 92%
rename from Blog.Core.Api/NacosListenConfigurationTask.cs
rename to Blog.Core.Extensions/NacosConfig/NacosListenConfigurationTask.cs
index 2cd949d1..919cc634 100644
--- a/Blog.Core.Api/NacosListenConfigurationTask.cs
+++ b/Blog.Core.Extensions/NacosConfig/NacosListenConfigurationTask.cs
@@ -1,12 +1,12 @@
-using Microsoft.Extensions.Configuration;
+using Blog.Core.Common.Helper;
+using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Hosting;
+using Nacos.V2;
using System;
using System.Threading;
using System.Threading.Tasks;
-using Nacos.V2;
-using Blog.Core.Common.Helper;
-namespace Blog.Core.Api
+namespace Blog.Core.Extensions.NacosConfig
{
///
/// Nacos配置文件变更事件
@@ -72,8 +72,6 @@ public class NacosConfigListener : IListener
///
public void ReceiveConfigInfo(string configInfo)
{
-
- // Serilog.Log.Information($"Nacos配置文件更新!!! {DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")} [{configInfo}]");
var _configurationBuilder = new ConfigurationBuilder();
_configurationBuilder.Sources.Clear();
var buffer = System.Text.Encoding.Default.GetBytes(configInfo);
diff --git a/Blog.Core.Api/NacosListenNamingTask.cs b/Blog.Core.Extensions/NacosConfig/NacosListenNamingTask.cs
similarity index 91%
rename from Blog.Core.Api/NacosListenNamingTask.cs
rename to Blog.Core.Extensions/NacosConfig/NacosListenNamingTask.cs
index ec3c13f4..d2228673 100644
--- a/Blog.Core.Api/NacosListenNamingTask.cs
+++ b/Blog.Core.Extensions/NacosConfig/NacosListenNamingTask.cs
@@ -1,12 +1,11 @@
using Blog.Core.Common.Helper;
-using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Hosting;
using Nacos.V2;
using System;
using System.Threading;
using System.Threading.Tasks;
-namespace Blog.Core.Api
+namespace Blog.Core.Extensions.NacosConfig
{
///
///
@@ -14,10 +13,7 @@ namespace Blog.Core.Api
public class NacosListenNamingTask : BackgroundService
{
private readonly INacosNamingService _nacosNamingService;
- IServiceProvider _serviceProvider;
- IConfiguration _configuration;
-
///
/// 监听事件
///
@@ -29,12 +25,9 @@ public class NacosListenNamingTask : BackgroundService
///
///
///
- public NacosListenNamingTask(INacosNamingService nacosNamingService, IServiceProvider serviceProvider, IConfiguration configuration)
+ public NacosListenNamingTask(INacosNamingService nacosNamingService)
{
_nacosNamingService = nacosNamingService;
- _serviceProvider = serviceProvider;
- _configuration = configuration;
-
}
///
@@ -95,7 +88,7 @@ public Task OnEvent(Nacos.V2.IEvent @event)
//_redisCachqManager.DisposeRedisConnection();
-
+
Serilog.Log.Information($"收到服务变更事件!!! {DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")} [{e}]");
}
diff --git a/Blog.Core.Extensions/ServiceExtensions/NacosSetup.cs b/Blog.Core.Extensions/ServiceExtensions/NacosSetup.cs
new file mode 100644
index 00000000..e3b95c20
--- /dev/null
+++ b/Blog.Core.Extensions/ServiceExtensions/NacosSetup.cs
@@ -0,0 +1,57 @@
+using Blog.Core.Common;
+using Blog.Core.Common.Helper;
+using Blog.Core.Extensions.NacosConfig;
+using Microsoft.Extensions.Configuration;
+using Microsoft.Extensions.DependencyInjection;
+using Nacos.V2.DependencyInjection;
+using System;
+
+namespace Blog.Core.Extensions
+{
+ ///
+ /// Memory缓存 启动服务
+ ///
+ public static class NacosSetup
+ {
+ public static void AddNacosSetup(this IServiceCollection services, IConfiguration Configuration)
+ {
+ if (services == null) throw new ArgumentNullException(nameof(services));
+
+ // 在实际生产工作中 本地开发是不需要注册nacos的 所以根据环境变量去判断
+ // 比如 开发环境 dev 测试环境 test 生产 prod 只有这几种环境变量的时候才需要去注册nacos
+ if (Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT") != null
+ && Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT") != ""
+ && Appsettings.app(new string[] { "Startup", "Nacos", "Enabled" }).ObjToBool())
+ {
+ // 从当前配置取文件去注册naocs
+ services.AddNacosV2Config(x =>
+ {
+ x.ServerAddresses = JsonConfigSettings.NacosServerAddresses;
+ x.EndPoint = "";
+ x.Namespace = JsonConfigSettings.NacosNamespace;
+ x.DefaultTimeOut = JsonConfigSettings.NacosDefaultTimeOut;
+ x.ListenInterval = JsonConfigSettings.ListenInterval;
+ // swich to use http or rpc
+ x.ConfigUseRpc = false;
+ });
+ services.AddNacosV2Naming(x =>
+ {
+ x.ServerAddresses = JsonConfigSettings.NacosServerAddresses;
+ x.EndPoint = "";
+ x.Namespace = JsonConfigSettings.NacosNamespace;
+ x.DefaultTimeOut = JsonConfigSettings.NacosDefaultTimeOut;
+ x.ListenInterval = JsonConfigSettings.ListenInterval;
+ // swich to use http or rpc
+ x.NamingUseRpc = false;
+ });
+ services.AddHostedService(); //增加服务注入,删除事件
+ // 监听nacos中的配置中心 如果有新配置变更 执行相关逻辑
+ services.AddHostedService();//增加配置文件监听事件
+ }
+
+ services.AddSingleton(new ConfigurationManager((ConfigurationRoot)Configuration));
+ services.AddSingleton(Configuration);
+
+ }
+ }
+}
diff --git a/Blog.Core.Tests/DependencyInjection/DI_Test.cs b/Blog.Core.Tests/DependencyInjection/DI_Test.cs
index 550f7a85..0f1b08ba 100644
--- a/Blog.Core.Tests/DependencyInjection/DI_Test.cs
+++ b/Blog.Core.Tests/DependencyInjection/DI_Test.cs
@@ -31,7 +31,7 @@ public class DI_Test
[Fact]
public void DI_Connet_Test()
{
- var basePath = Microsoft.DotNet.PlatformAbstractions.ApplicationEnvironment.ApplicationBasePath;
+ var basePath = AppContext.BaseDirectory;
IServiceCollection services = new ServiceCollection().AddLogging();
services.AddAutoMapper(typeof(Startup));
@@ -108,7 +108,7 @@ public static MutiDBOperate GetMainConnectionDb()
public IContainer DICollections()
{
- var basePath = Microsoft.DotNet.PlatformAbstractions.ApplicationEnvironment.ApplicationBasePath;
+ var basePath = AppContext.BaseDirectory;
IServiceCollection services = new ServiceCollection();
services.AddAutoMapper(typeof(Startup));
From 28ceb9167189048d1417aac35031a73209767eae Mon Sep 17 00:00:00 2001
From: anjoy8 <3143422472@qq.com>
Date: Wed, 28 Jul 2021 14:22:09 +0800
Subject: [PATCH 052/456] =?UTF-8?q?fix=EF=BC=9Anacos=20config?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
Blog.Core.Api/Blog.Core.xml | 2 +-
Blog.Core.Api/Controllers/NacosController.cs | 9 +-
Blog.Core.Api/Program.cs | 12 +-
Blog.Core.Api/appsettings.dev.json | 267 -------------------
Blog.Core.Api/appsettings.json | 9 +
Blog.Core.Api/appsettings.prod.json | 258 ------------------
Blog.Core.Api/appsettings.test.json | 258 ------------------
7 files changed, 20 insertions(+), 795 deletions(-)
delete mode 100644 Blog.Core.Api/appsettings.dev.json
delete mode 100644 Blog.Core.Api/appsettings.prod.json
delete mode 100644 Blog.Core.Api/appsettings.test.json
diff --git a/Blog.Core.Api/Blog.Core.xml b/Blog.Core.Api/Blog.Core.xml
index 128153b6..3f79cf4e 100644
--- a/Blog.Core.Api/Blog.Core.xml
+++ b/Blog.Core.Api/Blog.Core.xml
@@ -815,7 +815,7 @@
- nacos
+ 服务管理
diff --git a/Blog.Core.Api/Controllers/NacosController.cs b/Blog.Core.Api/Controllers/NacosController.cs
index 5c037435..d2d94cfc 100644
--- a/Blog.Core.Api/Controllers/NacosController.cs
+++ b/Blog.Core.Api/Controllers/NacosController.cs
@@ -4,19 +4,16 @@
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Nacos.V2;
-using System;
-using System.Collections.Generic;
-using System.Linq;
using System.Threading.Tasks;
namespace Blog.Core.Api.Controllers
{
///
- /// nacos
+ /// 服务管理
///
[Produces("application/json")]
- [Route("api/Login")]
- [AllowAnonymous]
+ [Route("api/[Controller]/[action]")]
+ [Authorize(Permissions.Name)]
public class NacosController : BaseApiCpntroller
{
diff --git a/Blog.Core.Api/Program.cs b/Blog.Core.Api/Program.cs
index 34143225..30615a39 100644
--- a/Blog.Core.Api/Program.cs
+++ b/Blog.Core.Api/Program.cs
@@ -19,11 +19,13 @@ public static void Main(string[] args)
{
webBuilder
.UseStartup()
- .ConfigureAppConfiguration((hostingContext, config) => {
- config.Sources.Clear();
- config.AddJsonFile("appsettings.json", optional: true, reloadOnChange: false)
- .AddJsonFile($"appsettings{ GetAppSettingsConfigName() }json", optional: true, reloadOnChange: false);
- })
+ .ConfigureAppConfiguration((hostingContext, config) =>
+ {
+ config.Sources.Clear();
+ config.AddJsonFile("appsettings.json", optional: true, reloadOnChange: false)
+ //.AddJsonFile($"appsettings{ GetAppSettingsConfigName() }json", optional: true, reloadOnChange: false)
+ ;
+ })
.UseUrls("http://*:8081")
.ConfigureLogging((hostingContext, builder) =>
{
diff --git a/Blog.Core.Api/appsettings.dev.json b/Blog.Core.Api/appsettings.dev.json
deleted file mode 100644
index fa948eaa..00000000
--- a/Blog.Core.Api/appsettings.dev.json
+++ /dev/null
@@ -1,267 +0,0 @@
-{
- "urls": "http://*:8081", //web服务端口,如果用IIS部署,把这个去掉
- "Logging": {
- "LogLevel": {
- "Default": "Information", //加入Default否则log4net本地写入不了日志
- "Blog.Core.AuthHelper.ApiResponseHandler": "Error"
- },
- "IncludeScopes": false,
- "Debug": {
- "LogLevel": {
- "Default": "Warning"
- }
- },
- "Console": {
- "LogLevel": {
- "Default": "Warning",
- "Microsoft.Hosting.Lifetime": "Debug"
- }
- },
- "Log4Net": {
- "Name": "Blog.Core"
- }
- },
- "AllowedHosts": "*",
- "Redis": {
- "ConnectionString": "127.0.0.1:6319,password=admin"
- },
- "RabbitMQ": {
- "Enabled": false,
- "Connection": "118.25.251.13",
- "UserName": "",
- "Password": "!",
- "RetryCount": 3
- },
- "EventBus": {
- "Enabled": false,
- "SubscriptionClientName": "Blog.Core"
- },
- "AppSettings": {
- "RedisCachingAOP": {
- "Enabled": false
- },
- "MemoryCachingAOP": {
- "Enabled": true
- },
- "LogAOP": {
- "Enabled": false
- },
- "TranAOP": {
- "Enabled": false
- },
- "SqlAOP": {
- "Enabled": true,
- "OutToLogFile": {
- "Enabled": false
- },
- "OutToConsole": {
- "Enabled": true
- }
- },
- "Date": "2018-08-28",
- "SeedDBEnabled": true, //只生成表结构
- "SeedDBDataEnabled": true, //生成表,并初始化数据
- "Author": "Blog.Core",
- "UseLoadTest": false
- },
-
- // 请配置MainDB为你想要的主库的ConnId值,并设置对应的Enabled为true;
- // *** 单库操作,把 MutiDBEnabled 设为false ***;
- // *** 多库操作,把 MutiDBEnabled 设为true,其他的从库Enabled也为true **;
- // 具体配置看视频:https://www.bilibili.com/video/BV1BJ411B7mn?p=6
-
- "MainDB": "WMBLOG_SQLITE", //当前项目的主库,所对应的连接字符串的Enabled必须为true
- "MutiDBEnabled": false, //是否开启多库模式
- "CQRSEnabled": false, //是否开启读写分离模式,必须是单库模式,且数据库类型一致,比如都是SqlServer
- "DBS": [
- /*
- 对应下边的 DBType
- MySql = 0,
- SqlServer = 1,
- Sqlite = 2,
- Oracle = 3,
- PostgreSQL = 4,
- Dm = 5,//达梦
- Kdbndp = 6,//人大金仓
- */
- {
- "ConnId": "WMBLOG_SQLITE",
- "DBType": 2,
- "Enabled": true,
- "HitRate": 50, // 值越大,优先级越高
- "Connection": "WMBlog.db" //sqlite只写数据库名就行
- },
- {
- "ConnId": "WMBLOG_MSSQL_1",
- "DBType": 1,
- "Enabled": false,
- "HitRate": 40,
- "Connection": "Data Source=(localdb)\\MSSQLLocalDB;Initial Catalog=WMBLOG_MSSQL_1;Integrated Security=True;Connect Timeout=30;Encrypt=False;TrustServerCertificate=False;ApplicationIntent=ReadWrite;MultiSubnetFailover=False",
- "ProviderName": "System.Data.SqlClient"
- },
- {
- "ConnId": "WMBLOG_MSSQL_2",
- "DBType": 1,
- "Enabled": false,
- "HitRate": 30,
- "Connection": "Data Source=(localdb)\\MSSQLLocalDB;Initial Catalog=WMBLOG_MSSQL_2;Integrated Security=True;Connect Timeout=30;Encrypt=False;TrustServerCertificate=False;ApplicationIntent=ReadWrite;MultiSubnetFailover=False",
- "ProviderName": "System.Data.SqlClient"
- },
- {
- "ConnId": "WMBLOG_MYSQL",
- "DBType": 0,
- "Enabled": false,
- "HitRate": 20,
- "Connection": "server=.;Database=ddd;Uid=root;Pwd=123456;Port=10060;Allow User Variables=True;"
- },
- {
- "ConnId": "WMBLOG_MYSQL_2",
- "DBType": 0,
- "Enabled": true,
- "HitRate": 20,
- "Connection": "server=.;Database=blogcore001;Uid=root;Pwd=123456;Port=3096;Allow User Variables=True;"
- },
- {
- "ConnId": "WMBLOG_ORACLE",
- "DBType": 3,
- "Enabled": false,
- "HitRate": 10,
- "Connection": "Data Source=127.0.0.1/ops;User ID=OPS;Password=123456;Persist Security Info=True;Connection Timeout=60;"
- },
- {
- "ConnId": "WMBLOG_DM",
- "DBType": 5,
- "Enabled": false,
- "HitRate": 10,
- "Connection": "PORT=5236;DATABASE=DAMENG;HOST=localhost;PASSWORD=SYSDBA;USER ID=SYSDBA;"
- },
- {
- "ConnId": "WMBLOG_KDBNDP",
- "DBType": 6,
- "Enabled": true,
- "HitRate": 10,
- "Connection": "Server=127.0.0.1;Port=54321;UID=SYSTEM;PWD=system;database=SQLSUGAR4XTEST1;"
- }
- ],
- "Audience": {
- "Secret": "sdfsdfsrty45634kkhllghtdgdfss345t678fs", //不要太短,16位+
- "SecretFile": "C:\\my-file\\blog.core.audience.secret.txt", //安全。内容就是Secret
- "Issuer": "Blog.Core",
- "Audience": "wr"
- },
- "Mongo": {
- "ConnectionString": "mongodb://nosql.data",
- "Database": "BlogCoreDb"
- },
- "Startup": {
- "Cors": {
- "PolicyName": "CorsIpAccess", //策略名称
- "EnableAllIPs": false, //当为true时,开放所有IP均可访问。
- // 支持多个域名端口,注意端口号后不要带/斜杆:比如localhost:8000/,是错的
- // 注意,http://127.0.0.1:1818 和 http://localhost:1818 是不一样的
- "IPs": "http://127.0.0.1:2364,http://localhost:2364"
- },
- "AppConfigAlert": {
- "Enabled": true
- },
- "ApiName": "Blog.Core",
- "IdentityServer4": {
- "Enabled": false, // 这里默认是false,表示使用jwt,如果设置为true,则表示系统使用Ids4模式
- "AuthorizationUrl": "http://localhost:5004", // 认证中心域名
- "ApiName": "blog.core.api" // 资源服务器
- },
- "RedisMq": {
- "Enabled": false //redis 消息队列
- },
- "MiniProfiler": {
- "Enabled": false //性能分析开启
- }
- },
- "Middleware": {
- "RequestResponseLog": {
- "Enabled": false
- },
- "IPLog": {
- "Enabled": true
- },
- "RecordAccessLogs": {
- "Enabled": true,
- "IgnoreApis": "/api/permission/getnavigationbar,/api/monitor/getids4users,/api/monitor/getaccesslogs,/api/monitor/server,/api/monitor/getactiveusers,/api/monitor/server,"
- },
- "SignalR": {
- "Enabled": false
- },
- "QuartzNetJob": {
- "Enabled": true
- },
- "Consul": {
- "Enabled": false
- },
- "IpRateLimit": {
- "Enabled": true
- }
- },
- "IpRateLimiting": {
- "EnableEndpointRateLimiting": true, //False: globally executed, true: executed for each
- "StackBlockedRequests": false, //False: Number of rejections should be recorded on another counter
- "RealIpHeader": "X-Real-IP",
- "ClientIdHeader": "X-ClientId",
- "IpWhitelist": [], //白名单
- "EndpointWhitelist": [ "get:/api/xxx", "*:/api/yyy" ],
- "ClientWhitelist": [ "dev-client-1", "dev-client-2" ],
- "QuotaExceededResponse": {
- "Content": "{{\"status\":429,\"msg\":\"访问过于频繁,请稍后重试\",\"success\":false}}",
- "ContentType": "application/json",
- "StatusCode": 429
- },
- "HttpStatusCode": 429, //返回状态码
- "GeneralRules": [ //api规则,结尾一定要带*
- {
- "Endpoint": "*:/api/blog*",
- "Period": "1m",
- "Limit": 20
- },
- {
- "Endpoint": "*/api/*",
- "Period": "1s",
- "Limit": 3
- },
- {
- "Endpoint": "*/api/*",
- "Period": "1m",
- "Limit": 30
- },
- {
- "Endpoint": "*/api/*",
- "Period": "12h",
- "Limit": 500
- }
- ]
-
- },
- "ConsulSetting": {
- "ServiceName": "BlogCoreService",
- "ServiceIP": "localhost",
- "ServicePort": "8081",
- "ServiceHealthCheck": "/healthcheck",
- "ConsulAddress": "http://localhost:8500"
- },
- "PayInfo": { //建行聚合支付信息
- "MERCHANTID": "", //商户号
- "POSID": "", //柜台号
- "BRANCHID": "", //分行号
- "pubKey": "", //公钥
- "USER_ID": "", //操作员号
- "PASSWORD": "", //密码
- "OutAddress": "http://127.0.0.1:12345" //外联地址
- },
- "nacos": {
- "ServerAddresses": [ "http://localhost:8848" ], // nacos 连接地址
- "DefaultTimeOut": 15000, // 默认超时时间
- "Namespace": "public", // 命名空间
- "ListenInterval": 10000, // 监听的频率
- "ServiceName": "blog.Core.Api", // 服务名
- "Port": "8081", // 服务端口号
- "RegisterEnabled": true // 是否直接注册nacos
- }
-}
diff --git a/Blog.Core.Api/appsettings.json b/Blog.Core.Api/appsettings.json
index f41ed9c3..b39bce54 100644
--- a/Blog.Core.Api/appsettings.json
+++ b/Blog.Core.Api/appsettings.json
@@ -257,5 +257,14 @@
"USER_ID": "", //操作员号
"PASSWORD": "", //密码
"OutAddress": "http://127.0.0.1:12345" //外联地址
+ },
+ "nacos": {
+ "ServerAddresses": [ "http://localhost:8848" ], // nacos 连接地址
+ "DefaultTimeOut": 15000, // 默认超时时间
+ "Namespace": "public", // 命名空间
+ "ListenInterval": 10000, // 监听的频率
+ "ServiceName": "blog.Core.Api", // 服务名
+ "Port": "8081", // 服务端口号
+ "RegisterEnabled": true // 是否直接注册nacos
}
}
diff --git a/Blog.Core.Api/appsettings.prod.json b/Blog.Core.Api/appsettings.prod.json
deleted file mode 100644
index 02a6c25e..00000000
--- a/Blog.Core.Api/appsettings.prod.json
+++ /dev/null
@@ -1,258 +0,0 @@
-{
- "urls": "http://*:8081", //web服务端口,如果用IIS部署,把这个去掉
- "Logging": {
- "LogLevel": {
- "Default": "Information", //加入Default否则log4net本地写入不了日志
- "Blog.Core.AuthHelper.ApiResponseHandler": "Error"
- },
- "IncludeScopes": false,
- "Debug": {
- "LogLevel": {
- "Default": "Warning"
- }
- },
- "Console": {
- "LogLevel": {
- "Default": "Warning",
- "Microsoft.Hosting.Lifetime": "Debug"
- }
- },
- "Log4Net": {
- "Name": "Blog.Core"
- }
- },
- "AllowedHosts": "*",
- "Redis": {
- "ConnectionString": "127.0.0.1:6319,password=admin"
- },
- "RabbitMQ": {
- "Enabled": false,
- "Connection": "118.25.251.13",
- "UserName": "",
- "Password": "!",
- "RetryCount": 3
- },
- "EventBus": {
- "Enabled": false,
- "SubscriptionClientName": "Blog.Core"
- },
- "AppSettings": {
- "RedisCachingAOP": {
- "Enabled": false
- },
- "MemoryCachingAOP": {
- "Enabled": true
- },
- "LogAOP": {
- "Enabled": false
- },
- "TranAOP": {
- "Enabled": false
- },
- "SqlAOP": {
- "Enabled": true,
- "OutToLogFile": {
- "Enabled": false
- },
- "OutToConsole": {
- "Enabled": true
- }
- },
- "Date": "2018-08-28",
- "SeedDBEnabled": true, //只生成表结构
- "SeedDBDataEnabled": true, //生成表,并初始化数据
- "Author": "Blog.Core",
- "UseLoadTest": false
- },
-
- // 请配置MainDB为你想要的主库的ConnId值,并设置对应的Enabled为true;
- // *** 单库操作,把 MutiDBEnabled 设为false ***;
- // *** 多库操作,把 MutiDBEnabled 设为true,其他的从库Enabled也为true **;
- // 具体配置看视频:https://www.bilibili.com/video/BV1BJ411B7mn?p=6
-
- "MainDB": "WMBLOG_SQLITE", //当前项目的主库,所对应的连接字符串的Enabled必须为true
- "MutiDBEnabled": false, //是否开启多库模式
- "CQRSEnabled": false, //是否开启读写分离模式,必须是单库模式,且数据库类型一致,比如都是SqlServer
- "DBS": [
- /*
- 对应下边的 DBType
- MySql = 0,
- SqlServer = 1,
- Sqlite = 2,
- Oracle = 3,
- PostgreSQL = 4,
- Dm = 5,//达梦
- Kdbndp = 6,//人大金仓
- */
- {
- "ConnId": "WMBLOG_SQLITE",
- "DBType": 2,
- "Enabled": true,
- "HitRate": 50, // 值越大,优先级越高
- "Connection": "WMBlog.db" //sqlite只写数据库名就行
- },
- {
- "ConnId": "WMBLOG_MSSQL_1",
- "DBType": 1,
- "Enabled": false,
- "HitRate": 40,
- "Connection": "Data Source=(localdb)\\MSSQLLocalDB;Initial Catalog=WMBLOG_MSSQL_1;Integrated Security=True;Connect Timeout=30;Encrypt=False;TrustServerCertificate=False;ApplicationIntent=ReadWrite;MultiSubnetFailover=False",
- "ProviderName": "System.Data.SqlClient"
- },
- {
- "ConnId": "WMBLOG_MSSQL_2",
- "DBType": 1,
- "Enabled": false,
- "HitRate": 30,
- "Connection": "Data Source=(localdb)\\MSSQLLocalDB;Initial Catalog=WMBLOG_MSSQL_2;Integrated Security=True;Connect Timeout=30;Encrypt=False;TrustServerCertificate=False;ApplicationIntent=ReadWrite;MultiSubnetFailover=False",
- "ProviderName": "System.Data.SqlClient"
- },
- {
- "ConnId": "WMBLOG_MYSQL",
- "DBType": 0,
- "Enabled": false,
- "HitRate": 20,
- "Connection": "server=.;Database=ddd;Uid=root;Pwd=123456;Port=10060;Allow User Variables=True;"
- },
- {
- "ConnId": "WMBLOG_MYSQL_2",
- "DBType": 0,
- "Enabled": true,
- "HitRate": 20,
- "Connection": "server=.;Database=blogcore001;Uid=root;Pwd=123456;Port=3096;Allow User Variables=True;"
- },
- {
- "ConnId": "WMBLOG_ORACLE",
- "DBType": 3,
- "Enabled": false,
- "HitRate": 10,
- "Connection": "Data Source=127.0.0.1/ops;User ID=OPS;Password=123456;Persist Security Info=True;Connection Timeout=60;"
- },
- {
- "ConnId": "WMBLOG_DM",
- "DBType": 5,
- "Enabled": false,
- "HitRate": 10,
- "Connection": "PORT=5236;DATABASE=DAMENG;HOST=localhost;PASSWORD=SYSDBA;USER ID=SYSDBA;"
- },
- {
- "ConnId": "WMBLOG_KDBNDP",
- "DBType": 6,
- "Enabled": true,
- "HitRate": 10,
- "Connection": "Server=127.0.0.1;Port=54321;UID=SYSTEM;PWD=system;database=SQLSUGAR4XTEST1;"
- }
- ],
- "Audience": {
- "Secret": "sdfsdfsrty45634kkhllghtdgdfss345t678fs", //不要太短,16位+
- "SecretFile": "C:\\my-file\\blog.core.audience.secret.txt", //安全。内容就是Secret
- "Issuer": "Blog.Core",
- "Audience": "wr"
- },
- "Mongo": {
- "ConnectionString": "mongodb://nosql.data",
- "Database": "BlogCoreDb"
- },
- "Startup": {
- "Cors": {
- "PolicyName": "CorsIpAccess", //策略名称
- "EnableAllIPs": false, //当为true时,开放所有IP均可访问。
- // 支持多个域名端口,注意端口号后不要带/斜杆:比如localhost:8000/,是错的
- // 注意,http://127.0.0.1:1818 和 http://localhost:1818 是不一样的
- "IPs": "http://127.0.0.1:2364,http://localhost:2364"
- },
- "AppConfigAlert": {
- "Enabled": true
- },
- "ApiName": "Blog.Core",
- "IdentityServer4": {
- "Enabled": false, // 这里默认是false,表示使用jwt,如果设置为true,则表示系统使用Ids4模式
- "AuthorizationUrl": "http://localhost:5004", // 认证中心域名
- "ApiName": "blog.core.api" // 资源服务器
- },
- "RedisMq": {
- "Enabled": false //redis 消息队列
- },
- "MiniProfiler": {
- "Enabled": false //性能分析开启
- }
- },
- "Middleware": {
- "RequestResponseLog": {
- "Enabled": false
- },
- "IPLog": {
- "Enabled": true
- },
- "RecordAccessLogs": {
- "Enabled": true,
- "IgnoreApis": "/api/permission/getnavigationbar,/api/monitor/getids4users,/api/monitor/getaccesslogs,/api/monitor/server,/api/monitor/getactiveusers,/api/monitor/server,"
- },
- "SignalR": {
- "Enabled": false
- },
- "QuartzNetJob": {
- "Enabled": true
- },
- "Consul": {
- "Enabled": false
- },
- "IpRateLimit": {
- "Enabled": true
- }
- },
- "IpRateLimiting": {
- "EnableEndpointRateLimiting": true, //False: globally executed, true: executed for each
- "StackBlockedRequests": false, //False: Number of rejections should be recorded on another counter
- "RealIpHeader": "X-Real-IP",
- "ClientIdHeader": "X-ClientId",
- "IpWhitelist": [], //白名单
- "EndpointWhitelist": [ "get:/api/xxx", "*:/api/yyy" ],
- "ClientWhitelist": [ "dev-client-1", "dev-client-2" ],
- "QuotaExceededResponse": {
- "Content": "{{\"status\":429,\"msg\":\"访问过于频繁,请稍后重试\",\"success\":false}}",
- "ContentType": "application/json",
- "StatusCode": 429
- },
- "HttpStatusCode": 429, //返回状态码
- "GeneralRules": [ //api规则,结尾一定要带*
- {
- "Endpoint": "*:/api/blog*",
- "Period": "1m",
- "Limit": 20
- },
- {
- "Endpoint": "*/api/*",
- "Period": "1s",
- "Limit": 3
- },
- {
- "Endpoint": "*/api/*",
- "Period": "1m",
- "Limit": 30
- },
- {
- "Endpoint": "*/api/*",
- "Period": "12h",
- "Limit": 500
- }
- ]
-
- },
- "ConsulSetting": {
- "ServiceName": "BlogCoreService",
- "ServiceIP": "localhost",
- "ServicePort": "8081",
- "ServiceHealthCheck": "/healthcheck",
- "ConsulAddress": "http://localhost:8500"
- },
- "PayInfo": { //建行聚合支付信息
- "MERCHANTID": "", //商户号
- "POSID": "", //柜台号
- "BRANCHID": "", //分行号
- "pubKey": "", //公钥
- "USER_ID": "", //操作员号
- "PASSWORD": "", //密码
- "OutAddress": "http://127.0.0.1:12345" //外联地址
- }
-}
diff --git a/Blog.Core.Api/appsettings.test.json b/Blog.Core.Api/appsettings.test.json
deleted file mode 100644
index 02a6c25e..00000000
--- a/Blog.Core.Api/appsettings.test.json
+++ /dev/null
@@ -1,258 +0,0 @@
-{
- "urls": "http://*:8081", //web服务端口,如果用IIS部署,把这个去掉
- "Logging": {
- "LogLevel": {
- "Default": "Information", //加入Default否则log4net本地写入不了日志
- "Blog.Core.AuthHelper.ApiResponseHandler": "Error"
- },
- "IncludeScopes": false,
- "Debug": {
- "LogLevel": {
- "Default": "Warning"
- }
- },
- "Console": {
- "LogLevel": {
- "Default": "Warning",
- "Microsoft.Hosting.Lifetime": "Debug"
- }
- },
- "Log4Net": {
- "Name": "Blog.Core"
- }
- },
- "AllowedHosts": "*",
- "Redis": {
- "ConnectionString": "127.0.0.1:6319,password=admin"
- },
- "RabbitMQ": {
- "Enabled": false,
- "Connection": "118.25.251.13",
- "UserName": "",
- "Password": "!",
- "RetryCount": 3
- },
- "EventBus": {
- "Enabled": false,
- "SubscriptionClientName": "Blog.Core"
- },
- "AppSettings": {
- "RedisCachingAOP": {
- "Enabled": false
- },
- "MemoryCachingAOP": {
- "Enabled": true
- },
- "LogAOP": {
- "Enabled": false
- },
- "TranAOP": {
- "Enabled": false
- },
- "SqlAOP": {
- "Enabled": true,
- "OutToLogFile": {
- "Enabled": false
- },
- "OutToConsole": {
- "Enabled": true
- }
- },
- "Date": "2018-08-28",
- "SeedDBEnabled": true, //只生成表结构
- "SeedDBDataEnabled": true, //生成表,并初始化数据
- "Author": "Blog.Core",
- "UseLoadTest": false
- },
-
- // 请配置MainDB为你想要的主库的ConnId值,并设置对应的Enabled为true;
- // *** 单库操作,把 MutiDBEnabled 设为false ***;
- // *** 多库操作,把 MutiDBEnabled 设为true,其他的从库Enabled也为true **;
- // 具体配置看视频:https://www.bilibili.com/video/BV1BJ411B7mn?p=6
-
- "MainDB": "WMBLOG_SQLITE", //当前项目的主库,所对应的连接字符串的Enabled必须为true
- "MutiDBEnabled": false, //是否开启多库模式
- "CQRSEnabled": false, //是否开启读写分离模式,必须是单库模式,且数据库类型一致,比如都是SqlServer
- "DBS": [
- /*
- 对应下边的 DBType
- MySql = 0,
- SqlServer = 1,
- Sqlite = 2,
- Oracle = 3,
- PostgreSQL = 4,
- Dm = 5,//达梦
- Kdbndp = 6,//人大金仓
- */
- {
- "ConnId": "WMBLOG_SQLITE",
- "DBType": 2,
- "Enabled": true,
- "HitRate": 50, // 值越大,优先级越高
- "Connection": "WMBlog.db" //sqlite只写数据库名就行
- },
- {
- "ConnId": "WMBLOG_MSSQL_1",
- "DBType": 1,
- "Enabled": false,
- "HitRate": 40,
- "Connection": "Data Source=(localdb)\\MSSQLLocalDB;Initial Catalog=WMBLOG_MSSQL_1;Integrated Security=True;Connect Timeout=30;Encrypt=False;TrustServerCertificate=False;ApplicationIntent=ReadWrite;MultiSubnetFailover=False",
- "ProviderName": "System.Data.SqlClient"
- },
- {
- "ConnId": "WMBLOG_MSSQL_2",
- "DBType": 1,
- "Enabled": false,
- "HitRate": 30,
- "Connection": "Data Source=(localdb)\\MSSQLLocalDB;Initial Catalog=WMBLOG_MSSQL_2;Integrated Security=True;Connect Timeout=30;Encrypt=False;TrustServerCertificate=False;ApplicationIntent=ReadWrite;MultiSubnetFailover=False",
- "ProviderName": "System.Data.SqlClient"
- },
- {
- "ConnId": "WMBLOG_MYSQL",
- "DBType": 0,
- "Enabled": false,
- "HitRate": 20,
- "Connection": "server=.;Database=ddd;Uid=root;Pwd=123456;Port=10060;Allow User Variables=True;"
- },
- {
- "ConnId": "WMBLOG_MYSQL_2",
- "DBType": 0,
- "Enabled": true,
- "HitRate": 20,
- "Connection": "server=.;Database=blogcore001;Uid=root;Pwd=123456;Port=3096;Allow User Variables=True;"
- },
- {
- "ConnId": "WMBLOG_ORACLE",
- "DBType": 3,
- "Enabled": false,
- "HitRate": 10,
- "Connection": "Data Source=127.0.0.1/ops;User ID=OPS;Password=123456;Persist Security Info=True;Connection Timeout=60;"
- },
- {
- "ConnId": "WMBLOG_DM",
- "DBType": 5,
- "Enabled": false,
- "HitRate": 10,
- "Connection": "PORT=5236;DATABASE=DAMENG;HOST=localhost;PASSWORD=SYSDBA;USER ID=SYSDBA;"
- },
- {
- "ConnId": "WMBLOG_KDBNDP",
- "DBType": 6,
- "Enabled": true,
- "HitRate": 10,
- "Connection": "Server=127.0.0.1;Port=54321;UID=SYSTEM;PWD=system;database=SQLSUGAR4XTEST1;"
- }
- ],
- "Audience": {
- "Secret": "sdfsdfsrty45634kkhllghtdgdfss345t678fs", //不要太短,16位+
- "SecretFile": "C:\\my-file\\blog.core.audience.secret.txt", //安全。内容就是Secret
- "Issuer": "Blog.Core",
- "Audience": "wr"
- },
- "Mongo": {
- "ConnectionString": "mongodb://nosql.data",
- "Database": "BlogCoreDb"
- },
- "Startup": {
- "Cors": {
- "PolicyName": "CorsIpAccess", //策略名称
- "EnableAllIPs": false, //当为true时,开放所有IP均可访问。
- // 支持多个域名端口,注意端口号后不要带/斜杆:比如localhost:8000/,是错的
- // 注意,http://127.0.0.1:1818 和 http://localhost:1818 是不一样的
- "IPs": "http://127.0.0.1:2364,http://localhost:2364"
- },
- "AppConfigAlert": {
- "Enabled": true
- },
- "ApiName": "Blog.Core",
- "IdentityServer4": {
- "Enabled": false, // 这里默认是false,表示使用jwt,如果设置为true,则表示系统使用Ids4模式
- "AuthorizationUrl": "http://localhost:5004", // 认证中心域名
- "ApiName": "blog.core.api" // 资源服务器
- },
- "RedisMq": {
- "Enabled": false //redis 消息队列
- },
- "MiniProfiler": {
- "Enabled": false //性能分析开启
- }
- },
- "Middleware": {
- "RequestResponseLog": {
- "Enabled": false
- },
- "IPLog": {
- "Enabled": true
- },
- "RecordAccessLogs": {
- "Enabled": true,
- "IgnoreApis": "/api/permission/getnavigationbar,/api/monitor/getids4users,/api/monitor/getaccesslogs,/api/monitor/server,/api/monitor/getactiveusers,/api/monitor/server,"
- },
- "SignalR": {
- "Enabled": false
- },
- "QuartzNetJob": {
- "Enabled": true
- },
- "Consul": {
- "Enabled": false
- },
- "IpRateLimit": {
- "Enabled": true
- }
- },
- "IpRateLimiting": {
- "EnableEndpointRateLimiting": true, //False: globally executed, true: executed for each
- "StackBlockedRequests": false, //False: Number of rejections should be recorded on another counter
- "RealIpHeader": "X-Real-IP",
- "ClientIdHeader": "X-ClientId",
- "IpWhitelist": [], //白名单
- "EndpointWhitelist": [ "get:/api/xxx", "*:/api/yyy" ],
- "ClientWhitelist": [ "dev-client-1", "dev-client-2" ],
- "QuotaExceededResponse": {
- "Content": "{{\"status\":429,\"msg\":\"访问过于频繁,请稍后重试\",\"success\":false}}",
- "ContentType": "application/json",
- "StatusCode": 429
- },
- "HttpStatusCode": 429, //返回状态码
- "GeneralRules": [ //api规则,结尾一定要带*
- {
- "Endpoint": "*:/api/blog*",
- "Period": "1m",
- "Limit": 20
- },
- {
- "Endpoint": "*/api/*",
- "Period": "1s",
- "Limit": 3
- },
- {
- "Endpoint": "*/api/*",
- "Period": "1m",
- "Limit": 30
- },
- {
- "Endpoint": "*/api/*",
- "Period": "12h",
- "Limit": 500
- }
- ]
-
- },
- "ConsulSetting": {
- "ServiceName": "BlogCoreService",
- "ServiceIP": "localhost",
- "ServicePort": "8081",
- "ServiceHealthCheck": "/healthcheck",
- "ConsulAddress": "http://localhost:8500"
- },
- "PayInfo": { //建行聚合支付信息
- "MERCHANTID": "", //商户号
- "POSID": "", //柜台号
- "BRANCHID": "", //分行号
- "pubKey": "", //公钥
- "USER_ID": "", //操作员号
- "PASSWORD": "", //密码
- "OutAddress": "http://127.0.0.1:12345" //外联地址
- }
-}
From cba72686d515ec36f6aeffeb624073822ee4ee94 Mon Sep 17 00:00:00 2001
From: tianyu
Date: Wed, 28 Jul 2021 15:24:33 +0800
Subject: [PATCH 053/456] =?UTF-8?q?bhsw=20=E4=BF=AE=E6=94=B9nacos?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
Blog.Core.Api/Controllers/NacosController.cs | 20 ++++++++++++++++++++
1 file changed, 20 insertions(+)
diff --git a/Blog.Core.Api/Controllers/NacosController.cs b/Blog.Core.Api/Controllers/NacosController.cs
index d2d94cfc..8c824296 100644
--- a/Blog.Core.Api/Controllers/NacosController.cs
+++ b/Blog.Core.Api/Controllers/NacosController.cs
@@ -38,6 +38,26 @@ public NacosController(INacosNamingService nacosNamingService)
#endregion
+
+ ///
+ /// 系统实例是否启动完成
+ ///
+ ///
+ [HttpGet]
+
+ public async Task> checkSystemStartFinish()
+ {
+ //********************* 用当前接口做基本健康检查 确定 基础服务 数据库 缓存都已正常启动*****
+ // 然后再进行服务上线
+ var data = new MessageModel();
+ // *************** 此处请求一下db 跟redis连接等 项目中简介 保证项目已全部启动
+ data.success = true;
+ data.msg = "SUCCESS";
+ return data;
+
+ }
+
+
///
/// 获取Nacos 状态
///
From 81e8a44441e5d40886bee037b557625920c2c656 Mon Sep 17 00:00:00 2001
From: hudingwen <765472804@qq.com>
Date: Thu, 29 Jul 2021 15:29:13 +0800
Subject: [PATCH 054/456] =?UTF-8?q?=E5=88=86=E6=94=AF=E6=B5=8B=E8=AF=95=20?=
=?UTF-8?q?=E7=9B=AE=E5=BD=95=E8=B0=83=E6=95=B4?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
Blog.Core.Api/Blog.Core.Model.xml | 263 +-----------------
.../Controllers/DbFirst/DbFirstController.cs | 2 +-
Blog.Core.Api/Startup.cs | 2 +-
Blog.Core.Common/Blog.Core.Common.csproj | 5 +
Blog.Core.Common/Helper/JsonHelper.cs | 38 ++-
.../Seed/DBSeed.cs | 5 +-
.../Seed/FrameSeed.cs | 3 +-
.../Seed/MyContext.cs | 2 +-
.../{StaticHelper => Static}/StaticPayInfo.cs | 2 +-
.../Middlewares/SeedDataMildd.cs | 2 +-
.../ServiceExtensions/DbSetup.cs | 2 +-
.../Blog.Core.IServices.csproj | 1 +
Blog.Core.Model/Blog.Core.Model.csproj | 6 +-
Blog.Core.Repository/BASE/BaseRepository.cs | 1 -
.../Blog.Core.Repository.csproj | 1 +
Blog.Core.Services/PayServices.cs | 2 +-
Blog.Core.Tasks/Blog.Core.Tasks.csproj | 1 +
.../QuartzNet/Jobs/Job_OperateLog_Quartz.cs | 1 -
.../DependencyInjection/DI_Test.cs | 2 +-
19 files changed, 61 insertions(+), 280 deletions(-)
rename {Blog.Core.Model => Blog.Core.Common}/Seed/DBSeed.cs (99%)
rename {Blog.Core.Model => Blog.Core.Common}/Seed/FrameSeed.cs (99%)
rename {Blog.Core.Model => Blog.Core.Common}/Seed/MyContext.cs (99%)
rename Blog.Core.Common/{StaticHelper => Static}/StaticPayInfo.cs (97%)
diff --git a/Blog.Core.Api/Blog.Core.Model.xml b/Blog.Core.Api/Blog.Core.Model.xml
index ce6dd052..4befdebc 100644
--- a/Blog.Core.Api/Blog.Core.Model.xml
+++ b/Blog.Core.Api/Blog.Core.Model.xml
@@ -96,6 +96,11 @@
返回信息
+
+
+ 开发者信息
+
+
返回数据集合
@@ -1007,264 +1012,6 @@
找不到指定资源
-
-
- 异步添加种子数据
-
-
-
-
-
-
-
- 生成Controller层
-
- sqlsugar实例
- 数据库链接ID
- 数据库表名数组,默认空,生成所有表
-
-
-
-
-
- 生成Model层
-
- sqlsugar实例
- 数据库链接ID
- 数据库表名数组,默认空,生成所有表
-
-
-
-
-
- 生成IRepository层
-
- sqlsugar实例
- 数据库链接ID
-
- 数据库表名数组,默认空,生成所有表
-
-
-
-
- 生成 IService 层
-
- sqlsugar实例
- 数据库链接ID
-
- 数据库表名数组,默认空,生成所有表
-
-
-
-
- 生成 Repository 层
-
- sqlsugar实例
- 数据库链接ID
-
- 数据库表名数组,默认空,生成所有表
-
-
-
-
- 生成 Service 层
-
- sqlsugar实例
- 数据库链接ID
-
- 数据库表名数组,默认空,生成所有表
-
-
-
-
- 功能描述:根据数据库表生产Controller层
- 作 者:Blog.Core
-
-
- 数据库链接ID
- 实体类存放路径
- 命名空间
- 生产指定的表
- 实现接口
-
- 是否序列化
-
-
-
- 功能描述:根据数据库表生产Model层
- 作 者:Blog.Core
-
-
- 数据库链接ID
- 实体类存放路径
- 命名空间
- 生产指定的表
- 实现接口
-
- 是否序列化
-
-
-
- 功能描述:根据数据库表生产IRepository层
- 作 者:Blog.Core
-
-
- 数据库链接ID
- 实体类存放路径
- 命名空间
- 生产指定的表
- 实现接口
-
-
-
-
- 功能描述:根据数据库表生产IServices层
- 作 者:Blog.Core
-
-
- 数据库链接ID
- 实体类存放路径
- 命名空间
- 生产指定的表
- 实现接口
-
-
-
-
- 功能描述:根据数据库表生产 Repository 层
- 作 者:Blog.Core
-
-
- 数据库链接ID
- 实体类存放路径
- 命名空间
- 生产指定的表
- 实现接口
-
-
-
-
- 功能描述:根据数据库表生产 Services 层
- 作 者:Blog.Core
-
-
- 数据库链接ID
- 实体类存放路径
- 命名空间
- 生产指定的表
- 实现接口
-
-
-
-
- 根据模板内容批量生成文件
-
- 类文件字符串list
- 生成路径
- 文件名格式模板
-
-
-
- 连接字符串
- Blog.Core
-
-
-
-
- 连接字符串
- Blog.Core
-
-
-
-
- 数据库类型
- Blog.Core
-
-
-
-
- 数据连接对象
- Blog.Core
-
-
-
-
- 功能描述:构造函数
- 作 者:Blog.Core
-
-
-
-
- 功能描述:获取数据库处理对象
- 作 者:Blog.Core
-
- 返回值
-
-
-
- 功能描述:获取数据库处理对象
- 作 者:Blog.Core
-
- db
- 返回值
-
-
-
- 功能描述:根据实体类生成数据库表
- 作 者:Blog.Core
-
- 是否备份表
- 指定的实体
-
-
-
- 功能描述:根据实体类生成数据库表
- 作 者:Blog.Core
-
- 是否备份表
- 指定的实体
-
-
-
- 功能描述:设置初始化参数
- 作 者:Blog.Core
-
- 连接字符串
- 数据库类型
-
-
-
- 功能描述:创建一个链接配置
- 作 者:Blog.Core
-
- 是否自动关闭连接
- 是否夸类事务
- ConnectionConfig
-
-
-
- 功能描述:获取一个自定义的DB
- 作 者:Blog.Core
-
- config
- 返回值
-
-
-
- 功能描述:获取一个自定义的数据库处理对象
- 作 者:Blog.Core
-
- sugarClient
- 返回值
-
-
-
- 功能描述:获取一个自定义的数据库处理对象
- 作 者:Blog.Core
-
- config
- 返回值
-
表格数据,支持分页
diff --git a/Blog.Core.Api/Controllers/DbFirst/DbFirstController.cs b/Blog.Core.Api/Controllers/DbFirst/DbFirstController.cs
index cad64362..464c3eaf 100644
--- a/Blog.Core.Api/Controllers/DbFirst/DbFirstController.cs
+++ b/Blog.Core.Api/Controllers/DbFirst/DbFirstController.cs
@@ -1,7 +1,7 @@
using Blog.Core.Common;
using Blog.Core.Common.DB;
+using Blog.Core.Common.Seed;
using Blog.Core.Model;
-using Blog.Core.Model.Seed;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Hosting;
diff --git a/Blog.Core.Api/Startup.cs b/Blog.Core.Api/Startup.cs
index f75a7df5..35ab31ea 100644
--- a/Blog.Core.Api/Startup.cs
+++ b/Blog.Core.Api/Startup.cs
@@ -1,12 +1,12 @@
using Autofac;
using Blog.Core.Common;
using Blog.Core.Common.LogHelper;
+using Blog.Core.Common.Seed;
using Blog.Core.Extensions;
using Blog.Core.Filter;
using Blog.Core.Hubs;
using Blog.Core.IServices;
using Blog.Core.Middlewares;
-using Blog.Core.Model.Seed;
using Blog.Core.Tasks;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
diff --git a/Blog.Core.Common/Blog.Core.Common.csproj b/Blog.Core.Common/Blog.Core.Common.csproj
index 92af0184..8073607d 100644
--- a/Blog.Core.Common/Blog.Core.Common.csproj
+++ b/Blog.Core.Common/Blog.Core.Common.csproj
@@ -17,6 +17,7 @@
+
@@ -32,4 +33,8 @@
+
+
+
+
diff --git a/Blog.Core.Common/Helper/JsonHelper.cs b/Blog.Core.Common/Helper/JsonHelper.cs
index 352cb8e1..a615abf0 100644
--- a/Blog.Core.Common/Helper/JsonHelper.cs
+++ b/Blog.Core.Common/Helper/JsonHelper.cs
@@ -1,11 +1,46 @@
using System;
using System.Collections.Generic;
-using System.Text.Json;
+
namespace Blog.Core.Common.Helper
{
public class JsonHelper
{
+ ///
+ /// 对象序列化
+ ///
+ /// 对象
+ /// 是否使用textjson
+ /// 返回json字符串
+ public static string ObjToJson(object obj, bool isUseTextJson = false)
+ {
+ if (isUseTextJson)
+ {
+ return System.Text.Json.JsonSerializer.Serialize(obj);
+ }
+ else
+ {
+ return Newtonsoft.Json.JsonConvert.SerializeObject(obj);
+ }
+ }
+ ///
+ /// json反序列化obj
+ ///
+ /// 反序列类型
+ /// json
+ /// 是否使用textjson
+ /// 返回对象
+ public static T JsonToObj(string strJson, bool isUseTextJson = false)
+ {
+ if (isUseTextJson)
+ {
+ return System.Text.Json.JsonSerializer.Deserialize(strJson);
+ }
+ else
+ {
+ return Newtonsoft.Json.JsonConvert.DeserializeObject(strJson);
+ }
+ }
///
/// 转换对象为JSON格式数据
///
@@ -17,7 +52,6 @@ public static string GetJSON(object obj)
string result = String.Empty;
try
{
- JsonSerializer.Serialize("");
System.Runtime.Serialization.Json.DataContractJsonSerializer serializer =
new System.Runtime.Serialization.Json.DataContractJsonSerializer(typeof(T));
using (System.IO.MemoryStream ms = new System.IO.MemoryStream())
diff --git a/Blog.Core.Model/Seed/DBSeed.cs b/Blog.Core.Common/Seed/DBSeed.cs
similarity index 99%
rename from Blog.Core.Model/Seed/DBSeed.cs
rename to Blog.Core.Common/Seed/DBSeed.cs
index bb649a84..05ced06c 100644
--- a/Blog.Core.Model/Seed/DBSeed.cs
+++ b/Blog.Core.Common/Seed/DBSeed.cs
@@ -1,5 +1,4 @@
-using Blog.Core.Common;
-using Blog.Core.Common.DB;
+using Blog.Core.Common.DB;
using Blog.Core.Common.Helper;
using Blog.Core.Model.Models;
using Newtonsoft.Json;
@@ -11,7 +10,7 @@
using System.Text;
using System.Threading.Tasks;
-namespace Blog.Core.Model.Seed
+namespace Blog.Core.Common.Seed
{
public class DBSeed
{
diff --git a/Blog.Core.Model/Seed/FrameSeed.cs b/Blog.Core.Common/Seed/FrameSeed.cs
similarity index 99%
rename from Blog.Core.Model/Seed/FrameSeed.cs
rename to Blog.Core.Common/Seed/FrameSeed.cs
index 2ac7d916..649f5cd6 100644
--- a/Blog.Core.Model/Seed/FrameSeed.cs
+++ b/Blog.Core.Common/Seed/FrameSeed.cs
@@ -1,11 +1,10 @@
using SqlSugar;
-using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
-namespace Blog.Core.Model.Seed
+namespace Blog.Core.Common.Seed
{
public class FrameSeed
{
diff --git a/Blog.Core.Model/Seed/MyContext.cs b/Blog.Core.Common/Seed/MyContext.cs
similarity index 99%
rename from Blog.Core.Model/Seed/MyContext.cs
rename to Blog.Core.Common/Seed/MyContext.cs
index e4d71328..8b1e1d14 100644
--- a/Blog.Core.Model/Seed/MyContext.cs
+++ b/Blog.Core.Common/Seed/MyContext.cs
@@ -2,7 +2,7 @@
using SqlSugar;
using System;
-namespace Blog.Core.Model.Seed
+namespace Blog.Core.Common.Seed
{
public class MyContext
{
diff --git a/Blog.Core.Common/StaticHelper/StaticPayInfo.cs b/Blog.Core.Common/Static/StaticPayInfo.cs
similarity index 97%
rename from Blog.Core.Common/StaticHelper/StaticPayInfo.cs
rename to Blog.Core.Common/Static/StaticPayInfo.cs
index 36a62d4b..4b73493f 100644
--- a/Blog.Core.Common/StaticHelper/StaticPayInfo.cs
+++ b/Blog.Core.Common/Static/StaticPayInfo.cs
@@ -1,6 +1,6 @@
-namespace Blog.Core.Common.StaticHelper
+namespace Blog.Core.Common.Static
{
public static class StaticPayInfo
{
diff --git a/Blog.Core.Extensions/Middlewares/SeedDataMildd.cs b/Blog.Core.Extensions/Middlewares/SeedDataMildd.cs
index 5fb621e7..0c64bc8e 100644
--- a/Blog.Core.Extensions/Middlewares/SeedDataMildd.cs
+++ b/Blog.Core.Extensions/Middlewares/SeedDataMildd.cs
@@ -1,5 +1,5 @@
using Blog.Core.Common;
-using Blog.Core.Model.Seed;
+using Blog.Core.Common.Seed;
using log4net;
using Microsoft.AspNetCore.Builder;
using System;
diff --git a/Blog.Core.Extensions/ServiceExtensions/DbSetup.cs b/Blog.Core.Extensions/ServiceExtensions/DbSetup.cs
index ac6668d1..b00470ab 100644
--- a/Blog.Core.Extensions/ServiceExtensions/DbSetup.cs
+++ b/Blog.Core.Extensions/ServiceExtensions/DbSetup.cs
@@ -1,4 +1,4 @@
-using Blog.Core.Model.Seed;
+using Blog.Core.Common.Seed;
using Microsoft.Extensions.DependencyInjection;
using System;
diff --git a/Blog.Core.IServices/Blog.Core.IServices.csproj b/Blog.Core.IServices/Blog.Core.IServices.csproj
index 937d8104..e1055a78 100644
--- a/Blog.Core.IServices/Blog.Core.IServices.csproj
+++ b/Blog.Core.IServices/Blog.Core.IServices.csproj
@@ -5,6 +5,7 @@
+
diff --git a/Blog.Core.Model/Blog.Core.Model.csproj b/Blog.Core.Model/Blog.Core.Model.csproj
index 2111ab86..c5e83d77 100644
--- a/Blog.Core.Model/Blog.Core.Model.csproj
+++ b/Blog.Core.Model/Blog.Core.Model.csproj
@@ -15,11 +15,7 @@
-
-
-
-
-
+
diff --git a/Blog.Core.Repository/BASE/BaseRepository.cs b/Blog.Core.Repository/BASE/BaseRepository.cs
index 55fd0e11..2c100dcf 100644
--- a/Blog.Core.Repository/BASE/BaseRepository.cs
+++ b/Blog.Core.Repository/BASE/BaseRepository.cs
@@ -3,7 +3,6 @@
using Blog.Core.IRepository.Base;
using Blog.Core.IRepository.UnitOfWork;
using Blog.Core.Model;
-using Blog.Core.Model.Models;
using SqlSugar;
using System;
using System.Collections.Generic;
diff --git a/Blog.Core.Repository/Blog.Core.Repository.csproj b/Blog.Core.Repository/Blog.Core.Repository.csproj
index db11e99d..2697a74d 100644
--- a/Blog.Core.Repository/Blog.Core.Repository.csproj
+++ b/Blog.Core.Repository/Blog.Core.Repository.csproj
@@ -25,6 +25,7 @@
+
diff --git a/Blog.Core.Services/PayServices.cs b/Blog.Core.Services/PayServices.cs
index 73331b2d..ed5b6a55 100644
--- a/Blog.Core.Services/PayServices.cs
+++ b/Blog.Core.Services/PayServices.cs
@@ -1,6 +1,6 @@
using Blog.Core.Common;
using Blog.Core.Common.Helper;
-using Blog.Core.Common.StaticHelper;
+using Blog.Core.Common.Static;
using Blog.Core.IRepository.Base;
using Blog.Core.IServices;
using Blog.Core.Model;
diff --git a/Blog.Core.Tasks/Blog.Core.Tasks.csproj b/Blog.Core.Tasks/Blog.Core.Tasks.csproj
index e41f726e..0dc571bf 100644
--- a/Blog.Core.Tasks/Blog.Core.Tasks.csproj
+++ b/Blog.Core.Tasks/Blog.Core.Tasks.csproj
@@ -9,6 +9,7 @@
+
diff --git a/Blog.Core.Tasks/QuartzNet/Jobs/Job_OperateLog_Quartz.cs b/Blog.Core.Tasks/QuartzNet/Jobs/Job_OperateLog_Quartz.cs
index e2c479ed..8e9b3847 100644
--- a/Blog.Core.Tasks/QuartzNet/Jobs/Job_OperateLog_Quartz.cs
+++ b/Blog.Core.Tasks/QuartzNet/Jobs/Job_OperateLog_Quartz.cs
@@ -2,7 +2,6 @@
using Blog.Core.IServices;
using Blog.Core.Model.Models;
using Microsoft.AspNetCore.Hosting;
-using Microsoft.Extensions.Logging;
using Quartz;
using System;
using System.Collections.Generic;
diff --git a/Blog.Core.Tests/DependencyInjection/DI_Test.cs b/Blog.Core.Tests/DependencyInjection/DI_Test.cs
index 550f7a85..7ef085a4 100644
--- a/Blog.Core.Tests/DependencyInjection/DI_Test.cs
+++ b/Blog.Core.Tests/DependencyInjection/DI_Test.cs
@@ -7,9 +7,9 @@
using Blog.Core.Common.AppConfig;
using Blog.Core.Common.DB;
using Blog.Core.Common.LogHelper;
+using Blog.Core.Common.Seed;
using Blog.Core.IRepository.Base;
using Blog.Core.IServices;
-using Blog.Core.Model.Seed;
using Blog.Core.Repository.Base;
using Blog.Core.Services;
using Microsoft.Extensions.DependencyInjection;
From d9d6431a4b9d331541041e2b9dda8bb7b28b3269 Mon Sep 17 00:00:00 2001
From: anjoy8 <3143422472@qq.com>
Date: Fri, 30 Jul 2021 10:36:08 +0800
Subject: [PATCH 055/456] =?UTF-8?q?fix=EF=BC=9Aconfig=20nacos=20launch?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
Blog.Core.Api/Blog.Core.xml | 6 ++++++
Blog.Core.Api/Properties/launchSettings.json | 2 +-
Blog.Core.Extensions/NacosConfig/NacosListenNamingTask.cs | 1 +
Blog.Core.Extensions/ServiceExtensions/NacosSetup.cs | 4 +---
4 files changed, 9 insertions(+), 4 deletions(-)
diff --git a/Blog.Core.Api/Blog.Core.xml b/Blog.Core.Api/Blog.Core.xml
index 3f79cf4e..35c54ff6 100644
--- a/Blog.Core.Api/Blog.Core.xml
+++ b/Blog.Core.Api/Blog.Core.xml
@@ -829,6 +829,12 @@
+
+
+ 系统实例是否启动完成
+
+
+
获取Nacos 状态
diff --git a/Blog.Core.Api/Properties/launchSettings.json b/Blog.Core.Api/Properties/launchSettings.json
index 75116a3b..891d625b 100644
--- a/Blog.Core.Api/Properties/launchSettings.json
+++ b/Blog.Core.Api/Properties/launchSettings.json
@@ -13,7 +13,7 @@
"commandName": "Project",
"launchBrowser": true,
"environmentVariables": {
- "ASPNETCORE_ENVIRONMENT": "dev"
+ "ASPNETCORE_ENVIRONMENT": ""
},
"applicationUrl": "http://localhost:8081"
},
diff --git a/Blog.Core.Extensions/NacosConfig/NacosListenNamingTask.cs b/Blog.Core.Extensions/NacosConfig/NacosListenNamingTask.cs
index d2228673..baca9378 100644
--- a/Blog.Core.Extensions/NacosConfig/NacosListenNamingTask.cs
+++ b/Blog.Core.Extensions/NacosConfig/NacosListenNamingTask.cs
@@ -50,6 +50,7 @@ protected override async Task ExecuteAsync(CancellationToken stoppingToken)
Metadata = JsonConfigSettings.NacosMetadata
};
await _nacosNamingService.RegisterInstance(JsonConfigSettings.NacosServiceName, Nacos.V2.Common.Constants.DEFAULT_GROUP, instance);
+ ConsoleHelper.WriteSuccessLine($"Nacos connect: Success!");
}
// 程序停止
diff --git a/Blog.Core.Extensions/ServiceExtensions/NacosSetup.cs b/Blog.Core.Extensions/ServiceExtensions/NacosSetup.cs
index e3b95c20..fab03514 100644
--- a/Blog.Core.Extensions/ServiceExtensions/NacosSetup.cs
+++ b/Blog.Core.Extensions/ServiceExtensions/NacosSetup.cs
@@ -19,9 +19,7 @@ public static void AddNacosSetup(this IServiceCollection services, IConfiguratio
// 在实际生产工作中 本地开发是不需要注册nacos的 所以根据环境变量去判断
// 比如 开发环境 dev 测试环境 test 生产 prod 只有这几种环境变量的时候才需要去注册nacos
- if (Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT") != null
- && Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT") != ""
- && Appsettings.app(new string[] { "Startup", "Nacos", "Enabled" }).ObjToBool())
+ if (Appsettings.app(new string[] { "Startup", "Nacos", "Enabled" }).ObjToBool())
{
// 从当前配置取文件去注册naocs
services.AddNacosV2Config(x =>
From 93d5f31d30fc92ca9be860a8fa4eed5ccc46047b Mon Sep 17 00:00:00 2001
From: tianyu
Date: Tue, 3 Aug 2021 16:21:35 +0800
Subject: [PATCH 056/456] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=20Serilog=20=20?=
=?UTF-8?q?=E4=BD=BF=E7=94=A8tcp=E7=9A=84=E6=96=B9=E5=BC=8F=E8=87=AA?=
=?UTF-8?q?=E5=AE=9A=E4=B9=89=E6=A0=BC=E5=BC=8F=E5=8C=96=20=E5=86=99?=
=?UTF-8?q?=E5=85=A5elk=E7=9A=84=E5=AE=9E=E7=8E=B0=20by=20=20=E7=94=B0?=
=?UTF-8?q?=E9=9B=A8=20=20github=20=20www5255977?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
Blog.Core.Api/Controllers/LoginController.cs | 4 +-
Blog.Core.Api/appsettings.json | 10 +
Blog.Core.Common/Blog.Core.Common.csproj | 4 +
Blog.Core.Common/Helper/JsonConfigUtils.cs | 1 -
.../LogHelper/Seri/SerilogServer.cs | 9 +-
.../NacosListenConfigurationTask.cs | 2 +-
.../NacosConfig/NacosListenNamingTask.cs | 3 -
.../AppSettingsFileNameConfig.cs | 30 ++
.../Blog.Core.Serilog.Es.csproj | 17 +
.../Formatters/JsonConfigUtils.cs | 66 ++++
.../Formatters/LogConfigRootDTO.cs | 26 ++
.../Formatters/LogstashJsonFormatter.cs | 152 ++++++++
.../HttpInfo/HttpContextProvider.cs | 20 ++
Blog.Core.Serilog.Es/HttpInfo/ParamsHelper.cs | 82 +++++
.../NetworkLoggerConfigurationExtensions.cs | 102 ++++++
Blog.Core.Serilog.Es/Sinks/TCP/TCPSink.cs | 44 +++
.../Sinks/TCP/TCPSocketWriter.cs | 325 ++++++++++++++++++
Blog.Core.Serilog.Es/Sinks/UDP/UDPSink.cs | 42 +++
Blog.Core.sln | 6 +
19 files changed, 938 insertions(+), 7 deletions(-)
create mode 100644 Blog.Core.Serilog.Es/AppSettingsFileNameConfig.cs
create mode 100644 Blog.Core.Serilog.Es/Blog.Core.Serilog.Es.csproj
create mode 100644 Blog.Core.Serilog.Es/Formatters/JsonConfigUtils.cs
create mode 100644 Blog.Core.Serilog.Es/Formatters/LogConfigRootDTO.cs
create mode 100644 Blog.Core.Serilog.Es/Formatters/LogstashJsonFormatter.cs
create mode 100644 Blog.Core.Serilog.Es/HttpInfo/HttpContextProvider.cs
create mode 100644 Blog.Core.Serilog.Es/HttpInfo/ParamsHelper.cs
create mode 100644 Blog.Core.Serilog.Es/NetworkLoggerConfigurationExtensions.cs
create mode 100644 Blog.Core.Serilog.Es/Sinks/TCP/TCPSink.cs
create mode 100644 Blog.Core.Serilog.Es/Sinks/TCP/TCPSocketWriter.cs
create mode 100644 Blog.Core.Serilog.Es/Sinks/UDP/UDPSink.cs
diff --git a/Blog.Core.Api/Controllers/LoginController.cs b/Blog.Core.Api/Controllers/LoginController.cs
index 686c6431..e007cc6d 100644
--- a/Blog.Core.Api/Controllers/LoginController.cs
+++ b/Blog.Core.Api/Controllers/LoginController.cs
@@ -14,6 +14,7 @@
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
+
namespace Blog.Core.Controllers
{
@@ -61,10 +62,11 @@ public LoginController(ISysUserInfoServices sysUserInfoServices, IUserRoleServic
[Route("Token")]
public async Task> GetJwtStr(string name, string pass)
{
+
string jwtStr = string.Empty;
bool suc = false;
//这里就是用户登陆以后,通过数据库去调取数据,分配权限的操作
-
+
var user = await _sysUserInfoServices.GetUserRoleNameStr(name, MD5Helper.MD5Encrypt32(pass));
if (user != null)
{
diff --git a/Blog.Core.Api/appsettings.json b/Blog.Core.Api/appsettings.json
index b39bce54..989b1d0d 100644
--- a/Blog.Core.Api/appsettings.json
+++ b/Blog.Core.Api/appsettings.json
@@ -266,5 +266,15 @@
"ServiceName": "blog.Core.Api", // 服务名
"Port": "8081", // 服务端口号
"RegisterEnabled": true // 是否直接注册nacos
+ },
+ "LogFiedOutPutConfigs": {
+ "tcpAddressHost": "", // 输出elk的tcp连接地址
+ "tcpAddressPort": 0, // 输出elk的tcp端口号
+ "ConfigsInfo": [ // 配置的输出elk节点内容 常用语动态标识
+ {
+ "FiedName": "applicationName",
+ "FiedValue": "Blog.Core.Api"
+ }
+ ]
}
}
diff --git a/Blog.Core.Common/Blog.Core.Common.csproj b/Blog.Core.Common/Blog.Core.Common.csproj
index 8ada40a3..5bc856c1 100644
--- a/Blog.Core.Common/Blog.Core.Common.csproj
+++ b/Blog.Core.Common/Blog.Core.Common.csproj
@@ -32,4 +32,8 @@
+
+
+
+
diff --git a/Blog.Core.Common/Helper/JsonConfigUtils.cs b/Blog.Core.Common/Helper/JsonConfigUtils.cs
index f04fff19..b49024b3 100644
--- a/Blog.Core.Common/Helper/JsonConfigUtils.cs
+++ b/Blog.Core.Common/Helper/JsonConfigUtils.cs
@@ -101,7 +101,6 @@ public ConfigurationManager(IConfigurationRoot _config)
}
catch (Exception ex)
{
- Serilog.Log.Information($"配置文件管理器异常:,{ ex.ToString() }");
value = defaultValue;
}
diff --git a/Blog.Core.Common/LogHelper/Seri/SerilogServer.cs b/Blog.Core.Common/LogHelper/Seri/SerilogServer.cs
index fcdbfd84..2c70532d 100644
--- a/Blog.Core.Common/LogHelper/Seri/SerilogServer.cs
+++ b/Blog.Core.Common/LogHelper/Seri/SerilogServer.cs
@@ -1,7 +1,8 @@
using Blog.Core.Common.Helper;
+using Blog.Core.Serilog.Es;
+using Blog.Core.Serilog.Es.Formatters;
using Serilog;
using Serilog.Events;
-using Serilog.Sinks.Elasticsearch;
using System;
using System.IO;
@@ -18,6 +19,8 @@ public class SerilogServer
public static void WriteLog(string filename, string[] dataParas, bool IsHeader = true, string defaultFolder = "", bool isJudgeJsonFormat = false)
{
Log.Logger = new LoggerConfiguration()
+ // TCPSink 集成Serilog 使用tcp的方式向elk 输出log日志 LogstashJsonFormatter 这个是按照自定义格式化输出内容
+ .WriteTo.TCPSink(new LogstashJsonFormatter())
.MinimumLevel.Debug()
.MinimumLevel.Override("Microsoft", LogEventLevel.Error)
//.WriteTo.File(Path.Combine($"log/Serilog/{filename}/", ".log"), rollingInterval: RollingInterval.Day, outputTemplate: "{Timestamp:yyyy-MM-dd HH:mm:ss.fff} [{Level}] {Message}{NewLine}{Exception}")
@@ -54,7 +57,11 @@ public static void WriteLog(string filename, string[] dataParas, bool IsHeader =
String.Join("\r\n", dataParas) + "\r\n"
);
}
+ // 展示elk支持输出4种日志级别
Log.Information(logContent);
+ Log.Warning(logContent);
+ Log.Error(logContent);
+ Log.Debug(logContent);
}
else
{
diff --git a/Blog.Core.Extensions/NacosConfig/NacosListenConfigurationTask.cs b/Blog.Core.Extensions/NacosConfig/NacosListenConfigurationTask.cs
index 919cc634..42347ea2 100644
--- a/Blog.Core.Extensions/NacosConfig/NacosListenConfigurationTask.cs
+++ b/Blog.Core.Extensions/NacosConfig/NacosListenConfigurationTask.cs
@@ -43,7 +43,7 @@ protected override async Task ExecuteAsync(CancellationToken stoppingToken)
}
catch (Exception ex)
{
- Serilog.Log.Information($"Nacos配置文件获取异常!!! " + ex.ToString());
+
}
}
diff --git a/Blog.Core.Extensions/NacosConfig/NacosListenNamingTask.cs b/Blog.Core.Extensions/NacosConfig/NacosListenNamingTask.cs
index baca9378..60657bb5 100644
--- a/Blog.Core.Extensions/NacosConfig/NacosListenNamingTask.cs
+++ b/Blog.Core.Extensions/NacosConfig/NacosListenNamingTask.cs
@@ -88,9 +88,6 @@ public Task OnEvent(Nacos.V2.IEvent @event)
// 配置有变动后 刷新redis配置 刷新 mq配置
//_redisCachqManager.DisposeRedisConnection();
-
-
- Serilog.Log.Information($"收到服务变更事件!!! {DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")} [{e}]");
}
return Task.CompletedTask;
diff --git a/Blog.Core.Serilog.Es/AppSettingsFileNameConfig.cs b/Blog.Core.Serilog.Es/AppSettingsFileNameConfig.cs
new file mode 100644
index 00000000..c4f2cda0
--- /dev/null
+++ b/Blog.Core.Serilog.Es/AppSettingsFileNameConfig.cs
@@ -0,0 +1,30 @@
+using System;
+
+namespace Blog.Core.Serilog.Es
+{
+ public class AppSettingsFileNameConfig
+ {
+ ///
+ /// 配置文件名称常量
+ ///
+ public static string AppSettingsFileName = $"appsettings{ GetAppSettingsConfigName() }json";
+
+
+ ///
+ /// 根据环境变量定向配置文件名称
+ ///
+ ///
+ private static string GetAppSettingsConfigName()
+ {
+ if (Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT") != null
+ && Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT") != "")
+ {
+ return $".{Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT")}.";
+ }
+ else
+ {
+ return ".";
+ }
+ }
+ }
+}
diff --git a/Blog.Core.Serilog.Es/Blog.Core.Serilog.Es.csproj b/Blog.Core.Serilog.Es/Blog.Core.Serilog.Es.csproj
new file mode 100644
index 00000000..b5c2e0ed
--- /dev/null
+++ b/Blog.Core.Serilog.Es/Blog.Core.Serilog.Es.csproj
@@ -0,0 +1,17 @@
+
+
+
+ net5.0
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Blog.Core.Serilog.Es/Formatters/JsonConfigUtils.cs b/Blog.Core.Serilog.Es/Formatters/JsonConfigUtils.cs
new file mode 100644
index 00000000..e9425040
--- /dev/null
+++ b/Blog.Core.Serilog.Es/Formatters/JsonConfigUtils.cs
@@ -0,0 +1,66 @@
+using Microsoft.Extensions.Configuration;
+using Microsoft.Extensions.Configuration.Json;
+using Microsoft.Extensions.DependencyInjection;
+using Microsoft.Extensions.Options;
+
+namespace Blog.Core.Serilog.Es.Formatters
+{
+ ///
+ /// Json 配置文件通用类
+ ///
+ public static class JsonConfigUtils
+ {
+ #region 变量
+
+ ///
+ /// 锁
+ ///
+ private static object __Lock__ = new object();
+
+ // 读取到的系统配置信息
+ public static IConfiguration Configuration { get; set; }
+
+ #endregion
+
+ ///
+ /// 读取配置文件的信息
+ ///
+ ///
+ /// 要读取json的名称
+ /// 要读取的json节点名称
+ ///
+ public static T GetAppSettings(string AppSettingsFileName, string key) where T : class, new()
+ {
+ lock (__Lock__)
+ {
+ if (Configuration == null)
+ {
+ Configuration = new ConfigurationBuilder()
+ .Add(new JsonConfigurationSource
+ {
+ Path = AppSettingsFileName,
+ Optional = false,
+ ReloadOnChange = true
+ })
+ .Build();
+ }
+ var appconfig = new ServiceCollection()
+ .AddOptions()
+ .Configure(Configuration.GetSection(key))
+ .BuildServiceProvider()
+ .GetService>()
+ .Value;
+
+ return appconfig;
+ }
+ }
+
+
+ public static string GetJson(string jsonPath, string key)
+ {
+ IConfiguration config = new ConfigurationBuilder().AddJsonFile(jsonPath).Build(); //json文件地址
+ string s = config.GetSection(key).Value; //json某个对象
+ return s;
+ }
+ }
+}
diff --git a/Blog.Core.Serilog.Es/Formatters/LogConfigRootDTO.cs b/Blog.Core.Serilog.Es/Formatters/LogConfigRootDTO.cs
new file mode 100644
index 00000000..36a9916c
--- /dev/null
+++ b/Blog.Core.Serilog.Es/Formatters/LogConfigRootDTO.cs
@@ -0,0 +1,26 @@
+using System.Collections.Generic;
+
+namespace Blog.Core.Serilog.Es.Formatters
+{
+
+ public class LogConfigRootDTO
+ {
+ ///
+ /// tcp日志的host地址
+ ///
+ public string tcpAddressHost { set; get; }
+
+ ///
+ /// tcp日志的port地址
+ ///
+ public int tcpAddressPort { set; get; }
+
+ public List ConfigsInfo { get; set; }
+ }
+
+ public class Configsinfo
+ {
+ public string FiedName { get; set; }
+ public string FiedValue { get; set; }
+ }
+}
diff --git a/Blog.Core.Serilog.Es/Formatters/LogstashJsonFormatter.cs b/Blog.Core.Serilog.Es/Formatters/LogstashJsonFormatter.cs
new file mode 100644
index 00000000..f123c177
--- /dev/null
+++ b/Blog.Core.Serilog.Es/Formatters/LogstashJsonFormatter.cs
@@ -0,0 +1,152 @@
+// Adapted from RawJsonFormatter in Serilog.Sinks.Seq Copyright 2016 Serilog Contributors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using Serilog.Events;
+using Serilog.Formatting;
+using Serilog.Formatting.Json;
+using Blog.Core.Serilog.Es.HttpInfo;
+
+namespace Blog.Core.Serilog.Es.Formatters
+{
+ public class LogstashJsonFormatter : ITextFormatter
+ {
+ private static readonly JsonValueFormatter ValueFormatter = new JsonValueFormatter();
+
+ public void Format(LogEvent logEvent, TextWriter output)
+ {
+ FormatContent(logEvent, output);
+
+ output.WriteLine();
+ }
+
+
+ ///
+ /// 格式化 最终输出到elk的核心部分
+ ///
+ ///
+ ///
+ private static void FormatContent(LogEvent logEvent, TextWriter output)
+ {
+ if (logEvent == null) throw new ArgumentNullException(nameof(logEvent));
+ if (output == null) throw new ArgumentNullException(nameof(output));
+
+ output.Write('{');
+
+ // 读取相关配置
+ var logConfigRootDTOInfo = JsonConfigUtils.GetAppSettings(AppSettingsFileNameConfig.AppSettingsFileName, "LogFiedOutPutConfigs");
+ if (logConfigRootDTOInfo == null)
+ {
+ return;
+ }
+
+ // 写入所有的项目配置项的字段 在appsetting中配置的 输出elk节点的数据字段
+ foreach (var item in logConfigRootDTOInfo.ConfigsInfo)
+ {
+ switch (item.FiedName)
+ {
+ //case "orgid":
+ // WritePropertyAndValue(output, "method", HttpContextProvider.GetCurrent().Request.Method);
+ // output.Write(",");
+ // break;
+ default:
+ WritePropertyAndValue(output, item.FiedName, item.FiedValue);
+ output.Write(",");
+ break;
+ }
+ }
+ // 写入http对应的信息数据
+ if (HttpContextProvider.GetCurrent()!=null && HttpContextProvider.GetCurrent().Request!=null)
+ {
+ if (!string.IsNullOrEmpty(HttpContextProvider.GetCurrent().Request.Method))
+ {
+ WritePropertyAndValue(output, "method", HttpContextProvider.GetCurrent().Request.Method);
+ output.Write(",");
+ }
+ // 输出请求页面url
+ if (!string.IsNullOrEmpty(HttpContextProvider.GetCurrent().Request.Path))
+ {
+ WritePropertyAndValue(output, "requestUrl", HttpContextProvider.GetCurrent().Request.Path.ToString());
+ output.Write(",");
+ }
+ // 输出携带token
+ if (HttpContextProvider.GetCurrent().Request.Headers["Authorization"].FirstOrDefault() != null)
+ {
+ WritePropertyAndValue(output, "Authorization", HttpContextProvider.GetCurrent().Request.Headers["Authorization"].FirstOrDefault());
+ output.Write(",");
+ }
+ // 输出请求参数
+ if (!string.IsNullOrEmpty(HttpContextProvider.GetCurrent().Request.Method))
+ {
+ string contentFromBody = ParamsHelper.GetParams(HttpContextProvider.GetCurrent());
+ WritePropertyAndValue(output, "requestParam", contentFromBody);
+ output.Write(",");
+ }
+ // 输出请求方法类型
+ if (!string.IsNullOrEmpty(HttpContextProvider.GetCurrent().Request.Method))
+ {
+ WritePropertyAndValue(output, "method", HttpContextProvider.GetCurrent().Request.Method);
+ output.Write(",");
+ }
+ }
+ // 输出请求时间戳
+ WritePropertyAndValue(output, "timestamp", logEvent.Timestamp.ToString("o"));
+ output.Write(",");
+
+ // 输出日志级别
+ WritePropertyAndValue(output, "level", logEvent.Level.ToString());
+ output.Write(",");
+
+ // 输出log内容
+ WritePropertyAndValue(output, "executeResult", logEvent.MessageTemplate.Render(logEvent.Properties));
+
+ if (logEvent.Exception != null)
+ {
+ output.Write(",");
+ WritePropertyAndValue(output, "exception", logEvent.Exception.ToString());
+ }
+
+ WriteProperties(logEvent.Properties, output);
+
+ output.Write('}');
+ }
+
+ private static void WritePropertyAndValue(TextWriter output, string propertyKey, string propertyValue)
+ {
+ JsonValueFormatter.WriteQuotedJsonString(propertyKey, output);
+ output.Write(":");
+ JsonValueFormatter.WriteQuotedJsonString(propertyValue, output);
+ }
+
+ private static void WriteProperties(IReadOnlyDictionary properties, TextWriter output)
+ {
+ if (properties.Any()) output.Write(",");
+
+ var precedingDelimiter = "";
+ foreach (var property in properties)
+ {
+ output.Write(precedingDelimiter);
+ precedingDelimiter = ",";
+
+ var camelCasePropertyKey = property.Key[0].ToString().ToLower() + property.Key.Substring(1);
+ JsonValueFormatter.WriteQuotedJsonString(camelCasePropertyKey, output);
+ output.Write(':');
+ ValueFormatter.Format(property.Value, output);
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/Blog.Core.Serilog.Es/HttpInfo/HttpContextProvider.cs b/Blog.Core.Serilog.Es/HttpInfo/HttpContextProvider.cs
new file mode 100644
index 00000000..612f20b5
--- /dev/null
+++ b/Blog.Core.Serilog.Es/HttpInfo/HttpContextProvider.cs
@@ -0,0 +1,20 @@
+using Microsoft.AspNetCore.Http;
+
+namespace Blog.Core.Serilog.Es.HttpInfo
+{
+ public static class HttpContextProvider
+ {
+ private static IHttpContextAccessor _accessor;
+
+ public static HttpContext GetCurrent()
+ {
+ var context = _accessor?.HttpContext;
+ return context;
+ }
+ public static void ConfigureAccessor(IHttpContextAccessor accessor)
+ {
+ _accessor = accessor;
+ }
+ }
+
+}
diff --git a/Blog.Core.Serilog.Es/HttpInfo/ParamsHelper.cs b/Blog.Core.Serilog.Es/HttpInfo/ParamsHelper.cs
new file mode 100644
index 00000000..3b39c0bf
--- /dev/null
+++ b/Blog.Core.Serilog.Es/HttpInfo/ParamsHelper.cs
@@ -0,0 +1,82 @@
+using Microsoft.AspNetCore.Http;
+using System;
+using System.Collections.Generic;
+using System.Collections.Specialized;
+using System.IO;
+using System.Text;
+using System.Web;
+
+namespace Blog.Core.Serilog.Es.HttpInfo
+{
+ ///
+ /// 获取参数帮助类
+ ///
+ public class ParamsHelper
+ {
+ ///
+ /// 获取参数值
+ ///
+ ///
+ ///
+ public static string GetParams(HttpContext context)
+ {
+ try
+ {
+ NameValueCollection form = HttpUtility.ParseQueryString(context.Request.QueryString.ToString());
+ HttpRequest request = context.Request;
+
+ string data = string.Empty;
+ switch (request.Method)
+ {
+ case "POST":
+
+ request.Body.Position = 0;
+ using (var ms = new MemoryStream())
+ {
+ request.Body.CopyTo(ms);
+ var b = ms.ToArray();
+ data = Encoding.UTF8.GetString(b); //把body赋值给bodyStr
+
+ }
+ break;
+ case "GET":
+ //第一步:取出所有get参数
+ IDictionary parameters = new Dictionary();
+ for (int f = 0; f < form.Count; f++)
+ {
+ string key = form.Keys[f];
+ parameters.Add(key, form[key]);
+ }
+
+ // 第二步:把字典按Key的字母顺序排序
+ IDictionary sortedParams = new SortedDictionary(parameters);
+ IEnumerator> dem = sortedParams.GetEnumerator();
+
+ // 第三步:把所有参数名和参数值串在一起
+ StringBuilder query = new StringBuilder();
+ while (dem.MoveNext())
+ {
+ string key = dem.Current.Key;
+ string value = dem.Current.Value;
+ if (!string.IsNullOrEmpty(key))
+ {
+ query.Append(key).Append("=").Append(value).Append("&");
+ }
+ }
+ data = query.ToString().TrimEnd('&');
+ break;
+ default:
+ data = string.Empty;
+
+ break;
+ }
+ return data;
+ }
+ catch(Exception ex)
+ {
+ return string.Empty;
+ }
+ }
+
+ }
+}
diff --git a/Blog.Core.Serilog.Es/NetworkLoggerConfigurationExtensions.cs b/Blog.Core.Serilog.Es/NetworkLoggerConfigurationExtensions.cs
new file mode 100644
index 00000000..d77f80f2
--- /dev/null
+++ b/Blog.Core.Serilog.Es/NetworkLoggerConfigurationExtensions.cs
@@ -0,0 +1,102 @@
+using System;
+using System.Linq;
+using System.Net;
+using Serilog;
+using Serilog.Configuration;
+using Serilog.Debugging;
+using Serilog.Events;
+using Serilog.Formatting;
+using Blog.Core.Serilog.Es.Formatters;
+using Blog.Core.Serilog.Es.Sinks.TCP;
+
+namespace Blog.Core.Serilog.Es
+{
+ ///
+ /// Extends Serilog configuration to write events to the network.
+ ///
+ public static class NetworkLoggerConfigurationExtensions
+ {
+ private static string TcpAddressHost = "";
+ private static int TcpAddressProt = 0;
+ ///
+ /// 获得tcpAddress
+ ///
+ private static void GetTcpAddress()
+ {
+ // 读取相关配置
+ var logConfigRootDTOInfo = JsonConfigUtils.GetAppSettings(AppSettingsFileNameConfig.AppSettingsFileName, "LogFiedOutPutConfigs");
+ if (logConfigRootDTOInfo == null)
+ {
+ return;
+ }
+ TcpAddressHost = logConfigRootDTOInfo.tcpAddressHost;
+ TcpAddressProt = logConfigRootDTOInfo.tcpAddressPort;
+ }
+
+ public static LoggerConfiguration TCPSink(
+ this LoggerSinkConfiguration loggerConfiguration,
+ ITextFormatter textFormatter = null,
+ LogEventLevel restrictedToMinimumLevel = LevelAlias.Minimum)
+ {
+ GetTcpAddress();
+ if (!string.IsNullOrEmpty(TcpAddressHost))
+ {
+ var sink = new TCPSink(BuildUri($"tcp://{TcpAddressHost}:{TcpAddressProt}"), textFormatter ?? new LogstashJsonFormatter());
+ return loggerConfiguration.Sink(sink, restrictedToMinimumLevel);
+ }
+ else {
+ return new LoggerConfiguration();
+ }
+ }
+
+ private static IPAddress ResolveAddress(string uri)
+ {
+ // Check if it is IP address
+ IPAddress address;
+
+ if (IPAddress.TryParse(uri, out address))
+ return address;
+
+ address = ResolveIP(uri);
+ if (address != null)
+ return address;
+
+ SelfLog.WriteLine("Unable to determine the destination IP-Address");
+ return IPAddress.Loopback;
+ }
+
+ private static IPAddress ResolveIP(string uri)
+ {
+ try
+ {
+ var ipHostEntry = Dns.GetHostEntryAsync(uri).Result;
+ if (!ipHostEntry.AddressList.Any())
+ return null;
+ return ipHostEntry.AddressList.First();
+ }
+ catch (Exception)
+ {
+ SelfLog.WriteLine("Could not resolve " + uri);
+ return null;
+ }
+ }
+
+ private static Uri BuildUri(string s)
+ {
+ Uri uri;
+ try
+ {
+ uri = new Uri(s);
+ }
+ catch (UriFormatException ex)
+ {
+ throw new ArgumentNullException("Uri should be in the format tcp://server:port", ex);
+ }
+ if (uri.Port == 0)
+ throw new UriFormatException("Uri port cannot be 0");
+ if (!(uri.Scheme.ToLower() == "tcp" || uri.Scheme.ToLower() == "tls"))
+ throw new UriFormatException("Uri scheme must be tcp or tls");
+ return uri;
+ }
+ }
+}
\ No newline at end of file
diff --git a/Blog.Core.Serilog.Es/Sinks/TCP/TCPSink.cs b/Blog.Core.Serilog.Es/Sinks/TCP/TCPSink.cs
new file mode 100644
index 00000000..fc5a43c9
--- /dev/null
+++ b/Blog.Core.Serilog.Es/Sinks/TCP/TCPSink.cs
@@ -0,0 +1,44 @@
+using System;
+using System.IO;
+using System.Net;
+using System.Text;
+using Serilog.Core;
+using Serilog.Events;
+using Serilog.Formatting;
+
+namespace Blog.Core.Serilog.Es.Sinks.TCP
+{
+ public class TCPSink : ILogEventSink, IDisposable
+ {
+ private readonly ITextFormatter _formatter;
+ private readonly TcpSocketWriter _socketWriter;
+
+ public TCPSink(IPAddress ipAddress, int port, ITextFormatter formatter)
+ {
+ _socketWriter = new TcpSocketWriter(new Uri($"tcp://{ipAddress}:{port}"));
+ _formatter = formatter;
+ }
+
+ public TCPSink(Uri uri, ITextFormatter formatter)
+ {
+ _socketWriter = new TcpSocketWriter(uri);
+ _formatter = formatter;
+ }
+
+ public void Emit(LogEvent logEvent)
+ {
+ var sb = new StringBuilder();
+
+ using (var sw = new StringWriter(sb))
+ _formatter.Format(logEvent, sw);
+
+ sb.Replace("RenderedMessage", "message");
+ _socketWriter.Enqueue(sb.ToString());
+ }
+
+ public void Dispose()
+ {
+ _socketWriter.Dispose();
+ }
+ }
+}
\ No newline at end of file
diff --git a/Blog.Core.Serilog.Es/Sinks/TCP/TCPSocketWriter.cs b/Blog.Core.Serilog.Es/Sinks/TCP/TCPSocketWriter.cs
new file mode 100644
index 00000000..f1f592c9
--- /dev/null
+++ b/Blog.Core.Serilog.Es/Sinks/TCP/TCPSocketWriter.cs
@@ -0,0 +1,325 @@
+/*
+ * Copyright 2014 Splunk, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"): you may
+ * not use this file except in compliance with the License. You may obtain
+ * a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ */
+
+using Serilog;
+using System;
+using System.Collections.Concurrent;
+using System.IO;
+using System.Net;
+using System.Net.Security;
+using System.Net.Sockets;
+using System.Security.Authentication;
+using System.Text;
+using System.Text.RegularExpressions;
+using System.Threading;
+using System.Threading.Tasks;
+
+namespace Blog.Core.Serilog.Es.Sinks.TCP
+{
+ ///
+ /// TcpSocketWriter encapsulates queueing strings to be written to a TCP _socket
+ /// and handling reconnections (according to a TcpConnectionPolicy object passed
+ /// to it) when a TCP session drops.
+ ///
+ ///
+ /// TcpSocketWriter maintains a fixed sized queue of strings to be sent via
+ /// the TCP _port and, while the _socket is open, sends them as quickly as possible.
+ ///
+ /// If the TCP session drops, TcpSocketWriter will stop pulling strings off the
+ /// queue until it can reestablish a connection. Any SocketErrors emitted during this
+ /// process will be passed as arguments to invocations of LoggingFailureHandler.
+ /// If the TcpConnectionPolicy.Connect method throws an exception (in particular,
+ /// TcpReconnectFailure to indicate that the policy has reached a point where it
+ /// will no longer try to establish a connection) then the LoggingFailureHandler
+ /// event is invoked, and no further attempt to log anything will be made.
+ ///
+ public class TcpSocketWriter : IDisposable
+ {
+ private readonly FixedSizeQueue _eventQueue;
+ private readonly ExponentialBackoffTcpReconnectionPolicy _reconnectPolicy = new ExponentialBackoffTcpReconnectionPolicy();
+ private readonly CancellationTokenSource _tokenSource; // Must be private or Dispose will not function properly.
+ private readonly TaskCompletionSource _disposed = new TaskCompletionSource();
+
+ private Stream _stream;
+
+ ///
+ /// Event that is invoked when reconnecting after a TCP session is dropped fails.
+ ///
+ public event Action LoggingFailureHandler = ex =>
+ {
+ UnexpectedErrorLogger(
+ ex,
+ (x, socketError) =>
+ {
+ if (socketError == null)
+ {
+ //Log.Error(x, "failure inside TCP socket: {message}", x.Message);
+ }
+ else
+ {
+ //Log.Error(
+ // x,
+ // "failure inside TCP socket: {message} - socket error found {socketErrorCode}",
+ // x.Message,
+ // socketError);
+ }
+
+ });
+ };
+
+ public static void UnexpectedErrorLogger(Exception ex, Action log)
+ {
+ SocketError? socketErrorCode = null;
+ var current = ex;
+ do
+ {
+ if (current is SocketException)
+ {
+ socketErrorCode = ((SocketException) current).SocketErrorCode;
+ }
+
+ current = current.InnerException;
+ } while (socketErrorCode == null && current != null);
+
+ log(ex, socketErrorCode);
+ }
+
+ ///
+ /// Construct a TCP _socket writer that writes to the given endPoint and _port.
+ ///
+ /// Uri to open a TCP socket to.
+ /// The maximum number of log entries to queue before starting to drop entries.
+ public TcpSocketWriter(Uri uri, int maxQueueSize = 5000)
+ {
+ _eventQueue = new FixedSizeQueue(maxQueueSize);
+ _tokenSource = new CancellationTokenSource();
+
+ Func> tryOpenSocket = async h =>
+ {
+ try
+ {
+ TcpClient client = new TcpClient();
+ await client.ConnectAsync(uri.Host, uri.Port);
+ Stream stream = client.GetStream();
+ if (uri.Scheme.ToLower() != "tls")
+ return stream;
+
+ var sslStream = new SslStream(client.GetStream(), false, null, null);
+ await sslStream.AuthenticateAsClientAsync(uri.Host);
+ return sslStream;
+ }
+ catch (Exception e)
+ {
+ LoggingFailureHandler(e);
+ throw;
+ }
+ };
+
+ var threadReady = new TaskCompletionSource();
+
+ Task queueListener = Task.Factory.StartNew(async () =>
+ {
+ try
+ {
+ bool sslEnabled = uri.Scheme.ToLower() == "tls";
+ _stream = await _reconnectPolicy.ConnectAsync(tryOpenSocket, uri, _tokenSource.Token);
+ threadReady.SetResult(true); // Signal the calling thread that we are ready.
+
+ string entry = null;
+ while (_stream != null) // null indicates that the thread has been cancelled and cleaned up.
+ {
+ if (_tokenSource.Token.IsCancellationRequested)
+ {
+ _eventQueue.CompleteAdding();
+ // Post-condition: no further items will be added to the queue, so there will be a finite number of items to handle.
+ while (_eventQueue.Count > 0)
+ {
+ entry = _eventQueue.Dequeue();
+ try
+ {
+ byte[] messsage = Encoding.UTF8.GetBytes(entry);
+ await _stream.WriteAsync(messsage, 0, messsage.Length);
+ await _stream.FlushAsync();
+ }
+ catch (SocketException ex)
+ {
+ LoggingFailureHandler(ex);
+ }
+ }
+ break;
+ }
+ if (entry == null)
+ {
+ entry = _eventQueue.Dequeue(_tokenSource.Token);
+ }
+ else
+ {
+ try
+ {
+ byte[] messsage = Encoding.UTF8.GetBytes(entry);
+ await _stream.WriteAsync(messsage, 0, messsage.Length);
+ await _stream.FlushAsync();
+ // No exception, it was sent
+ entry = null;
+ }
+ catch (IOException ex)
+ {
+ LoggingFailureHandler(ex);
+ _stream = await _reconnectPolicy.ConnectAsync(tryOpenSocket, uri, _tokenSource.Token);
+ }
+ catch (SocketException ex)
+ {
+ LoggingFailureHandler(ex);
+ _stream = await _reconnectPolicy.ConnectAsync(tryOpenSocket, uri, _tokenSource.Token);
+ }
+ }
+ }
+ }
+ catch (Exception e)
+ {
+ LoggingFailureHandler(e);
+ }
+ finally
+ {
+ if (_stream != null)
+ {
+ _stream.Dispose();
+ }
+
+ _disposed.SetResult(true);
+ }
+ }, CancellationToken.None, TaskCreationOptions.LongRunning, TaskScheduler.Default);
+ threadReady.Task.Wait(TimeSpan.FromSeconds(5));
+ }
+
+ public void Dispose()
+ {
+ // The following operations are idempotent. Issue a cancellation to tell the
+ // writer thread to stop the queue from accepting entries and write what it has
+ // before cleaning up, then wait until that cleanup is finished.
+ _tokenSource.Cancel();
+ Task.Run(async () => await _disposed.Task).Wait();
+ }
+
+ ///
+ /// Push a string onto the queue to be written.
+ ///
+ /// The string to be written to the TCP _socket.
+ public void Enqueue(string entry)
+ {
+ _eventQueue.Enqueue(entry);
+ }
+ }
+
+ ///
+ /// TcpConnectionPolicy implementation that tries to reconnect after
+ /// increasingly long intervals.
+ ///
+ ///
+ /// The intervals double every time, starting from 0s, 1s, 2s, 4s, ...
+ /// until 10 minutes between connections, when it plateaus and does
+ /// not increase the interval length any further.
+ ///
+ public class ExponentialBackoffTcpReconnectionPolicy
+ {
+ private readonly int ceiling = 10 * 60; // 10 minutes in seconds
+
+ public async Task ConnectAsync(Func> connect, Uri host, CancellationToken cancellationToken)
+ {
+ int delay = 1; // in seconds
+ while (!cancellationToken.IsCancellationRequested)
+ {
+ try
+ {
+ //Log.Debug("Attempting to connect to TCP endpoint {host} after delay of {delay} seconds", host, delay);
+ return await connect(host);
+ }
+ catch (SocketException) { }
+
+ // If this is cancelled via the cancellationToken instead of
+ // completing its delay, the next while-loop test will fail,
+ // the loop will terminate, and the method will return null
+ // with no additional connection attempts.
+ await Task.Delay(delay * 1000, cancellationToken);
+ // The nth delay is min(10 minutes, 2^n - 1 seconds).
+ delay = Math.Min((delay + 1) * 2 - 1, ceiling);
+ }
+
+ // cancellationToken has been cancelled.
+ return null;
+ }
+ }
+
+ ///
+ /// A queue with a maximum size. When the queue is at its maximum size
+ /// and a new item is queued, the oldest item in the queue is dropped.
+ ///
+ ///
+ internal class FixedSizeQueue
+ {
+ private int Size { get; }
+ private readonly IProgress _progress = new Progress();
+ private bool IsCompleted { get; set; }
+
+ private readonly BlockingCollection _collection = new BlockingCollection();
+
+ public FixedSizeQueue(int size)
+ {
+ Size = size;
+ IsCompleted = false;
+ }
+
+ public void Enqueue(T obj)
+ {
+ lock (this)
+ {
+ if (IsCompleted)
+ {
+ throw new InvalidOperationException("Tried to add an item to a completed queue.");
+ }
+
+ _collection.Add(obj);
+
+ while (_collection.Count > Size)
+ {
+ _collection.Take();
+ }
+ _progress.Report(true);
+ }
+ }
+
+ public void CompleteAdding()
+ {
+ lock (this)
+ {
+ IsCompleted = true;
+ }
+ }
+
+ public T Dequeue(CancellationToken cancellationToken)
+ {
+ return _collection.Take(cancellationToken);
+ }
+
+ public T Dequeue()
+ {
+ return _collection.Take();
+ }
+
+
+ public decimal Count => _collection.Count;
+ }
+}
\ No newline at end of file
diff --git a/Blog.Core.Serilog.Es/Sinks/UDP/UDPSink.cs b/Blog.Core.Serilog.Es/Sinks/UDP/UDPSink.cs
new file mode 100644
index 00000000..f07c24e1
--- /dev/null
+++ b/Blog.Core.Serilog.Es/Sinks/UDP/UDPSink.cs
@@ -0,0 +1,42 @@
+using System;
+using System.IO;
+using System.Net;
+using System.Net.Sockets;
+using System.Text;
+using Serilog.Core;
+using Serilog.Events;
+using Serilog.Formatting;
+
+
+namespace Serilog.Sinks.Network.Sinks.UDP
+{
+ public class UDPSink : ILogEventSink, IDisposable
+ {
+ private Socket _socket = new Socket(SocketType.Dgram, ProtocolType.Udp);
+ private readonly ITextFormatter _formatter;
+
+ public UDPSink(IPAddress ipAddress, int port, ITextFormatter formatter)
+ {
+ _socket.Connect(ipAddress, port);
+ _formatter = formatter;
+ }
+
+ public void Emit(LogEvent logEvent)
+ {
+ var sb = new StringBuilder();
+
+ using (var sw = new StringWriter(sb))
+ _formatter.Format(logEvent, sw);
+
+ sb.Replace("RenderedMessage", "message");
+
+ _socket.Send(Encoding.UTF8.GetBytes(sb.ToString()));
+ }
+
+ public void Dispose()
+ {
+ _socket?.Dispose();
+ _socket = null;
+ }
+ }
+}
diff --git a/Blog.Core.sln b/Blog.Core.sln
index 2446fd7a..1e86d304 100644
--- a/Blog.Core.sln
+++ b/Blog.Core.sln
@@ -53,6 +53,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Blog.Core.ConsoleApp", "Blo
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Blog.Core.Gateway", "Blog.Core.Gateway\Blog.Core.Gateway.csproj", "{A11C0DF2-1E13-4EED-BA49-44A57136B189}"
EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Blog.Core.Serilog.Es", "Blog.Core.Serilog.Es\Blog.Core.Serilog.Es.csproj", "{52AFAB53-D1CA-4014-8B63-3550FDCDA6E1}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -111,6 +113,10 @@ Global
{A11C0DF2-1E13-4EED-BA49-44A57136B189}.Debug|Any CPU.Build.0 = Debug|Any CPU
{A11C0DF2-1E13-4EED-BA49-44A57136B189}.Release|Any CPU.ActiveCfg = Release|Any CPU
{A11C0DF2-1E13-4EED-BA49-44A57136B189}.Release|Any CPU.Build.0 = Release|Any CPU
+ {52AFAB53-D1CA-4014-8B63-3550FDCDA6E1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {52AFAB53-D1CA-4014-8B63-3550FDCDA6E1}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {52AFAB53-D1CA-4014-8B63-3550FDCDA6E1}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {52AFAB53-D1CA-4014-8B63-3550FDCDA6E1}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
From fe8a7d1efa28060387910d263132b62185dee332 Mon Sep 17 00:00:00 2001
From: ansonzhang <3143422472@qq.com>
Date: Wed, 4 Aug 2021 18:06:04 +0800
Subject: [PATCH 057/456] Update README.md
---
README.md | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/README.md b/README.md
index af5ee5e4..1e9ac25d 100644
--- a/README.md
+++ b/README.md
@@ -73,14 +73,16 @@ Blog.Core 开箱即用的企业级前后端分离【 .NET Core5.0 Api + Vue 2.x
- [x] 新增 Redis 消息队列 ✨;
- [x] 新增 RabbitMQ 消息队列 ✨;
- [x] 新增 EventBus 事件总线 ✨;
-- [x] 调试中 - 统一聚合支付;
+- [x] 新增 - 统一聚合支付;
+- [x] 新增 - Nacos注册中心配置;
+- [x] 新增 - ES 搜索配置;
- [ ] 计划 - 数据部门权限;
-- [ ] 计划 - ES 搜索;
微服务模块:
- [x] 可配合 Docker 实现容器化;
- [x] 可配合 Jenkins 实现CI / CD;
- [x] 可配合 Consul 实现服务发现;
+- [x] 可配合 Nacos 实现服务发现;
- [x] 可配合 Ocelot 实现网关处理;
- [x] 可配合 Nginx 实现负载均衡;
- [x] 可配合 Ids4 实现认证中心;
From 0c5714a8680fed5db972fcf0a440b72577257e3e Mon Sep 17 00:00:00 2001
From: anjoy8 <3143422472@qq.com>
Date: Fri, 6 Aug 2021 18:05:56 +0800
Subject: [PATCH 058/456] :dart: fix: log monitor
---
.../Controllers/MonitorController.cs | 38 +++++++++++++++--
Blog.Core.Common/LogHelper/LogLock.cs | 41 ++++++++++++++++---
2 files changed, 70 insertions(+), 9 deletions(-)
diff --git a/Blog.Core.Api/Controllers/MonitorController.cs b/Blog.Core.Api/Controllers/MonitorController.cs
index b06af190..28ff3265 100644
--- a/Blog.Core.Api/Controllers/MonitorController.cs
+++ b/Blog.Core.Api/Controllers/MonitorController.cs
@@ -105,13 +105,43 @@ public MessageModel GetAccessApiByHour()
};
}
+ private List GetAccessLogsToday(IWebHostEnvironment environment)
+ {
+ List userAccessModels = new();
+ var accessLogs = LogLock.ReadLog(
+ Path.Combine(environment.ContentRootPath, "Log"), "RecordAccessLogs_", Encoding.UTF8, ReadType.PrefixLatest
+ ).ObjToString();
+ try
+ {
+ return JsonConvert.DeserializeObject>("[" + accessLogs + "]");
+ }
+ catch (Exception)
+ {
+ var accLogArr = accessLogs.Split("\n");
+ foreach (var item in accLogArr)
+ {
+ if (item.ObjToString() != "")
+ {
+ try
+ {
+ var accItem = JsonConvert.DeserializeObject(item.TrimEnd(','));
+ userAccessModels.Add(accItem);
+ }
+ catch (Exception)
+ {
+ }
+ }
+ }
+
+ }
+
+ return userAccessModels;
+ }
+
[HttpGet]
public MessageModel GetActiveUsers([FromServices] IWebHostEnvironment environment)
{
- var accessLogsToday = JsonConvert.DeserializeObject>("[" + LogLock.ReadLog(
- Path.Combine(environment.ContentRootPath, "Log"), "RecordAccessLogs_", Encoding.UTF8, ReadType.PrefixLatest
- ) + "]")
- .Where(d => d.BeginTime.ObjToDate() >= DateTime.Today);
+ var accessLogsToday = GetAccessLogsToday(environment).Where(d => d.BeginTime.ObjToDate() >= DateTime.Today);
var Logs = accessLogsToday.OrderByDescending(d => d.BeginTime).Take(50).ToList();
diff --git a/Blog.Core.Common/LogHelper/LogLock.cs b/Blog.Core.Common/LogHelper/LogLock.cs
index adeb0e11..dc2d158a 100644
--- a/Blog.Core.Common/LogHelper/LogLock.cs
+++ b/Blog.Core.Common/LogHelper/LogLock.cs
@@ -150,6 +150,37 @@ public static string ReadLog(string folderPath, string fileName, Encoding encode
return s;
}
+ private static List GetRequestInfo(ReadType readType)
+ {
+ List requestInfos = new();
+ var accessLogs = ReadLog(Path.Combine(_contentRoot, "Log"), "RequestIpInfoLog_", Encoding.UTF8, readType).ObjToString();
+ try
+ {
+ return JsonConvert.DeserializeObject>("[" + accessLogs + "]");
+ }
+ catch (Exception)
+ {
+ var accLogArr = accessLogs.Split("\r\n");
+ foreach (var item in accLogArr)
+ {
+ if (item.ObjToString() != "")
+ {
+ try
+ {
+ var accItem = JsonConvert.DeserializeObject(item.TrimEnd(','));
+ requestInfos.Add(accItem);
+ }
+ catch (Exception)
+ {
+ }
+ }
+ }
+
+ }
+
+ return requestInfos;
+ }
+
public static List GetLogData()
{
@@ -232,7 +263,7 @@ public static List GetLogData()
try
{
- var Logs = JsonConvert.DeserializeObject>("[" + ReadLog(Path.Combine(_contentRoot, "Log"), "RequestIpInfoLog_", Encoding.UTF8, ReadType.PrefixLatest) + "]");
+ var Logs = GetRequestInfo(ReadType.PrefixLatest);
Logs = Logs.Where(d => d.Datetime.ObjToDate() >= DateTime.Today).ToList();
@@ -276,7 +307,7 @@ public static RequestApiWeekView RequestApiinfoByWeek()
try
{
- Logs = JsonConvert.DeserializeObject>("[" + ReadLog(Path.Combine(_contentRoot, "Log"), "RequestIpInfoLog_", Encoding.UTF8, ReadType.Prefix) + "]");
+ Logs = GetRequestInfo(ReadType.Prefix);
apiWeeks = (from n in Logs
group n by new { n.Week, n.Url } into g
@@ -347,8 +378,8 @@ public static AccessApiDateView AccessApiByDate()
List apiDates = new List();
try
{
- Logs = JsonConvert.DeserializeObject>("[" + ReadLog(Path.Combine(_contentRoot, "Log"), "RequestIpInfoLog_", Encoding.UTF8, ReadType.Prefix) + "]");
-
+ Logs = GetRequestInfo(ReadType.Prefix);
+
apiDates = (from n in Logs
group n by new { n.Date } into g
select new ApiDate
@@ -377,7 +408,7 @@ public static AccessApiDateView AccessApiByHour()
List apiDates = new List();
try
{
- Logs = JsonConvert.DeserializeObject>("[" + ReadLog(Path.Combine(_contentRoot, "Log"), "RequestIpInfoLog_", Encoding.UTF8, ReadType.Prefix) + "]");
+ Logs = GetRequestInfo(ReadType.Prefix);
apiDates = (from n in Logs
where n.Datetime.ObjToDate() >= DateTime.Today
From 1d9764459be5719667530bdaca31335540d4b483 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E5=AE=81=E9=AA=91?= <1075858260@qq.com>
Date: Mon, 9 Aug 2021 11:55:24 +0800
Subject: [PATCH 059/456] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E9=94=99=E8=AF=AF?=
=?UTF-8?q?=E6=B3=A8=E9=87=8A?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
Blog.Core.Extensions/ServiceExtensions/NacosSetup.cs | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/Blog.Core.Extensions/ServiceExtensions/NacosSetup.cs b/Blog.Core.Extensions/ServiceExtensions/NacosSetup.cs
index fab03514..d314f6ea 100644
--- a/Blog.Core.Extensions/ServiceExtensions/NacosSetup.cs
+++ b/Blog.Core.Extensions/ServiceExtensions/NacosSetup.cs
@@ -9,7 +9,7 @@
namespace Blog.Core.Extensions
{
///
- /// Memory缓存 启动服务
+ /// Nacos
///
public static class NacosSetup
{
From 2b024137adb063f5adc4d71b732d2b03f7c1c5d9 Mon Sep 17 00:00:00 2001
From: anjoy8 <3143422472@qq.com>
Date: Mon, 9 Aug 2021 15:52:17 +0800
Subject: [PATCH 060/456] Update BlogController.cs
---
Blog.Core.Api/Controllers/BlogController.cs | 20 ++++++++++++++------
1 file changed, 14 insertions(+), 6 deletions(-)
diff --git a/Blog.Core.Api/Controllers/BlogController.cs b/Blog.Core.Api/Controllers/BlogController.cs
index 577e80bb..24860971 100644
--- a/Blog.Core.Api/Controllers/BlogController.cs
+++ b/Blog.Core.Api/Controllers/BlogController.cs
@@ -176,12 +176,20 @@ public MessageModel V2_Blogtest()
[Authorize]
public async Task> Post([FromBody] BlogArticle blogArticle)
{
- blogArticle.bCreateTime = DateTime.Now;
- blogArticle.bUpdateTime = DateTime.Now;
- blogArticle.IsDeleted = false;
- blogArticle.bcategory = "技术博文";
- var id = (await _blogArticleServices.Add(blogArticle));
- return id > 0 ? Success(id.ObjToString()) : Failed("添加失败");
+ if (blogArticle.btitle.Length > 5 && blogArticle.bcontent.Length > 50)
+ {
+
+ blogArticle.bCreateTime = DateTime.Now;
+ blogArticle.bUpdateTime = DateTime.Now;
+ blogArticle.IsDeleted = false;
+ blogArticle.bcategory = "技术博文";
+ var id = (await _blogArticleServices.Add(blogArticle));
+ return id > 0 ? Success(id.ObjToString()) : Failed("添加失败");
+ }
+ else
+ {
+ return Failed("文章标题不能少于5个字符,内容不能少于50个字符!");
+ }
}
From 9e7960ee569188cd412445e73728a3d45eeb4456 Mon Sep 17 00:00:00 2001
From: anjoy8 <3143422472@qq.com>
Date: Tue, 10 Aug 2021 14:58:17 +0800
Subject: [PATCH 061/456] Update IPLogMildd.cs
---
.../Middlewares/IPLogMildd.cs | 34 +++++++++----------
1 file changed, 17 insertions(+), 17 deletions(-)
diff --git a/Blog.Core.Extensions/Middlewares/IPLogMildd.cs b/Blog.Core.Extensions/Middlewares/IPLogMildd.cs
index 08791669..4f622458 100644
--- a/Blog.Core.Extensions/Middlewares/IPLogMildd.cs
+++ b/Blog.Core.Extensions/Middlewares/IPLogMildd.cs
@@ -57,24 +57,24 @@ public async Task InvokeAsync(HttpContext context)
if (!string.IsNullOrEmpty(requestInfo))
{
// 自定义log输出
- //Parallel.For(0, 1, e =>
- //{
- // LogLock.OutSql2Log("RequestIpInfoLog", new string[] { requestInfo + "," }, false);
- //});
-
- try
- {
- var testLogMatchRequestInfo = JsonConvert.DeserializeObject(requestInfo);
- if (testLogMatchRequestInfo != null)
- {
- var logFileName = FileHelper.GetAvailableFileNameWithPrefixOrderSize(_environment.ContentRootPath, "RequestIpInfoLog");
- SerilogServer.WriteLog(logFileName, new string[] { requestInfo + "," }, false, "", true);
- }
- }
- catch (Exception e)
+ Parallel.For(0, 1, e =>
{
- log.Error(requestInfo + "\r\n" + e.GetBaseException().ToString());
- }
+ LogLock.OutSql2Log("RequestIpInfoLog", new string[] { requestInfo + "," }, false);
+ });
+
+ //try
+ //{
+ // var testLogMatchRequestInfo = JsonConvert.DeserializeObject(requestInfo);
+ // if (testLogMatchRequestInfo != null)
+ // {
+ // var logFileName = FileHelper.GetAvailableFileNameWithPrefixOrderSize(_environment.ContentRootPath, "RequestIpInfoLog");
+ // SerilogServer.WriteLog(logFileName, new string[] { requestInfo + "," }, false, "", true);
+ // }
+ //}
+ //catch (Exception e)
+ //{
+ // log.Error(requestInfo + "\r\n" + e.GetBaseException().ToString());
+ //}
request.Body.Position = 0;
From 1fc32e5ccb40aa49ac23f88fc0176bd4b39d533b Mon Sep 17 00:00:00 2001
From: anjoy8 <3143422472@qq.com>
Date: Tue, 10 Aug 2021 17:03:25 +0800
Subject: [PATCH 062/456] fix:remove some no need code
---
Blog.Core.Api/Blog.Core.xml | 2 +-
Blog.Core.Api/Controllers/NacosController.cs | 2 +-
Blog.Core.Extensions/Middlewares/IPLogMildd.cs | 1 -
.../NacosConfig/NacosListenConfigurationTask.cs | 3 +--
Blog.Core.Gateway/Controllers/UserController.cs | 1 -
Blog.Core.Gateway/Startup.cs | 2 --
6 files changed, 3 insertions(+), 8 deletions(-)
diff --git a/Blog.Core.Api/Blog.Core.xml b/Blog.Core.Api/Blog.Core.xml
index 35c54ff6..adb43a72 100644
--- a/Blog.Core.Api/Blog.Core.xml
+++ b/Blog.Core.Api/Blog.Core.xml
@@ -829,7 +829,7 @@
-
+
系统实例是否启动完成
diff --git a/Blog.Core.Api/Controllers/NacosController.cs b/Blog.Core.Api/Controllers/NacosController.cs
index 8c824296..6aac936a 100644
--- a/Blog.Core.Api/Controllers/NacosController.cs
+++ b/Blog.Core.Api/Controllers/NacosController.cs
@@ -45,7 +45,7 @@ public NacosController(INacosNamingService nacosNamingService)
///
[HttpGet]
- public async Task> checkSystemStartFinish()
+ public MessageModel CheckSystemStartFinish()
{
//********************* 用当前接口做基本健康检查 确定 基础服务 数据库 缓存都已正常启动*****
// 然后再进行服务上线
diff --git a/Blog.Core.Extensions/Middlewares/IPLogMildd.cs b/Blog.Core.Extensions/Middlewares/IPLogMildd.cs
index 4f622458..eda2e369 100644
--- a/Blog.Core.Extensions/Middlewares/IPLogMildd.cs
+++ b/Blog.Core.Extensions/Middlewares/IPLogMildd.cs
@@ -1,5 +1,4 @@
using Blog.Core.Common;
-using Blog.Core.Common.Helper;
using Blog.Core.Common.LogHelper;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
diff --git a/Blog.Core.Extensions/NacosConfig/NacosListenConfigurationTask.cs b/Blog.Core.Extensions/NacosConfig/NacosListenConfigurationTask.cs
index 42347ea2..d1554d15 100644
--- a/Blog.Core.Extensions/NacosConfig/NacosListenConfigurationTask.cs
+++ b/Blog.Core.Extensions/NacosConfig/NacosListenConfigurationTask.cs
@@ -41,9 +41,8 @@ protected override async Task ExecuteAsync(CancellationToken stoppingToken)
// Add listener
await _configClient.AddListener("blog.Core.Api.json", "DEFAULT_GROUP", nacosConfigListener);
}
- catch (Exception ex)
+ catch (Exception)
{
-
}
}
diff --git a/Blog.Core.Gateway/Controllers/UserController.cs b/Blog.Core.Gateway/Controllers/UserController.cs
index df715f30..8a2d7fa3 100644
--- a/Blog.Core.Gateway/Controllers/UserController.cs
+++ b/Blog.Core.Gateway/Controllers/UserController.cs
@@ -4,7 +4,6 @@
using Microsoft.AspNetCore.Mvc;
using System.Collections.Generic;
using System.Linq;
-using System.Security.Claims;
namespace Blog.Core.Gateway.Controllers
{
diff --git a/Blog.Core.Gateway/Startup.cs b/Blog.Core.Gateway/Startup.cs
index 64e7b48e..eddcdeb5 100644
--- a/Blog.Core.Gateway/Startup.cs
+++ b/Blog.Core.Gateway/Startup.cs
@@ -6,8 +6,6 @@
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
-using Ocelot.DependencyInjection;
-using Ocelot.Provider.Consul;
namespace Blog.Core.AdminMvc
{
From c19e43188f9a40062e4ba7aeacee47748bf84113 Mon Sep 17 00:00:00 2001
From: a5855945
Date: Sat, 14 Aug 2021 14:09:26 +0800
Subject: [PATCH 063/456] =?UTF-8?q?=E4=BF=AE=E6=94=B9redis=E7=BC=93?=
=?UTF-8?q?=E5=AD=98=E4=BF=9D=E5=AD=98=E5=AD=97=E7=AC=A6=E4=B8=B2=E4=B9=9F?=
=?UTF-8?q?=E8=A2=AB=E5=BA=8F=E5=88=97=E5=8C=96=E5=AF=BC=E8=87=B4GetValue?=
=?UTF-8?q?=E7=9A=84=E5=80=BC=E4=B8=8D=E5=AF=B9?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
Blog.Core.Extensions/Redis/RedisBasketRepository.cs | 12 ++++++++++--
Blog.Core.Extensions/Redis/RedisCacheManager.cs | 12 ++++++++++--
2 files changed, 20 insertions(+), 4 deletions(-)
diff --git a/Blog.Core.Extensions/Redis/RedisBasketRepository.cs b/Blog.Core.Extensions/Redis/RedisBasketRepository.cs
index 02809bcb..31c7a030 100644
--- a/Blog.Core.Extensions/Redis/RedisBasketRepository.cs
+++ b/Blog.Core.Extensions/Redis/RedisBasketRepository.cs
@@ -59,8 +59,16 @@ public async Task Set(string key, object value, TimeSpan cacheTime)
{
if (value != null)
{
- //序列化,将object值生成RedisValue
- await _database.StringSetAsync(key, SerializeHelper.Serialize(value), cacheTime);
+ if (value is string cacheValue)
+ {
+ // 字符串无需序列化
+ await _database.StringSetAsync(key, cacheValue, cacheTime);
+ }
+ else
+ {
+ //序列化,将object值生成RedisValue
+ await _database.StringSetAsync(key, SerializeHelper.Serialize(value), cacheTime);
+ }
}
}
diff --git a/Blog.Core.Extensions/Redis/RedisCacheManager.cs b/Blog.Core.Extensions/Redis/RedisCacheManager.cs
index 040d79c4..ab4704df 100644
--- a/Blog.Core.Extensions/Redis/RedisCacheManager.cs
+++ b/Blog.Core.Extensions/Redis/RedisCacheManager.cs
@@ -137,8 +137,16 @@ public void Set(string key, object value, TimeSpan cacheTime)
{
if (value != null)
{
- //序列化,将object值生成RedisValue
- redisConnection.GetDatabase().StringSet(key, SerializeHelper.Serialize(value), cacheTime);
+ if (value is string cacheValue)
+ {
+ // 字符串无需序列化
+ redisConnection.GetDatabase().StringSet(key, cacheValue, cacheTime);
+ }
+ else
+ {
+ //序列化,将object值生成RedisValue
+ redisConnection.GetDatabase().StringSet(key, SerializeHelper.Serialize(value), cacheTime);
+ }
}
}
From 4b9448a08047938c14550b50d0ab469e0fbe8cf1 Mon Sep 17 00:00:00 2001
From: ansonzhang <3143422472@qq.com>
Date: Sun, 15 Aug 2021 11:07:36 +0800
Subject: [PATCH 064/456] Update README.md
---
README.md | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/README.md b/README.md
index 1e9ac25d..d473cc4c 100644
--- a/README.md
+++ b/README.md
@@ -96,13 +96,14 @@ Blog.Core 开箱即用的企业级前后端分离【 .NET Core5.0 Api + Vue 2.x
## 贡献者们
-Thanks goes to these wonderful people ([✨](https://github.com/anjoy8/Blog.Core/graphs/contributors)):
+Thanks goes to these wonderful people ([✨](https://github.com/anjoy8/Blog.Core/graphs/contributors)):(排名暂时按提交顺序)
| [
anjoy8](https://github.com/anjoy8)
💻📖 💡 | [
hudingwen](https://github.com/hudingwen)
💻 👀 | [
binyly ](https://github.com/binyly)
💻 👀 📖 🤔 | [
wuare ](https://github.com/wuare)
💻 🐛 🤔 | [
skang0401 ](https://github.com/skang0401)
📖| [
Jamnine](https://github.com/Jamnine)
💻 🌍|
| :---: | :---: | :---: | :---: | :---: | :---: |
-|[
aion1998 ](https://github.com/aion1998)
🐛|[
RLei123 ](https://github.com/RLei123)
💻|[
cluyun ](https://github.com/cluyun)
🌍|[
blue20171027 ](https://github.com/blue20171027)
💻|[
anewboyz ](https://github.com/anewboyz)
💻|[
jxd728 ](https://github.com/jxd728)
🌍|
+|[
aion1998 ](https://github.com/aion1998)
👍|[
RLei123 ](https://github.com/RLei123)
💻|[
cluyun ](https://github.com/cluyun)
🌍|[
blue20171027 ](https://github.com/blue20171027)
💻|[
anewboyz ](https://github.com/anewboyz)
💻|[
jxd728 ](https://github.com/jxd728)
🌍|
|[
wmchuang ](https://github.com/wmchuang)
🌍|[
liuzhenyulive ](https://github.com/liuzhenyulive)
💻|[
JsonBy ](https://github.com/JsonBy)
💻 💡 🤔|[
hsxian ](https://github.com/hsxian)
🌍|[
cuno92 ](https://github.com/cuno92)
📖|[
317447880 ](https://github.com/317447880)
💻|
+|[
Shuisen ](https://github.com/55371978)
💻|[
www5255977 ](https://github.com/45479028)
💻|...|
This project follows the [all-contributors](https://github.com/anjoy8/Blog.Core/graphs/contributors) specification.
From eefbe2c8c15910dfd0df94c5845c26201c1e7d27 Mon Sep 17 00:00:00 2001
From: hudingwen <765472804@qq.com>
Date: Thu, 19 Aug 2021 18:32:40 +0800
Subject: [PATCH 065/456] =?UTF-8?q?=E9=A1=B9=E7=9B=AE=E5=88=9D=E5=A7=8B?=
=?UTF-8?q?=E5=8C=96=E6=8A=A5=E9=94=99,=E7=94=B1=E4=BA=8Emodel=E5=B1=82?=
=?UTF-8?q?=E7=9A=84=E7=A8=8B=E5=BA=8F=E9=9B=86=E6=B2=A1=E6=89=BE=E5=88=B0?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
Blog.Core.Api/Blog.Core.xml | 6 ++++++
Blog.Core.Common/Seed/DBSeed.cs | 12 ++++++++----
2 files changed, 14 insertions(+), 4 deletions(-)
diff --git a/Blog.Core.Api/Blog.Core.xml b/Blog.Core.Api/Blog.Core.xml
index 3f79cf4e..35c54ff6 100644
--- a/Blog.Core.Api/Blog.Core.xml
+++ b/Blog.Core.Api/Blog.Core.xml
@@ -829,6 +829,12 @@
+
+
+ 系统实例是否启动完成
+
+
+
获取Nacos 状态
diff --git a/Blog.Core.Common/Seed/DBSeed.cs b/Blog.Core.Common/Seed/DBSeed.cs
index 05ced06c..1d00bbc7 100644
--- a/Blog.Core.Common/Seed/DBSeed.cs
+++ b/Blog.Core.Common/Seed/DBSeed.cs
@@ -89,10 +89,14 @@ public static async Task SeedAsync(MyContext myContext, string WebRootPath)
// 创建数据库表,遍历指定命名空间下的class,
// 注意不要把其他命名空间下的也添加进来。
Console.WriteLine("Create Tables...");
- var modelTypes = from t in Assembly.GetExecutingAssembly().GetTypes()
- where t.IsClass && t.Namespace == "Blog.Core.Model.Models"
- select t;
- modelTypes.ToList().ForEach(t =>
+
+ var path = AppDomain.CurrentDomain.RelativeSearchPath ?? AppDomain.CurrentDomain.BaseDirectory;
+ var referencedAssemblies = System.IO.Directory.GetFiles(path, "Blog.Core.Model.dll").Select(Assembly.LoadFrom).ToArray();
+ var modelTypes = referencedAssemblies
+ .SelectMany(a => a.DefinedTypes)
+ .Select(type => type.AsType())
+ .Where(x => x.IsClass && x.Namespace != null && x.Namespace.Equals("Blog.Core.Model.Models")).ToList();
+ modelTypes.ForEach(t =>
{
// 这里只支持添加表,不支持删除
// 如果想要删除,数据库直接右键删除,或者联系SqlSugar作者;
From d08ccc6474d0f96c7ded850ac9f397ed2e22660e Mon Sep 17 00:00:00 2001
From: hudingwen <765472804@qq.com>
Date: Fri, 20 Aug 2021 14:21:21 +0800
Subject: [PATCH 066/456] webhook-test
---
webhook-test.txt | 1 +
1 file changed, 1 insertion(+)
create mode 100644 webhook-test.txt
diff --git a/webhook-test.txt b/webhook-test.txt
new file mode 100644
index 00000000..39d1980e
--- /dev/null
+++ b/webhook-test.txt
@@ -0,0 +1 @@
+webhook-test
\ No newline at end of file
From e130256d3b9f46864dd2eab2bfa89d249a0f3203 Mon Sep 17 00:00:00 2001
From: hudingwen <765472804@qq.com>
Date: Fri, 20 Aug 2021 14:22:48 +0800
Subject: [PATCH 067/456] =?UTF-8?q?webhook=E6=B5=8B=E8=AF=95?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
webhook-test.txt | 1 -
1 file changed, 1 deletion(-)
delete mode 100644 webhook-test.txt
diff --git a/webhook-test.txt b/webhook-test.txt
deleted file mode 100644
index 39d1980e..00000000
--- a/webhook-test.txt
+++ /dev/null
@@ -1 +0,0 @@
-webhook-test
\ No newline at end of file
From 9aececb180717d9d296c7c1851374f9394b7eef0 Mon Sep 17 00:00:00 2001
From: hudingwen <765472804@qq.com>
Date: Sat, 21 Aug 2021 13:08:06 +0800
Subject: [PATCH 068/456] test webhook
---
test-webhook.txt | 1 +
1 file changed, 1 insertion(+)
create mode 100644 test-webhook.txt
diff --git a/test-webhook.txt b/test-webhook.txt
new file mode 100644
index 00000000..9af488ac
--- /dev/null
+++ b/test-webhook.txt
@@ -0,0 +1 @@
+test-webhook
\ No newline at end of file
From 3dc1dc964a95a9ee108db5fd708d7883546edfd3 Mon Sep 17 00:00:00 2001
From: hudingwen <765472804@qq.com>
Date: Sat, 21 Aug 2021 13:09:17 +0800
Subject: [PATCH 069/456] test webhook
---
test-webhook.txt | 1 -
1 file changed, 1 deletion(-)
delete mode 100644 test-webhook.txt
diff --git a/test-webhook.txt b/test-webhook.txt
deleted file mode 100644
index 9af488ac..00000000
--- a/test-webhook.txt
+++ /dev/null
@@ -1 +0,0 @@
-test-webhook
\ No newline at end of file
From ed7bc9afc68801bc6ddf9a9883ebd8b888eb6f51 Mon Sep 17 00:00:00 2001
From: 867824092
Date: Sat, 21 Aug 2021 20:18:34 +0800
Subject: [PATCH 070/456] Added Apollo configuration center
---
Blog.Core.Api/Blog.Core.xml | 5 ++
Blog.Core.Api/Controllers/ValuesController.cs | 20 +++++
Blog.Core.Api/Program.cs | 3 +
Blog.Core.Api/appsettings.apollo.json | 18 ++++
Blog.Core.Extensions/Apollo/ApolloOptions.cs | 27 ++++++
.../Apollo/ConfigurationBuilderExtensions.cs | 84 +++++++++++++++++++
.../Blog.Core.Extensions.csproj | 2 +
7 files changed, 159 insertions(+)
create mode 100644 Blog.Core.Api/appsettings.apollo.json
create mode 100644 Blog.Core.Extensions/Apollo/ApolloOptions.cs
create mode 100644 Blog.Core.Extensions/Apollo/ConfigurationBuilderExtensions.cs
diff --git a/Blog.Core.Api/Blog.Core.xml b/Blog.Core.Api/Blog.Core.xml
index adb43a72..6510d666 100644
--- a/Blog.Core.Api/Blog.Core.xml
+++ b/Blog.Core.Api/Blog.Core.xml
@@ -813,6 +813,11 @@
+
+
+ 此处的key格式为 xx:xx:x
+
+
服务管理
diff --git a/Blog.Core.Api/Controllers/ValuesController.cs b/Blog.Core.Api/Controllers/ValuesController.cs
index 7399d8f7..7bca6d8f 100644
--- a/Blog.Core.Api/Controllers/ValuesController.cs
+++ b/Blog.Core.Api/Controllers/ValuesController.cs
@@ -1,4 +1,5 @@
using AutoMapper;
+using Blog.Core.Common;
using Blog.Core.Common.HttpContextUser;
using Blog.Core.Common.HttpRestSharp;
using Blog.Core.Common.WebApiClients.HttpApis;
@@ -12,6 +13,7 @@
using Blog.Core.Model.ViewModels;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
+using Microsoft.Extensions.Configuration;
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
@@ -349,5 +351,23 @@ public void Put(int id, [FromBody] string value)
public void Delete(int id)
{
}
+
+ #region Apollo 配置
+ [HttpGet("/apollo")]
+ [AllowAnonymous]
+ public async Task>> GetAllConfigByAppllo([FromServices]IConfiguration configuration)
+ {
+ return await Task.FromResult(configuration.AsEnumerable());
+ }
+ ///
+ /// 此处的key格式为 xx:xx:x
+ ///
+ [HttpGet("/apollo/{key}")]
+ [AllowAnonymous]
+ public async Task GetConfigByAppllo(string key)
+ {
+ return await Task.FromResult(Appsettings.app(key));
+ }
+ #endregion
}
}
diff --git a/Blog.Core.Api/Program.cs b/Blog.Core.Api/Program.cs
index 30615a39..d405b821 100644
--- a/Blog.Core.Api/Program.cs
+++ b/Blog.Core.Api/Program.cs
@@ -1,4 +1,5 @@
using Autofac.Extensions.DependencyInjection;
+using Blog.Core.Extensions.Apollo;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Hosting;
@@ -25,6 +26,8 @@ public static void Main(string[] args)
config.AddJsonFile("appsettings.json", optional: true, reloadOnChange: false)
//.AddJsonFile($"appsettings{ GetAppSettingsConfigName() }json", optional: true, reloadOnChange: false)
;
+ //接入Apollo配置中心
+ config.AddConfigurationApollo("appsettings.apollo.json");
})
.UseUrls("http://*:8081")
.ConfigureLogging((hostingContext, builder) =>
diff --git a/Blog.Core.Api/appsettings.apollo.json b/Blog.Core.Api/appsettings.apollo.json
new file mode 100644
index 00000000..f938acd0
--- /dev/null
+++ b/Blog.Core.Api/appsettings.apollo.json
@@ -0,0 +1,18 @@
+{
+ //apollo 配置
+ "Apollo": {
+ "Enable": true,
+ "Config": {
+ "AppId": "blog.core",
+ "Env": "DEV",
+ "MetaServer": "http://localhost:8080/",
+ "ConfigServer": [ "http://localhost:8080/" ]
+ },
+ "Namespaces": [ //Namespaces的数据格式Properties,Xml,Json,Yml,Yaml,Txt
+ {
+ "Name": "test",
+ "Format": "json"
+ }
+ ]
+ }
+}
\ No newline at end of file
diff --git a/Blog.Core.Extensions/Apollo/ApolloOptions.cs b/Blog.Core.Extensions/Apollo/ApolloOptions.cs
new file mode 100644
index 00000000..6610ba47
--- /dev/null
+++ b/Blog.Core.Extensions/Apollo/ApolloOptions.cs
@@ -0,0 +1,27 @@
+
+using System.Collections.Generic;
+
+
+namespace Blog.Core.Extensions.Apollo
+{
+ ///
+ /// Apollo配置项
+ ///
+ public class ApolloOptions
+ {
+ public bool Enable { get; set; }
+ public List Namespaces { get; set; }
+
+ public class ChildNamespace
+ {
+ ///
+ /// 命名空间名字
+ ///
+ public string Name { get; set; }
+ ///
+ /// 数据格式 Json/Yml/Yaml等
+ ///
+ public string Format { get; set; }
+ }
+ }
+}
diff --git a/Blog.Core.Extensions/Apollo/ConfigurationBuilderExtensions.cs b/Blog.Core.Extensions/Apollo/ConfigurationBuilderExtensions.cs
new file mode 100644
index 00000000..909e9a19
--- /dev/null
+++ b/Blog.Core.Extensions/Apollo/ConfigurationBuilderExtensions.cs
@@ -0,0 +1,84 @@
+using Com.Ctrip.Framework.Apollo;
+using Microsoft.Extensions.Configuration;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using Com.Ctrip.Framework.Apollo.Enums;
+using Com.Ctrip.Framework.Apollo.Logging;
+using Microsoft.Extensions.Primitives;
+using System.Reflection;
+
+namespace Blog.Core.Extensions.Apollo
+{
+ public static class ConfigurationBuilderExtensions
+ {
+ ///
+ /// 接入Apollo
+ ///
+ ///
+ /// apollo配置文件路径 如果写入appsettings.json中 则jsonPath传null即可
+ public static void AddConfigurationApollo(this IConfigurationBuilder builder,string jsonPath)
+ {
+ if (!string.IsNullOrEmpty(jsonPath))
+ {
+ builder.AddJsonFile(jsonPath, true, false);
+ }
+ //阿波罗的日志级别调整
+ LogManager.UseConsoleLogging(LogLevel.Warn);
+ var options = new ApolloOptions();
+ var root = builder.Build();
+ root.Bind("Apollo", options);
+ if (options.Enable)
+ {
+ var apolloBuilder = builder.AddApollo(root.GetSection("Apollo:Config"));
+
+ foreach (var item in options.Namespaces)
+ {
+ apolloBuilder.AddNamespace(item.Name, MatchConfigFileFormat(item.Format));
+ }
+ //监听apollo配置
+ Monitor(builder.Build());
+ }
+
+ }
+ #region private
+ ///
+ /// 监听配置
+ ///
+ private static void Monitor(IConfigurationRoot root)
+ {
+ //TODO 需要根据改变执行特定的操作 如 mq redis 等其他跟配置相关的中间件
+ //TODO 初步思路:将需要执行特定的操作key和value放入内存字典中,在赋值操作时通过标准事件来执行特定的操作。
+
+ //要重新Build 此时才将Apollo provider加入到ConfigurationBuilder中
+ ChangeToken.OnChange(() => root.GetReloadToken(), () =>
+ {
+ foreach (var apolloProvider in root.Providers.Where(p => p is ApolloConfigurationProvider))
+ {
+ var property = apolloProvider.GetType().BaseType.GetProperty("Data", BindingFlags.Instance | BindingFlags.NonPublic);
+ var data = property.GetValue(apolloProvider) as IDictionary;
+ foreach (var item in data)
+ {
+ Console.WriteLine($"key {item.Key} value {item.Value}");
+ }
+ }
+ });
+ }
+
+ //匹配格式
+ private static ConfigFileFormat MatchConfigFileFormat(string value) => value switch
+ {
+ "json" => ConfigFileFormat.Json,
+ "properties" => ConfigFileFormat.Properties,
+ "xml" => ConfigFileFormat.Xml,
+ "yml" => ConfigFileFormat.Yml,
+ "yaml" => ConfigFileFormat.Yaml,
+ "txt" => ConfigFileFormat.Txt,
+ _ => throw new FormatException($"与apollo命名空间的所允许的类型不匹配:{string.Join(",", GetConfigFileFormat())}"),
+ };
+ //获取数据格式对应的枚举
+ private static IEnumerable GetConfigFileFormat() => Enum.GetValues().Select(u => u.ToString().ToLower());
+ #endregion
+
+ }
+}
diff --git a/Blog.Core.Extensions/Blog.Core.Extensions.csproj b/Blog.Core.Extensions/Blog.Core.Extensions.csproj
index e10b8f57..90d5ed97 100644
--- a/Blog.Core.Extensions/Blog.Core.Extensions.csproj
+++ b/Blog.Core.Extensions/Blog.Core.Extensions.csproj
@@ -8,6 +8,8 @@
+
+
From d443cd4cc0eff9fe0b4b3a036e4d7c53120c90d3 Mon Sep 17 00:00:00 2001
From: 867824092
Date: Sat, 21 Aug 2021 20:27:11 +0800
Subject: [PATCH 071/456] Apollo API description changed
---
Blog.Core.Api/Controllers/ValuesController.cs | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/Blog.Core.Api/Controllers/ValuesController.cs b/Blog.Core.Api/Controllers/ValuesController.cs
index 7bca6d8f..002f1e62 100644
--- a/Blog.Core.Api/Controllers/ValuesController.cs
+++ b/Blog.Core.Api/Controllers/ValuesController.cs
@@ -353,6 +353,9 @@ public void Delete(int id)
}
#region Apollo 配置
+ ///
+ /// 测试接入Apollo获取配置信息
+ ///
[HttpGet("/apollo")]
[AllowAnonymous]
public async Task>> GetAllConfigByAppllo([FromServices]IConfiguration configuration)
@@ -360,7 +363,7 @@ public async Task>> GetAllConfigByAppllo
return await Task.FromResult(configuration.AsEnumerable());
}
///
- /// 此处的key格式为 xx:xx:x
+ /// 通过此处的key格式为 xx:xx:x
///
[HttpGet("/apollo/{key}")]
[AllowAnonymous]
From 6ddb627474fd7ce875b842700ed2b70c8e7ef653 Mon Sep 17 00:00:00 2001
From: ansonzhang <3143422472@qq.com>
Date: Sat, 21 Aug 2021 22:54:52 +0800
Subject: [PATCH 072/456] Update README.md
---
README.md | 1 +
1 file changed, 1 insertion(+)
diff --git a/README.md b/README.md
index d473cc4c..44a20db5 100644
--- a/README.md
+++ b/README.md
@@ -76,6 +76,7 @@ Blog.Core 开箱即用的企业级前后端分离【 .NET Core5.0 Api + Vue 2.x
- [x] 新增 - 统一聚合支付;
- [x] 新增 - Nacos注册中心配置;
- [x] 新增 - ES 搜索配置;
+- [x] 新增 - Apollo 配置;
- [ ] 计划 - 数据部门权限;
微服务模块:
From 297cefcd20d5f2a461b2f339f9e30d3d2a3968bc Mon Sep 17 00:00:00 2001
From: zhanganzhong
Date: Sat, 21 Aug 2021 23:25:06 +0800
Subject: [PATCH 073/456] =?UTF-8?q?feat=EF=BC=9Adefault=20close=20Apollo?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
Blog.Core.Api/Blog.Core.xml | 7 ++++++-
Blog.Core.Api/appsettings.apollo.json | 2 +-
2 files changed, 7 insertions(+), 2 deletions(-)
diff --git a/Blog.Core.Api/Blog.Core.xml b/Blog.Core.Api/Blog.Core.xml
index 6510d666..87df176e 100644
--- a/Blog.Core.Api/Blog.Core.xml
+++ b/Blog.Core.Api/Blog.Core.xml
@@ -813,9 +813,14 @@
+
+
+ 测试接入Apollo获取配置信息
+
+
- 此处的key格式为 xx:xx:x
+ 通过此处的key格式为 xx:xx:x
diff --git a/Blog.Core.Api/appsettings.apollo.json b/Blog.Core.Api/appsettings.apollo.json
index f938acd0..826c75ca 100644
--- a/Blog.Core.Api/appsettings.apollo.json
+++ b/Blog.Core.Api/appsettings.apollo.json
@@ -1,7 +1,7 @@
{
//apollo 配置
"Apollo": {
- "Enable": true,
+ "Enable": false,
"Config": {
"AppId": "blog.core",
"Env": "DEV",
From a48865c311a9bb34c36cb6348442f52d651a9946 Mon Sep 17 00:00:00 2001
From: ansonzhang <3143422472@qq.com>
Date: Sat, 21 Aug 2021 23:46:46 +0800
Subject: [PATCH 074/456] Update README.md
---
README.md | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/README.md b/README.md
index 44a20db5..79020178 100644
--- a/README.md
+++ b/README.md
@@ -100,11 +100,11 @@ Blog.Core 开箱即用的企业级前后端分离【 .NET Core5.0 Api + Vue 2.x
Thanks goes to these wonderful people ([✨](https://github.com/anjoy8/Blog.Core/graphs/contributors)):(排名暂时按提交顺序)
-| [
anjoy8](https://github.com/anjoy8)
💻📖 💡 | [
hudingwen](https://github.com/hudingwen)
💻 👀 | [
binyly ](https://github.com/binyly)
💻 👀 📖 🤔 | [
wuare ](https://github.com/wuare)
💻 🐛 🤔 | [
skang0401 ](https://github.com/skang0401)
📖| [
Jamnine](https://github.com/Jamnine)
💻 🌍|
+| [
anjoy8](https://github.com/anjoy8)
💻📖 💡 | [
hudingwen](https://github.com/hudingwen)
💻 👀 | [
binyly ](https://github.com/binyly)
💻 👀 📖 👍 | [
wuare ](https://github.com/wuare)
💻😀 | [
skang0401 ](https://github.com/skang0401)
📖| [
Jamnine](https://github.com/Jamnine)
💻 🌍|
| :---: | :---: | :---: | :---: | :---: | :---: |
-|[
aion1998 ](https://github.com/aion1998)
👍|[
RLei123 ](https://github.com/RLei123)
💻|[
cluyun ](https://github.com/cluyun)
🌍|[
blue20171027 ](https://github.com/blue20171027)
💻|[
anewboyz ](https://github.com/anewboyz)
💻|[
jxd728 ](https://github.com/jxd728)
🌍|
-|[
wmchuang ](https://github.com/wmchuang)
🌍|[
liuzhenyulive ](https://github.com/liuzhenyulive)
💻|[
JsonBy ](https://github.com/JsonBy)
💻 💡 🤔|[
hsxian ](https://github.com/hsxian)
🌍|[
cuno92 ](https://github.com/cuno92)
📖|[
317447880 ](https://github.com/317447880)
💻|
-|[
Shuisen ](https://github.com/55371978)
💻|[
www5255977 ](https://github.com/45479028)
💻|...|
+|[
aion1998 ](https://github.com/aion1998)
👍|[
RLei123 ](https://github.com/RLei123)
😄|[
cluyun ](https://github.com/cluyun)
🍬|[
blue20171027 ](https://github.com/blue20171027)
✈|[
anewboyz ](https://github.com/anewboyz)
💻|[
jxd728 ](https://github.com/jxd728)
🌍|
+|[
wmchuang ](https://github.com/wmchuang)
🍟|[
liuzhenyulive ](https://github.com/liuzhenyulive)
💻|[
JsonBy ](https://github.com/JsonBy)
💻 💡 🤔|[
hsxian ](https://github.com/hsxian)
🎉|[
cuno92 ](https://github.com/cuno92)
📖|[
317447880 ](https://github.com/317447880)
💻|
+|[
Shuisen ](https://github.com/Shuisen)
💻|[
www5255977 ](https://github.com/www5255977)
🌍|[
867824092 ](https://github.com/867824092)
🍳|
This project follows the [all-contributors](https://github.com/anjoy8/Blog.Core/graphs/contributors) specification.
From e9248f5ecc62107ca5d912f59fb022e10885aa40 Mon Sep 17 00:00:00 2001
From: 867824092
Date: Mon, 23 Aug 2021 21:34:37 +0800
Subject: [PATCH 075/456] Kafka message communication
---
Blog.Core.Api/Startup.cs | 1 +
Blog.Core.Api/appsettings.json | 7 +
Blog.Core.EventBus/Blog.Core.EventBus.csproj | 2 +
.../EventBusKafka/EventBusKafka.cs | 118 +++++++++++++
.../EventBusKafka/IKafkaConnectionPool.cs | 25 +++
.../EventBusKafka/KafkaConnectionPool.cs | 79 +++++++++
.../EventBusKafka/KafkaConsumerHostService.cs | 162 ++++++++++++++++++
.../EventBusKafka/KafkaOptions.cs | 28 +++
.../EventBusKafka/ProtobufTransfer.cs | 32 ++++
.../ServiceExtensions/EventBusSetup.cs | 40 +++--
.../ServiceExtensions/KafkaSetup.cs | 26 +++
11 files changed, 503 insertions(+), 17 deletions(-)
create mode 100644 Blog.Core.EventBus/EventBusKafka/EventBusKafka.cs
create mode 100644 Blog.Core.EventBus/EventBusKafka/IKafkaConnectionPool.cs
create mode 100644 Blog.Core.EventBus/EventBusKafka/KafkaConnectionPool.cs
create mode 100644 Blog.Core.EventBus/EventBusKafka/KafkaConsumerHostService.cs
create mode 100644 Blog.Core.EventBus/EventBusKafka/KafkaOptions.cs
create mode 100644 Blog.Core.EventBus/EventBusKafka/ProtobufTransfer.cs
create mode 100644 Blog.Core.Extensions/ServiceExtensions/KafkaSetup.cs
diff --git a/Blog.Core.Api/Startup.cs b/Blog.Core.Api/Startup.cs
index 36969a92..b2aaf7ab 100644
--- a/Blog.Core.Api/Startup.cs
+++ b/Blog.Core.Api/Startup.cs
@@ -68,6 +68,7 @@ public void ConfigureServices(IServiceCollection services)
services.AddRedisInitMqSetup();
services.AddRabbitMQSetup();
+ services.AddKafkaSetup(Configuration);
services.AddEventBusSetup();
services.AddNacosSetup(Configuration);
diff --git a/Blog.Core.Api/appsettings.json b/Blog.Core.Api/appsettings.json
index 989b1d0d..39c865db 100644
--- a/Blog.Core.Api/appsettings.json
+++ b/Blog.Core.Api/appsettings.json
@@ -31,6 +31,13 @@
"UserName": "",
"Password": "!",
"RetryCount": 3
+ },
+ "Kafka": {
+ "Enabled": false,
+ "Servers": "localhost:9092",
+ "Topic": "blog",
+ "GroupId": "blog-consumer",
+ "NumPartitions": 3 //主题分区数量
},
"EventBus": {
"Enabled": false,
diff --git a/Blog.Core.EventBus/Blog.Core.EventBus.csproj b/Blog.Core.EventBus/Blog.Core.EventBus.csproj
index d15a0109..b71254af 100644
--- a/Blog.Core.EventBus/Blog.Core.EventBus.csproj
+++ b/Blog.Core.EventBus/Blog.Core.EventBus.csproj
@@ -8,11 +8,13 @@
+
+
diff --git a/Blog.Core.EventBus/EventBusKafka/EventBusKafka.cs b/Blog.Core.EventBus/EventBusKafka/EventBusKafka.cs
new file mode 100644
index 00000000..6b2dd0fb
--- /dev/null
+++ b/Blog.Core.EventBus/EventBusKafka/EventBusKafka.cs
@@ -0,0 +1,118 @@
+using Blog.Core.Common.Extensions;
+using Confluent.Kafka;
+using Microsoft.Extensions.Logging;
+using Microsoft.Extensions.Options;
+using Newtonsoft.Json;
+using System;
+
+namespace Blog.Core.EventBus
+{
+ ///
+ /// 基于Kafka的事件总线
+ ///
+ public class EventBusKafka : IEventBus
+ {
+ private readonly ILogger _logger;
+ private readonly IEventBusSubscriptionsManager _subsManager;
+ private readonly IKafkaConnectionPool _connectionPool;
+ private readonly KafkaOptions _options;
+ public EventBusKafka(ILogger logger,
+ IEventBusSubscriptionsManager subsManager,
+ IKafkaConnectionPool connectionPool,
+ IOptions options)
+ {
+ _logger = logger;
+ _subsManager = subsManager;
+ _connectionPool = connectionPool;
+ _options = options.Value;
+ }
+ ///
+ /// 发布
+ ///
+ public void Publish(IntegrationEvent @event)
+ {
+ var producer = _connectionPool.Producer();
+ try
+ {
+ var eventName = @event.GetType().Name;
+ var body = Protobuf.Serialize(JsonConvert.SerializeObject(@event));
+ DeliveryResult result = producer.ProduceAsync(_options.Topic, new Message
+ {
+ Key = eventName,
+ Value = body
+ }).ConfigureAwait(false).GetAwaiter().GetResult();
+ }
+ catch (Exception ex)
+ {
+ _logger.LogWarning($"Could not publish event: {@event.Id.ToString("N")} ({ex.Message}); Message:{ JsonConvert.SerializeObject(@event)}");
+ }
+ finally
+ {
+ //放入连接池中
+ _connectionPool.Return(producer);
+ }
+ }
+
+ ///
+ /// 订阅
+ /// 动态
+ ///
+ /// 事件处理器
+ /// 事件名
+ public void SubscribeDynamic(string eventName)
+ where TH : IDynamicIntegrationEventHandler
+ {
+ _logger.LogInformation("Subscribing to dynamic event {EventName} with {EventHandler}", eventName, typeof(TH).GetGenericTypeName());
+
+ _subsManager.AddDynamicSubscription | (eventName);
+ }
+
+ ///
+ /// 订阅
+ ///
+ /// 约束:事件模型
+ /// 约束:事件处理器<事件模型>
+ public void Subscribe()
+ where T : IntegrationEvent
+ where TH : IIntegrationEventHandler
+ {
+ var eventName = _subsManager.GetEventKey();
+
+ _logger.LogInformation("Subscribing to event {EventName} with {EventHandler}", eventName, typeof(TH).GetGenericTypeName());
+
+ _subsManager.AddSubscription();
+ }
+
+ ///
+ /// 取消订阅
+ ///
+ ///
+ ///
+ public void Unsubscribe()
+ where T : IntegrationEvent
+ where TH : IIntegrationEventHandler
+ {
+ var eventName = _subsManager.GetEventKey();
+
+ _logger.LogInformation("Unsubscribing from event {EventName}", eventName);
+
+ _subsManager.RemoveSubscription();
+ }
+
+ public void UnsubscribeDynamic| (string eventName)
+ where TH : IDynamicIntegrationEventHandler
+ {
+ _subsManager.RemoveDynamicSubscription | (eventName);
+ }
+
+ public void Dispose()
+ {
+ if (_connectionPool != null)
+ {
+ _connectionPool.Dispose();
+ }
+ _subsManager.Clear();
+ }
+
+ }
+}
diff --git a/Blog.Core.EventBus/EventBusKafka/IKafkaConnectionPool.cs b/Blog.Core.EventBus/EventBusKafka/IKafkaConnectionPool.cs
new file mode 100644
index 00000000..0968e0e3
--- /dev/null
+++ b/Blog.Core.EventBus/EventBusKafka/IKafkaConnectionPool.cs
@@ -0,0 +1,25 @@
+using Confluent.Kafka;
+using System;
+
+
+namespace Blog.Core.EventBus
+{
+ ///
+ /// Kafka连接池
+ ///
+ public interface IKafkaConnectionPool:IDisposable
+ {
+ ///
+ /// 取对象
+ ///
+ ///
+ IProducer Producer();
+
+ ///
+ /// 将对象放入连接池
+ ///
+ ///
+ ///
+ bool Return(IProducer producer);
+ }
+}
diff --git a/Blog.Core.EventBus/EventBusKafka/KafkaConnectionPool.cs b/Blog.Core.EventBus/EventBusKafka/KafkaConnectionPool.cs
new file mode 100644
index 00000000..addd1f6b
--- /dev/null
+++ b/Blog.Core.EventBus/EventBusKafka/KafkaConnectionPool.cs
@@ -0,0 +1,79 @@
+using Confluent.Kafka;
+using Microsoft.Extensions.Logging;
+using Microsoft.Extensions.Options;
+using System.Collections.Concurrent;
+using System.Threading;
+
+
+namespace Blog.Core.EventBus
+{
+ ///
+ /// Kafka producer 连接池管理
+ /// 可以使用微软官方的对象池进行构造ObjectPool
+ ///
+ public class KafkaConnectionPool : IKafkaConnectionPool
+ {
+ private readonly KafkaOptions _options;
+ private ConcurrentQueue> _producerPool = new();
+ private int _currentCount;
+ private int _maxSize;
+ public KafkaConnectionPool(IOptions options)
+ {
+ _options = options.Value;
+ _maxSize = _options.ConnectionPoolSize;
+ }
+
+ ///
+ /// 取对象
+ ///
+ ///
+ public IProducer Producer()
+ {
+ if (_producerPool.TryDequeue(out var producer))
+ {
+ Interlocked.Decrement(ref _currentCount);
+ return producer;
+ }
+
+ var config = new ProducerConfig()
+ {
+ BootstrapServers = _options.Servers,
+ QueueBufferingMaxMessages = 10,
+ MessageTimeoutMs = 5000,
+ RequestTimeoutMs = 3000
+ };
+
+ producer = new ProducerBuilder(config)
+ .Build();
+ return producer;
+ }
+ ///
+ /// 将对象放入连接池
+ ///
+ ///
+ ///
+ public bool Return(IProducer producer)
+ {
+ if (Interlocked.Increment(ref _currentCount) <= _maxSize)
+ {
+ _producerPool.Enqueue(producer);
+ return true;
+ }
+
+ producer.Dispose();
+ Interlocked.Decrement(ref _currentCount);
+
+ return false;
+ }
+ public void Dispose()
+ {
+ _maxSize = 0;
+ _currentCount = 0;
+ while (_producerPool.TryDequeue(out var context))
+ {
+ context?.Dispose();
+ }
+ }
+
+ }
+}
diff --git a/Blog.Core.EventBus/EventBusKafka/KafkaConsumerHostService.cs b/Blog.Core.EventBus/EventBusKafka/KafkaConsumerHostService.cs
new file mode 100644
index 00000000..27fcd000
--- /dev/null
+++ b/Blog.Core.EventBus/EventBusKafka/KafkaConsumerHostService.cs
@@ -0,0 +1,162 @@
+using Autofac;
+using Confluent.Kafka;
+using Confluent.Kafka.Admin;
+using Microsoft.Extensions.Hosting;
+using Microsoft.Extensions.Logging;
+using Microsoft.Extensions.Options;
+using Newtonsoft.Json;
+using Newtonsoft.Json.Linq;
+using System;
+using System.Linq;
+using System.Threading;
+using System.Threading.Tasks;
+
+namespace Blog.Core.EventBus
+{
+ ///
+ /// Kafka consumer 监听服务
+ ///
+ public class KafkaConsumerHostService : BackgroundService
+ {
+ private readonly string AUTOFAC_SCOPE_NAME = "blogcore_event_bus";
+ private readonly ILogger _logger;
+ private readonly IConsumer _consumer;
+ private readonly KafkaOptions _options;
+ private readonly IEventBusSubscriptionsManager _subsManager;
+ private readonly ILifetimeScope _autofac;
+ private CancellationTokenSource cts = new();
+ public KafkaConsumerHostService(ILogger logger,
+ IOptions options,
+ IEventBusSubscriptionsManager eventBusSubscriptionsManager,
+ ILifetimeScope autofac)
+ {
+ _autofac = autofac;
+ _subsManager = eventBusSubscriptionsManager;
+ _logger = logger;
+ _options = options.Value;
+ _consumer = new ConsumerBuilder(new ConsumerConfig
+ {
+ BootstrapServers = _options.Servers,
+ GroupId = _options.GroupId,
+ AutoOffsetReset = AutoOffsetReset.Earliest,
+ AllowAutoCreateTopics = true,
+ EnableAutoCommit = false,
+ LogConnectionClose = false
+ }).SetErrorHandler(ConsumerClient_OnConsumeError)
+ .Build();
+ }
+ protected override async Task ExecuteAsync(CancellationToken stoppingToken)
+ {
+ var result = await FetchTopicAsync();
+ if (result)
+ {
+ _consumer.Subscribe(_options.Topic);
+ while (!cts.Token.IsCancellationRequested)
+ {
+ var consumerResult = _consumer.Consume(cts.Token);
+ try
+ {
+ if (consumerResult.IsPartitionEOF || consumerResult.Message.Value == null) continue;
+
+ var @event = Protobuf.Deserialize(consumerResult.Message.Value);
+ await ProcessEvent(consumerResult.Message.Key, @event);
+ }
+ catch (ConsumeException e)
+ {
+ _logger.LogError($"Error occured: {e.Error.Reason}");
+ }
+ finally
+ {
+ _consumer.Commit(consumerResult);
+ }
+ }
+ }
+ }
+ public override Task StopAsync(CancellationToken cancellationToken)
+ {
+ cts.Cancel();
+ _logger.LogInformation("kafka consumer stop and disposable");
+ _consumer.Dispose();
+ return base.StopAsync(cancellationToken);
+ }
+ ///
+ /// 检测当前Topic是否存在
+ ///
+ ///
+ private async Task FetchTopicAsync()
+ {
+ if (string.IsNullOrEmpty(_options.Topic))
+ throw new ArgumentNullException(nameof(_options.Topic));
+
+ try
+ {
+ var config = new AdminClientConfig { BootstrapServers = _options.Servers };
+ using var adminClient = new AdminClientBuilder(config).Build();
+ await adminClient.CreateTopicsAsync(Enumerable.Range(0,1).Select(u=> new TopicSpecification
+ {
+ Name = _options.Topic,
+ NumPartitions = _options.NumPartitions
+ }));
+ }
+ catch (CreateTopicsException ex) when (ex.Message.Contains("already exists"))
+ {
+ }
+ catch (Exception ex)
+ {
+ _logger.LogError("An error was encountered when automatically creating topic! -->" + ex.Message);
+ return false;
+ }
+ return true;
+ }
+ ///
+ /// 接收到消息进行处理
+ ///
+ /// 事件名称
+ /// 消息内容
+ ///
+ private async Task ProcessEvent(string eventName, string message)
+ {
+ _logger.LogTrace("Processing Kafka event: {EventName}", eventName);
+
+ if (_subsManager.HasSubscriptionsForEvent(eventName))
+ {
+ using (var scope = _autofac.BeginLifetimeScope(AUTOFAC_SCOPE_NAME))
+ {
+ var subscriptions = _subsManager.GetHandlersForEvent(eventName);
+ foreach (var subscription in subscriptions)
+ {
+ if (subscription.IsDynamic)
+ {
+ var handler = scope.ResolveOptional(subscription.HandlerType) as IDynamicIntegrationEventHandler;
+ if (handler == null) continue;
+ dynamic eventData = JObject.Parse(message);
+
+ await Task.Yield();
+ await handler.Handle(eventData);
+ }
+ else
+ {
+ var handler = scope.ResolveOptional(subscription.HandlerType);
+ if (handler == null) continue;
+ var eventType = _subsManager.GetEventTypeByName(eventName);
+ var integrationEvent = JsonConvert.DeserializeObject(message, eventType);
+ var concreteType = typeof(IIntegrationEventHandler<>).MakeGenericType(eventType);
+
+ await Task.Yield();
+ await (Task)concreteType.GetMethod("Handle").Invoke(handler, new object[] { integrationEvent });
+ }
+ }
+ }
+ }
+ else
+ {
+ _logger.LogWarning("No subscription for Kafka event: {EventName}", eventName);
+ }
+ }
+
+ private void ConsumerClient_OnConsumeError(IConsumer consumer, Error e)
+ {
+ _logger.LogError("An error occurred during connect kafka:" + e.Reason);
+ }
+ }
+}
diff --git a/Blog.Core.EventBus/EventBusKafka/KafkaOptions.cs b/Blog.Core.EventBus/EventBusKafka/KafkaOptions.cs
new file mode 100644
index 00000000..637da2aa
--- /dev/null
+++ b/Blog.Core.EventBus/EventBusKafka/KafkaOptions.cs
@@ -0,0 +1,28 @@
+
+
+namespace Blog.Core.EventBus
+{
+ ///
+ /// Kafka 配置项
+ ///
+ public class KafkaOptions
+ {
+ public int ConnectionPoolSize { get; set; } = 10;
+ ///
+ /// 地址
+ ///
+ public string Servers { get; set; }
+ ///
+ /// 主题
+ ///
+ public string Topic { get; set; }
+ ///
+ /// 消费者组Id
+ ///
+ public string GroupId { get; set; }
+ ///
+ /// 主题分区
+ ///
+ public int NumPartitions { get; set; }
+ }
+}
diff --git a/Blog.Core.EventBus/EventBusKafka/ProtobufTransfer.cs b/Blog.Core.EventBus/EventBusKafka/ProtobufTransfer.cs
new file mode 100644
index 00000000..c365db12
--- /dev/null
+++ b/Blog.Core.EventBus/EventBusKafka/ProtobufTransfer.cs
@@ -0,0 +1,32 @@
+using System;
+using System.IO;
+namespace Blog.Core.EventBus
+{
+ public class Protobuf
+ {
+ ///
+ /// Protobuf 反序列化
+ ///
+ public static T Deserialize(ReadOnlySpan data)
+ {
+ Stream stream = new MemoryStream(data.ToArray());
+ var info = ProtoBuf.Serializer.Deserialize(stream);
+ return info;
+ }
+ ///
+ /// 通过Protobuf 转字节
+ ///
+ public static byte[] Serialize(T data)
+ {
+ byte[] datas;
+ using (var stream = new MemoryStream())
+ {
+ ProtoBuf.Serializer.Serialize(stream, data);
+ datas = stream.ToArray();
+ }
+ return datas;
+
+
+ }
+ }
+}
diff --git a/Blog.Core.Extensions/ServiceExtensions/EventBusSetup.cs b/Blog.Core.Extensions/ServiceExtensions/EventBusSetup.cs
index 2d74c3ee..197803c1 100644
--- a/Blog.Core.Extensions/ServiceExtensions/EventBusSetup.cs
+++ b/Blog.Core.Extensions/ServiceExtensions/EventBusSetup.cs
@@ -18,41 +18,47 @@ public static void AddEventBusSetup(this IServiceCollection services)
{
if (services == null) throw new ArgumentNullException(nameof(services));
- if (Appsettings.app(new string[] { "RabbitMQ", "Enabled" }).ObjToBool() && Appsettings.app(new string[] { "EventBus", "Enabled" }).ObjToBool())
+ if (Appsettings.app(new string[] { "EventBus", "Enabled" }).ObjToBool())
{
var subscriptionClientName = Appsettings.app(new string[] { "EventBus", "SubscriptionClientName" });
-
services.AddSingleton();
services.AddTransient();
-
- services.AddSingleton(sp =>
+ if (Appsettings.app(new string[] { "RabbitMQ", "Enabled" }).ObjToBool())
{
- var rabbitMQPersistentConnection = sp.GetRequiredService();
- var iLifetimeScope = sp.GetRequiredService();
- var logger = sp.GetRequiredService>();
- var eventBusSubcriptionsManager = sp.GetRequiredService();
-
- var retryCount = 5;
- if (!string.IsNullOrEmpty(Appsettings.app(new string[] { "RabbitMQ", "RetryCount" })))
+ services.AddSingleton(sp =>
{
- retryCount = int.Parse(Appsettings.app(new string[] { "RabbitMQ", "RetryCount" }));
- }
+ var rabbitMQPersistentConnection = sp.GetRequiredService();
+ var iLifetimeScope = sp.GetRequiredService();
+ var logger = sp.GetRequiredService>();
+ var eventBusSubcriptionsManager = sp.GetRequiredService();
- return new EventBusRabbitMQ(rabbitMQPersistentConnection, logger, iLifetimeScope, eventBusSubcriptionsManager, subscriptionClientName, retryCount);
- });
+ var retryCount = 5;
+ if (!string.IsNullOrEmpty(Appsettings.app(new string[] { "RabbitMQ", "RetryCount" })))
+ {
+ retryCount = int.Parse(Appsettings.app(new string[] { "RabbitMQ", "RetryCount" }));
+ }
+
+ return new EventBusRabbitMQ(rabbitMQPersistentConnection, logger, iLifetimeScope, eventBusSubcriptionsManager, subscriptionClientName, retryCount);
+ });
+ }
+ if(Appsettings.app(new string[] { "Kafka", "Enabled" }).ObjToBool())
+ {
+ services.AddHostedService();
+ services.AddSingleton();
+ }
}
}
public static void ConfigureEventBus(this IApplicationBuilder app)
{
- if (Appsettings.app(new string[] { "RabbitMQ", "Enabled" }).ObjToBool() && Appsettings.app(new string[] { "EventBus", "Enabled" }).ObjToBool())
+ if (Appsettings.app(new string[] { "EventBus", "Enabled" }).ObjToBool())
{
var eventBus = app.ApplicationServices.GetRequiredService();
- eventBus.Subscribe();
+ eventBus.Subscribe();
}
}
}
diff --git a/Blog.Core.Extensions/ServiceExtensions/KafkaSetup.cs b/Blog.Core.Extensions/ServiceExtensions/KafkaSetup.cs
new file mode 100644
index 00000000..79e60b94
--- /dev/null
+++ b/Blog.Core.Extensions/ServiceExtensions/KafkaSetup.cs
@@ -0,0 +1,26 @@
+using Blog.Core.Common;
+using Blog.Core.EventBus;
+using Microsoft.Extensions.Configuration;
+using Microsoft.Extensions.DependencyInjection;
+using Microsoft.Extensions.Logging;
+using System;
+
+namespace Blog.Core.Extensions
+{
+ ///
+ /// 注入Kafka相关配置
+ ///
+ public static class KafkaSetup
+ {
+ public static void AddKafkaSetup(this IServiceCollection services,IConfiguration configuration)
+ {
+ if (services == null) throw new ArgumentNullException(nameof(services));
+
+ if (Appsettings.app(new string[] { "Kafka", "Enabled" }).ObjToBool())
+ {
+ services.Configure(configuration.GetSection("kafka"));
+ services.AddSingleton();
+ }
+ }
+ }
+}
From 3bdedfd28da8cefee400572c7504c0611047ac90 Mon Sep 17 00:00:00 2001
From: ansonzhang <3143422472@qq.com>
Date: Tue, 24 Aug 2021 10:48:06 +0800
Subject: [PATCH 076/456] Update README.md
---
README.md | 1 +
1 file changed, 1 insertion(+)
diff --git a/README.md b/README.md
index 79020178..a83e2042 100644
--- a/README.md
+++ b/README.md
@@ -77,6 +77,7 @@ Blog.Core 开箱即用的企业级前后端分离【 .NET Core5.0 Api + Vue 2.x
- [x] 新增 - Nacos注册中心配置;
- [x] 新增 - ES 搜索配置;
- [x] 新增 - Apollo 配置;
+- [x] 新增 Kafka 消息队列,并配合实现EventBus ✨;
- [ ] 计划 - 数据部门权限;
微服务模块:
From 496970984f492d640eeb5a399155aa9a5d2e1351 Mon Sep 17 00:00:00 2001
From: anjoy8 <3143422472@qq.com>
Date: Tue, 24 Aug 2021 15:21:25 +0800
Subject: [PATCH 077/456] =?UTF-8?q?fix=EF=BC=9Achange=20port=20from=208081?=
=?UTF-8?q?=20->=209291?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
Blog.Core.Api/Dockerfile | 2 +-
Blog.Core.Api/Program.cs | 2 +-
Blog.Core.Api/Properties/launchSettings.json | 2 +-
Blog.Core.Api/appsettings.json | 6 +++---
Blog.Core.Api/wwwroot/CorsPost.html | 6 +++---
Blog.Core.Api/wwwroot/index.html | 4 ++--
Blog.Core.Build.bat | 2 +-
Blog.Core.Gateway/ocelot.Development.json | 2 +-
Blog.Core.Gateway/ocelot.json | 2 +-
Blog.Core.Publish.Docker.Jenkins.sh | 2 +-
Blog.Core.Publish.Docker.sh | 2 +-
Blog.Core.Tests/appsettings.json | 2 +-
Blog.Core.sln | 4 +++-
DockerBuild.bat | 18 ++++++++++++++++++
Dockerfile | 4 ++--
15 files changed, 40 insertions(+), 20 deletions(-)
create mode 100644 DockerBuild.bat
diff --git a/Blog.Core.Api/Dockerfile b/Blog.Core.Api/Dockerfile
index 2e25ef5a..43618077 100644
--- a/Blog.Core.Api/Dockerfile
+++ b/Blog.Core.Api/Dockerfile
@@ -37,5 +37,5 @@ RUN echo 'Asia/Shanghai' >/etc/timezone
#&& supervisord -c /etc/supervisord.conf
WORKDIR /app
COPY . .
-EXPOSE 8081
+EXPOSE 9291
ENTRYPOINT ["dotnet", "Blog.Core.Api.dll","-b","0.0.0.0"]
\ No newline at end of file
diff --git a/Blog.Core.Api/Program.cs b/Blog.Core.Api/Program.cs
index d405b821..9e416297 100644
--- a/Blog.Core.Api/Program.cs
+++ b/Blog.Core.Api/Program.cs
@@ -29,7 +29,7 @@ public static void Main(string[] args)
//接入Apollo配置中心
config.AddConfigurationApollo("appsettings.apollo.json");
})
- .UseUrls("http://*:8081")
+ .UseUrls("http://*:9291")
.ConfigureLogging((hostingContext, builder) =>
{
// 1.过滤掉系统默认的一些日志
diff --git a/Blog.Core.Api/Properties/launchSettings.json b/Blog.Core.Api/Properties/launchSettings.json
index 891d625b..9b02dcc0 100644
--- a/Blog.Core.Api/Properties/launchSettings.json
+++ b/Blog.Core.Api/Properties/launchSettings.json
@@ -15,7 +15,7 @@
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": ""
},
- "applicationUrl": "http://localhost:8081"
+ "applicationUrl": "http://localhost:9291"
},
"IIS Express": {
"commandName": "IISExpress",
diff --git a/Blog.Core.Api/appsettings.json b/Blog.Core.Api/appsettings.json
index 39c865db..c31755df 100644
--- a/Blog.Core.Api/appsettings.json
+++ b/Blog.Core.Api/appsettings.json
@@ -1,5 +1,5 @@
{
- "urls": "http://*:8081", //web服务端口,如果用IIS部署,把这个去掉
+ "urls": "http://*:9291", //web服务端口,如果用IIS部署,把这个去掉
"Logging": {
"LogLevel": {
"Default": "Information", //加入Default否则log4net本地写入不了日志
@@ -252,7 +252,7 @@
"ConsulSetting": {
"ServiceName": "BlogCoreService",
"ServiceIP": "localhost",
- "ServicePort": "8081",
+ "ServicePort": "9291",
"ServiceHealthCheck": "/healthcheck",
"ConsulAddress": "http://localhost:8500"
},
@@ -271,7 +271,7 @@
"Namespace": "public", // 命名空间
"ListenInterval": 10000, // 监听的频率
"ServiceName": "blog.Core.Api", // 服务名
- "Port": "8081", // 服务端口号
+ "Port": "9291", // 服务端口号
"RegisterEnabled": true // 是否直接注册nacos
},
"LogFiedOutPutConfigs": {
diff --git a/Blog.Core.Api/wwwroot/CorsPost.html b/Blog.Core.Api/wwwroot/CorsPost.html
index cf160d5c..8ebbf01a 100644
--- a/Blog.Core.Api/wwwroot/CorsPost.html
+++ b/Blog.Core.Api/wwwroot/CorsPost.html
@@ -15,13 +15,13 @@
$(document).ready(function () {
$("#jsonp").click(function () {
- $.getJSON("http://localhost:8081/api/Login/jsonp?callBack=?", function (data) {
+ $.getJSON("http://localhost:9291/api/Login/jsonp?callBack=?", function (data) {
$("#data-jsonp").html("数据: " + data.value);
});
});
$("#cors").click(function () {
- $.get("http://localhost:8081/api/Login/Token", function (data, status) {
+ $.get("http://localhost:9291/api/Login/Token", function (data, status) {
console.log(data);
$("#status-cors").html("状态: " + status);
$("#data-cors").html("数据: " + data? data.token:"失败");
@@ -43,7 +43,7 @@
};
$.ajax({
type: 'post',
- url: 'http://localhost:8081/api/Values',
+ url: 'http://localhost:9291/api/Values',
contentType: 'application/json',
data: JSON.stringify(postdata),
success: function (data, status) {
diff --git a/Blog.Core.Api/wwwroot/index.html b/Blog.Core.Api/wwwroot/index.html
index cf47942a..2e1be63e 100644
--- a/Blog.Core.Api/wwwroot/index.html
+++ b/Blog.Core.Api/wwwroot/index.html
@@ -18,7 +18,7 @@
"bRemark": "string"
};
$.ajax({
- url: "http://localhost:8081/api/Values",
+ url: "http://localhost:9291/api/Values",
type: "POST",
contentType: "application/json; charset=utf-8",
data: JSON.stringify(postdata),
@@ -34,7 +34,7 @@
-
diff --git a/Blog.Core.Build.bat b/Blog.Core.Build.bat
index c6163e9a..632e841c 100644
--- a/Blog.Core.Build.bat
+++ b/Blog.Core.Build.bat
@@ -2,7 +2,7 @@ git pull
@echo off
-for /f "tokens=5" %%i in ('netstat -aon ^| findstr ":8081"') do (
+for /f "tokens=5" %%i in ('netstat -aon ^| findstr ":9291"') do (
set n=%%i
)
taskkill /f /pid %n%
diff --git a/Blog.Core.Gateway/ocelot.Development.json b/Blog.Core.Gateway/ocelot.Development.json
index 3889dfb6..88475e25 100644
--- a/Blog.Core.Gateway/ocelot.Development.json
+++ b/Blog.Core.Gateway/ocelot.Development.json
@@ -16,7 +16,7 @@
"DownstreamHostAndPorts": [
{
"Host": "localhost",
- "Port": 8081
+ "Port": 9291
}
]
},
diff --git a/Blog.Core.Gateway/ocelot.json b/Blog.Core.Gateway/ocelot.json
index 362529e1..c9612a60 100644
--- a/Blog.Core.Gateway/ocelot.json
+++ b/Blog.Core.Gateway/ocelot.json
@@ -16,7 +16,7 @@
"DownstreamHostAndPorts": [
{
"Host": "localhost",
- "Port": 8081
+ "Port": 9291
}
]
},
diff --git a/Blog.Core.Publish.Docker.Jenkins.sh b/Blog.Core.Publish.Docker.Jenkins.sh
index cc953102..42f074a7 100644
--- a/Blog.Core.Publish.Docker.Jenkins.sh
+++ b/Blog.Core.Publish.Docker.Jenkins.sh
@@ -17,4 +17,4 @@ chmod 777 StopContainerImg.sh
./StopContainerImg.sh apkcontainer laozhangisphi/apkimg
docker build -t laozhangisphi/apkimg .
-docker run --name=apkcontainer -d -v /data/blogcore/appsettings.json:/app/appsettings.json -v /data/blogcore/Log/:/app/Log -v /etc/localtime:/etc/localtime -it -p 8081:8081 laozhangisphi/apkimg
\ No newline at end of file
+docker run --name=apkcontainer -d -v /data/blogcore/appsettings.json:/app/appsettings.json -v /data/blogcore/Log/:/app/Log -v /etc/localtime:/etc/localtime -it -p 9291:9291 laozhangisphi/apkimg
\ No newline at end of file
diff --git a/Blog.Core.Publish.Docker.sh b/Blog.Core.Publish.Docker.sh
index d4ae6246..eadc23c4 100644
--- a/Blog.Core.Publish.Docker.sh
+++ b/Blog.Core.Publish.Docker.sh
@@ -13,6 +13,6 @@ cd /home/Blog.Core/.PublishFiles
# 编译镜像
docker build -t laozhangisphi/apkimg .
# 生成容器
-docker run --name=apkcontainer -d -v /etc/localtime:/etc/localtime -it -p 8081:8081 laozhangisphi/apkimg
+docker run --name=apkcontainer -d -v /etc/localtime:/etc/localtime -it -p 9291:9291 laozhangisphi/apkimg
# 启动容器
docker start apkcontainer
diff --git a/Blog.Core.Tests/appsettings.json b/Blog.Core.Tests/appsettings.json
index a1edb353..95a95f16 100644
--- a/Blog.Core.Tests/appsettings.json
+++ b/Blog.Core.Tests/appsettings.json
@@ -197,7 +197,7 @@
"ConsulSetting": {
"ServiceName": "BlogCoreService",
"ServiceIP": "localhost",
- "ServicePort": "8081",
+ "ServicePort": "9291",
"ServiceHealthCheck": "/healthcheck",
"ConsulAddress": "http://localhost:8500"
}
diff --git a/Blog.Core.sln b/Blog.Core.sln
index 1e86d304..e587ddae 100644
--- a/Blog.Core.sln
+++ b/Blog.Core.sln
@@ -31,6 +31,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "SolutionItems", "SolutionIt
Blog.Core.Publish.Linux.sh = Blog.Core.Publish.Linux.sh
codecov.yml = codecov.yml
CreateYourProject.bat = CreateYourProject.bat
+ DockerBuild.bat = DockerBuild.bat
+ Dockerfile = Dockerfile
nuget.config = nuget.config
README.md = README.md
EndProjectSection
@@ -53,7 +55,7 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Blog.Core.ConsoleApp", "Blo
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Blog.Core.Gateway", "Blog.Core.Gateway\Blog.Core.Gateway.csproj", "{A11C0DF2-1E13-4EED-BA49-44A57136B189}"
EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Blog.Core.Serilog.Es", "Blog.Core.Serilog.Es\Blog.Core.Serilog.Es.csproj", "{52AFAB53-D1CA-4014-8B63-3550FDCDA6E1}"
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Blog.Core.Serilog.Es", "Blog.Core.Serilog.Es\Blog.Core.Serilog.Es.csproj", "{52AFAB53-D1CA-4014-8B63-3550FDCDA6E1}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
diff --git a/DockerBuild.bat b/DockerBuild.bat
new file mode 100644
index 00000000..7617488c
--- /dev/null
+++ b/DockerBuild.bat
@@ -0,0 +1,18 @@
+echo off
+echo "Press B to build images, P to push to registry, any other key to cancel"
+set /p op= :
+if "%op%"=="B" goto build
+if "%op%"=="P" goto push
+exit
+
+:build
+docker rmi laozhangisphi/apkimg
+docker build -f "Dockerfile" --force-rm -t laozhangisphi/apkimg .
+goto end
+
+:push
+docker push laozhangisphi/apkimg
+goto end
+
+:end
+pause
\ No newline at end of file
diff --git a/Dockerfile b/Dockerfile
index e6719f2e..7445e602 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -1,7 +1,7 @@
#See https://aka.ms/containerfastmode to understand how Visual Studio uses this Dockerfile to build your images for faster debugging.
#这种模式是直接在构建镜像的内部编译发布dotnet项目。
-#注意下容器内输出端口是8081
+#注意下容器内输出端口是9291
#如果你想先手动dotnet build成可执行的二进制文件,然后再构建镜像,请看.Api层下的dockerfile。
@@ -31,5 +31,5 @@ RUN dotnet publish "Blog.Core.Api.csproj" -c Release -o /app/publish
FROM base AS final
WORKDIR /app
COPY --from=publish /app/publish .
-EXPOSE 8081
+EXPOSE 9291
ENTRYPOINT ["dotnet", "Blog.Core.Api.dll"]
\ No newline at end of file
From dd02d21f1a046e03c537afeeac798b31dd7fed18 Mon Sep 17 00:00:00 2001
From: anjoy8 <3143422472@qq.com>
Date: Tue, 24 Aug 2021 16:11:10 +0800
Subject: [PATCH 078/456] Update README.md
---
.docs/contents/Update/README.md | 16 ++++++++++++++++
1 file changed, 16 insertions(+)
diff --git a/.docs/contents/Update/README.md b/.docs/contents/Update/README.md
index a80f7cb1..870f98ec 100644
--- a/.docs/contents/Update/README.md
+++ b/.docs/contents/Update/README.md
@@ -2,6 +2,22 @@
## 更新日志
+### 2021-08-21
+
+重要功能增加:项目增加 `Apollo` 配置中心;
+
+### 2021-08-03
+
+重要功能增加:项目增加 `ES` 搜索,增加 `Serilog` 使用 `tcp` 的方式自定义格式化,写入 `elk` 的实现;
+
+### 2021-06-28
+
+功能增加:项目增加 `nacos` 配置,支持将项目注册到 `nacos` 服务中心,搭建微服务之子服务;
+
+### 2021-06-04
+
+小功能更新:执行的时候,将 `Sql` 日志输出到控制台,方便查看,支持配置文件关闭;
+
### 2021-05-01
组件更新:多项日志中间件,由自写组件,转为使用`serilog`组件记录日志;
From ae995b3e64fd88c348a5f6ab9dfed2e49720dd03 Mon Sep 17 00:00:00 2001
From: anjoy8 <3143422472@qq.com>
Date: Tue, 24 Aug 2021 17:30:18 +0800
Subject: [PATCH 079/456] fix: change port in doc
---
.docs/contents/PressureTest/README.md | 2 +-
.docs/contents/guide/cheat-sheet.md | 4 ++--
.docs/contents/guide/function-sheet.md | 12 ++++++------
.docs/contents/guide/getting-started.md | 4 ++--
4 files changed, 11 insertions(+), 11 deletions(-)
diff --git a/.docs/contents/PressureTest/README.md b/.docs/contents/PressureTest/README.md
index 9798e89a..af2a2e93 100644
--- a/.docs/contents/PressureTest/README.md
+++ b/.docs/contents/PressureTest/README.md
@@ -20,7 +20,7 @@
本地发布后的 `windows` 环境,直接用 `kestrel` 启动。
线程数:100
循环数:1000
-HTTP默认值:协议:`http`;服务器或IP:`localhost`;端口号:`8081`;
+HTTP默认值:协议:`http`;服务器或IP:`localhost`;端口号:`9291`;
HTTP请求:方法:GET;路径:`/api/blog/ApacheTestUpdate`
HTTP信息请求管理器:无
响应断言:无
diff --git a/.docs/contents/guide/cheat-sheet.md b/.docs/contents/guide/cheat-sheet.md
index c99b5398..36f95e36 100644
--- a/.docs/contents/guide/cheat-sheet.md
+++ b/.docs/contents/guide/cheat-sheet.md
@@ -158,7 +158,7 @@ services.AddIpPolicyRateLimitSetup(Configuration);
```
-然后在 `IdentityServer4` 项目中,做指定的修改,配置 `8081` 的回调地址:
+然后在 `IdentityServer4` 项目中,做指定的修改,配置 `9291` 的回调地址:
```
new Client {
@@ -171,7 +171,7 @@ services.AddIpPolicyRateLimitSetup(Configuration);
{
"http://vueadmin.neters.club/callback",
// 这里要配置回调地址
- "http://localhost:8081/oauth2-redirect.html"
+ "http://localhost:9291/oauth2-redirect.html"
},
PostLogoutRedirectUris = { "http://vueadmin.neters.club" },
AllowedCorsOrigins = { "http://vueadmin.neters.club" },
diff --git a/.docs/contents/guide/function-sheet.md b/.docs/contents/guide/function-sheet.md
index 2a902c55..d81ad13f 100644
--- a/.docs/contents/guide/function-sheet.md
+++ b/.docs/contents/guide/function-sheet.md
@@ -212,7 +212,7 @@ http {
#access_log logs/host.access.log main;
location / {
root html;
- proxy_pass http://localhost:8081;
+ proxy_pass http://localhost:9291;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection keep-alive;
@@ -253,7 +253,7 @@ http {
location /api/ {
rewrite ^.+apb/?(.*)$ /$1 break;
include uwsgi_params;
- proxy_pass http://localhost:8081;
+ proxy_pass http://localhost:9291;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
#proxy_set_header Connection "upgrade";
@@ -265,7 +265,7 @@ http {
location /api2/ {
rewrite ^.+apb/?(.*)$ /$1 break;
include uwsgi_params;
- proxy_pass http://localhost:8081;
+ proxy_pass http://localhost:9291;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
@@ -276,7 +276,7 @@ http {
location /images/ {
include uwsgi_params;
- proxy_pass http://localhost:8081;
+ proxy_pass http://localhost:9291;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
#proxy_set_header Connection "upgrade";
@@ -361,7 +361,7 @@ http {
location /api {
rewrite ^.+apb/?(.*)$ /$1 break;
include uwsgi_params;
- proxy_pass http://localhost:8081;
+ proxy_pass http://localhost:9291;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
@@ -369,7 +369,7 @@ http {
location /images {
include uwsgi_params;
- proxy_pass http://localhost:8081;
+ proxy_pass http://localhost:9291;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
diff --git a/.docs/contents/guide/getting-started.md b/.docs/contents/guide/getting-started.md
index 8da8bb70..9c4f6b0d 100644
--- a/.docs/contents/guide/getting-started.md
+++ b/.docs/contents/guide/getting-started.md
@@ -14,7 +14,7 @@ Gitee(国内) 下载 [https://gitee.com/laozhangIsPhi/Blog.Core](https://git
## 编译与运行
1、拿到项目后,双击 `Blog.Core.sln` 解决方案;
2、首先 `F6` 编译,看是否有错误;
-3、然后 `F5` 运行,调起 `8081` 端口,浏览器查看效果;
+3、然后 `F5` 运行,调起 `9291` 端口,浏览器查看效果;
4、因为系统默认的是 `sqlite` 数据库,如果你想换其他数据库,请看下边;
5、注意:本系统是直接自动生成数据库和数据的,不用手动创建数据库;
@@ -78,7 +78,7 @@ Gitee(国内) 下载 [https://gitee.com/laozhangIsPhi/Blog.Core](https://git
```
## 如何配置项目端口号
-1、在 `Blog.Core` 层下的 `program.cs` 文件中,将 `8081`端口,修改为自己想要的端口号;
+1、在 `Blog.Core` 层下的 `program.cs` 文件中,将 `9291`端口,修改为自己想要的端口号;
2、或者在 `launchSettings.json` 中设置(`注意,如果仅仅修改这里,publish后,端口访问无效`);
## 如何项目重命名
From b0d81008c8d15180a13f25b21be8fe50b3465e0d Mon Sep 17 00:00:00 2001
From: anjoy8 <3143422472@qq.com>
Date: Tue, 24 Aug 2021 17:45:00 +0800
Subject: [PATCH 080/456] Update README.md
---
.docs/contents/guide/README.md | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/.docs/contents/guide/README.md b/.docs/contents/guide/README.md
index 209444c4..afd5d25b 100644
--- a/.docs/contents/guide/README.md
+++ b/.docs/contents/guide/README.md
@@ -5,6 +5,12 @@ Blog.Core 是一个开箱即用的企业级权限管理应用框架。
采用最新的前后端完全分离技术【 ASP.NET Core Api 5.0 + Vue 2.x 】。
并结合 `IdentityServer4` ,可快速解决多客户端和多资源服务的统一认证与鉴权的问题。
+## 其他资料
+
+博客园,早期架构搭建:[博客园](https://www.cnblogs.com/laozhang-is-phi/p/9495618.html)
+公众号,后期调整:[文章](https://mvp.neters.club/MVP_aspnetcore_2020/2020)
+视频:[B站](https://www.bilibili.com/video/BV1vC4y1p7Za)
+
### 为什么选择 ASPNET.Core
1、【开源】`ASPNET.NET Core` 是由 `Microsoft` 和 `.NET` 社区在 `GitHub` 上开源并维护的一个跨平台(支持 Windows、macOS 和 Linux)的新一代高性能框架,
From 5db61d9aafbc3027285b9f49bb6e10d1bd3a8c5d Mon Sep 17 00:00:00 2001
From: anjoy8 <3143422472@qq.com>
Date: Tue, 24 Aug 2021 18:34:59 +0800
Subject: [PATCH 081/456] Update README.md
---
.docs/contents/guide/README.md | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/.docs/contents/guide/README.md b/.docs/contents/guide/README.md
index afd5d25b..30950e0c 100644
--- a/.docs/contents/guide/README.md
+++ b/.docs/contents/guide/README.md
@@ -12,6 +12,14 @@ Blog.Core 是一个开箱即用的企业级权限管理应用框架。
视频:[B站](https://www.bilibili.com/video/BV1vC4y1p7Za)
+## 配套站点
+
+本资源服务器,配合多个项目,构建前后端权限一体化平台,前端用 `VUE` 框架。
+前端-客户端:[预览](https://vueadmin.neters.club/)、[源码](https://github.com/anjoy8/Blog.Admin)
+前端-管理后台:[预览](http://vueblog.neters.club/)、[源码](https://github.com/anjoy8/Blog.Vue)
+认证平台:[预览](https://ids.neters.club/)、[源码](https://github.com/anjoy8/Blog.IdentityServer)
+
+
### 为什么选择 ASPNET.Core
1、【开源】`ASPNET.NET Core` 是由 `Microsoft` 和 `.NET` 社区在 `GitHub` 上开源并维护的一个跨平台(支持 Windows、macOS 和 Linux)的新一代高性能框架,
拥有十分广泛的社区与支持者,可用于构建web应用、物联网IOT应用和移动端应用。
From 801dba60094e703abec82e1002f8474ff18b6e45 Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Wed, 25 Aug 2021 15:36:23 +0000
Subject: [PATCH 082/456] Bump Microsoft.AspNetCore.Authentication.JwtBearer
Bumps [Microsoft.AspNetCore.Authentication.JwtBearer](https://github.com/aspnet/AspNetCore) from 3.1.9 to 3.1.18.
- [Release notes](https://github.com/aspnet/AspNetCore/releases)
- [Commits](https://github.com/aspnet/AspNetCore/compare/v3.1.9...v3.1.18)
---
updated-dependencies:
- dependency-name: Microsoft.AspNetCore.Authentication.JwtBearer
dependency-type: direct:production
...
Signed-off-by: dependabot[bot]
---
Blog.Core.Extensions/Blog.Core.Extensions.csproj | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/Blog.Core.Extensions/Blog.Core.Extensions.csproj b/Blog.Core.Extensions/Blog.Core.Extensions.csproj
index 90d5ed97..a4dc8775 100644
--- a/Blog.Core.Extensions/Blog.Core.Extensions.csproj
+++ b/Blog.Core.Extensions/Blog.Core.Extensions.csproj
@@ -11,7 +11,7 @@
-
+
From 13d285026b9aa38efc9d7456ac934ea269d2f644 Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Mon, 30 Aug 2021 02:42:46 +0000
Subject: [PATCH 083/456] Bump Microsoft.AspNetCore.Authentication.JwtBearer in
/Blog.Core.Gateway
Bumps [Microsoft.AspNetCore.Authentication.JwtBearer](https://github.com/dotnet/aspnetcore) from 5.0.0 to 5.0.9.
- [Release notes](https://github.com/dotnet/aspnetcore/releases)
- [Commits](https://github.com/dotnet/aspnetcore/compare/v5.0.0...v5.0.9)
---
updated-dependencies:
- dependency-name: Microsoft.AspNetCore.Authentication.JwtBearer
dependency-type: direct:production
...
Signed-off-by: dependabot[bot]
---
Blog.Core.Extensions/Blog.Core.Extensions.csproj | 2 +-
Blog.Core.Gateway/Blog.Core.Gateway.csproj | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/Blog.Core.Extensions/Blog.Core.Extensions.csproj b/Blog.Core.Extensions/Blog.Core.Extensions.csproj
index a4dc8775..76ce50ee 100644
--- a/Blog.Core.Extensions/Blog.Core.Extensions.csproj
+++ b/Blog.Core.Extensions/Blog.Core.Extensions.csproj
@@ -11,7 +11,7 @@
-
+
diff --git a/Blog.Core.Gateway/Blog.Core.Gateway.csproj b/Blog.Core.Gateway/Blog.Core.Gateway.csproj
index 84713355..0dba222a 100644
--- a/Blog.Core.Gateway/Blog.Core.Gateway.csproj
+++ b/Blog.Core.Gateway/Blog.Core.Gateway.csproj
@@ -14,7 +14,7 @@
-
+
From c27abebe7337ab094b9c8cfb44dce2d569a7542a Mon Sep 17 00:00:00 2001
From: anjoy8 <3143422472@qq.com>
Date: Tue, 31 Aug 2021 11:49:37 +0800
Subject: [PATCH 084/456] Update CreateYourProject.bat
---
CreateYourProject.bat | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/CreateYourProject.bat b/CreateYourProject.bat
index 43a2a429..8f5b5ca7 100644
--- a/CreateYourProject.bat
+++ b/CreateYourProject.bat
@@ -3,9 +3,9 @@ echo "if u install template error,pls use:>>dotnet new -i .template.config\Blog.
color 3
-dotnet new -i Blog.Core.Webapi.Template::2.5.3
+dotnet new -i Blog.Core.Webapi.Template::2.5.4
-set /p OP=Please set your project name(for example:Baidu.Api):
+set /p OP=Please set your project name(for example:BlogMicService):
md .1YourProject
From 50947feb53ca6080347667a809f271a98b4b158e Mon Sep 17 00:00:00 2001
From: hudingwen <765472804@qq.com>
Date: Thu, 2 Sep 2021 15:23:51 +0800
Subject: [PATCH 085/456] merge
---
.docs/contents/PressureTest/README.md | 2 +-
.docs/contents/Update/README.md | 16 +
.docs/contents/guide/README.md | 14 +
.docs/contents/guide/cheat-sheet.md | 4 +-
.docs/contents/guide/function-sheet.md | 12 +-
.docs/contents/guide/getting-started.md | 4 +-
Blog.Core.Api/Controllers/BlogController.cs | 20 +-
Blog.Core.Api/Controllers/LoginController.cs | 4 +-
.../Controllers/MonitorController.cs | 38 +-
Blog.Core.Api/Controllers/NacosController.cs | 2 +-
Blog.Core.Api/Controllers/ValuesController.cs | 23 ++
Blog.Core.Api/Dockerfile | 2 +-
Blog.Core.Api/Program.cs | 5 +-
Blog.Core.Api/Properties/launchSettings.json | 4 +-
Blog.Core.Api/Startup.cs | 1 +
Blog.Core.Api/appsettings.apollo.json | 18 +
Blog.Core.Api/appsettings.json | 23 +-
Blog.Core.Api/wwwroot/CorsPost.html | 6 +-
Blog.Core.Api/wwwroot/index.html | 4 +-
Blog.Core.Build.bat | 2 +-
Blog.Core.Common/Helper/JsonConfigUtils.cs | 1 -
Blog.Core.Common/LogHelper/LogLock.cs | 41 ++-
.../LogHelper/Seri/SerilogServer.cs | 9 +-
Blog.Core.EventBus/Blog.Core.EventBus.csproj | 2 +
.../EventBusKafka/EventBusKafka.cs | 118 +++++++
.../EventBusKafka/IKafkaConnectionPool.cs | 25 ++
.../EventBusKafka/KafkaConnectionPool.cs | 79 +++++
.../EventBusKafka/KafkaConsumerHostService.cs | 162 +++++++++
.../EventBusKafka/KafkaOptions.cs | 28 ++
.../EventBusKafka/ProtobufTransfer.cs | 32 ++
Blog.Core.Extensions/Apollo/ApolloOptions.cs | 27 ++
.../Apollo/ConfigurationBuilderExtensions.cs | 84 +++++
.../Blog.Core.Extensions.csproj | 4 +-
.../Middlewares/IPLogMildd.cs | 35 +-
.../NacosListenConfigurationTask.cs | 3 +-
.../NacosConfig/NacosListenNamingTask.cs | 4 +-
.../Redis/RedisBasketRepository.cs | 12 +-
.../Redis/RedisCacheManager.cs | 12 +-
.../ServiceExtensions/EventBusSetup.cs | 40 ++-
.../ServiceExtensions/KafkaSetup.cs | 26 ++
.../ServiceExtensions/NacosSetup.cs | 6 +-
Blog.Core.Gateway/Blog.Core.Gateway.csproj | 2 +-
.../Controllers/UserController.cs | 1 -
Blog.Core.Gateway/Startup.cs | 2 -
Blog.Core.Gateway/ocelot.Development.json | 2 +-
Blog.Core.Gateway/ocelot.json | 2 +-
Blog.Core.Publish.Docker.Jenkins.sh | 2 +-
Blog.Core.Publish.Docker.sh | 2 +-
.../AppSettingsFileNameConfig.cs | 30 ++
.../Blog.Core.Serilog.Es.csproj | 17 +
.../Formatters/JsonConfigUtils.cs | 66 ++++
.../Formatters/LogConfigRootDTO.cs | 26 ++
.../Formatters/LogstashJsonFormatter.cs | 152 ++++++++
.../HttpInfo/HttpContextProvider.cs | 20 ++
Blog.Core.Serilog.Es/HttpInfo/ParamsHelper.cs | 82 +++++
.../NetworkLoggerConfigurationExtensions.cs | 102 ++++++
Blog.Core.Serilog.Es/Sinks/TCP/TCPSink.cs | 44 +++
.../Sinks/TCP/TCPSocketWriter.cs | 325 ++++++++++++++++++
Blog.Core.Serilog.Es/Sinks/UDP/UDPSink.cs | 42 +++
Blog.Core.Tests/appsettings.json | 2 +-
Blog.Core.sln | 8 +
CreateYourProject.bat | 4 +-
DockerBuild.bat | 18 +
Dockerfile | 4 +-
README.md | 17 +-
65 files changed, 1815 insertions(+), 111 deletions(-)
create mode 100644 Blog.Core.Api/appsettings.apollo.json
create mode 100644 Blog.Core.EventBus/EventBusKafka/EventBusKafka.cs
create mode 100644 Blog.Core.EventBus/EventBusKafka/IKafkaConnectionPool.cs
create mode 100644 Blog.Core.EventBus/EventBusKafka/KafkaConnectionPool.cs
create mode 100644 Blog.Core.EventBus/EventBusKafka/KafkaConsumerHostService.cs
create mode 100644 Blog.Core.EventBus/EventBusKafka/KafkaOptions.cs
create mode 100644 Blog.Core.EventBus/EventBusKafka/ProtobufTransfer.cs
create mode 100644 Blog.Core.Extensions/Apollo/ApolloOptions.cs
create mode 100644 Blog.Core.Extensions/Apollo/ConfigurationBuilderExtensions.cs
create mode 100644 Blog.Core.Extensions/ServiceExtensions/KafkaSetup.cs
create mode 100644 Blog.Core.Serilog.Es/AppSettingsFileNameConfig.cs
create mode 100644 Blog.Core.Serilog.Es/Blog.Core.Serilog.Es.csproj
create mode 100644 Blog.Core.Serilog.Es/Formatters/JsonConfigUtils.cs
create mode 100644 Blog.Core.Serilog.Es/Formatters/LogConfigRootDTO.cs
create mode 100644 Blog.Core.Serilog.Es/Formatters/LogstashJsonFormatter.cs
create mode 100644 Blog.Core.Serilog.Es/HttpInfo/HttpContextProvider.cs
create mode 100644 Blog.Core.Serilog.Es/HttpInfo/ParamsHelper.cs
create mode 100644 Blog.Core.Serilog.Es/NetworkLoggerConfigurationExtensions.cs
create mode 100644 Blog.Core.Serilog.Es/Sinks/TCP/TCPSink.cs
create mode 100644 Blog.Core.Serilog.Es/Sinks/TCP/TCPSocketWriter.cs
create mode 100644 Blog.Core.Serilog.Es/Sinks/UDP/UDPSink.cs
create mode 100644 DockerBuild.bat
diff --git a/.docs/contents/PressureTest/README.md b/.docs/contents/PressureTest/README.md
index 9798e89a..af2a2e93 100644
--- a/.docs/contents/PressureTest/README.md
+++ b/.docs/contents/PressureTest/README.md
@@ -20,7 +20,7 @@
本地发布后的 `windows` 环境,直接用 `kestrel` 启动。
线程数:100
循环数:1000
-HTTP默认值:协议:`http`;服务器或IP:`localhost`;端口号:`8081`;
+HTTP默认值:协议:`http`;服务器或IP:`localhost`;端口号:`9291`;
HTTP请求:方法:GET;路径:`/api/blog/ApacheTestUpdate`
HTTP信息请求管理器:无
响应断言:无
diff --git a/.docs/contents/Update/README.md b/.docs/contents/Update/README.md
index a80f7cb1..870f98ec 100644
--- a/.docs/contents/Update/README.md
+++ b/.docs/contents/Update/README.md
@@ -2,6 +2,22 @@
## 更新日志
+### 2021-08-21
+
+重要功能增加:项目增加 `Apollo` 配置中心;
+
+### 2021-08-03
+
+重要功能增加:项目增加 `ES` 搜索,增加 `Serilog` 使用 `tcp` 的方式自定义格式化,写入 `elk` 的实现;
+
+### 2021-06-28
+
+功能增加:项目增加 `nacos` 配置,支持将项目注册到 `nacos` 服务中心,搭建微服务之子服务;
+
+### 2021-06-04
+
+小功能更新:执行的时候,将 `Sql` 日志输出到控制台,方便查看,支持配置文件关闭;
+
### 2021-05-01
组件更新:多项日志中间件,由自写组件,转为使用`serilog`组件记录日志;
diff --git a/.docs/contents/guide/README.md b/.docs/contents/guide/README.md
index 209444c4..30950e0c 100644
--- a/.docs/contents/guide/README.md
+++ b/.docs/contents/guide/README.md
@@ -5,6 +5,20 @@ Blog.Core 是一个开箱即用的企业级权限管理应用框架。
采用最新的前后端完全分离技术【 ASP.NET Core Api 5.0 + Vue 2.x 】。
并结合 `IdentityServer4` ,可快速解决多客户端和多资源服务的统一认证与鉴权的问题。
+## 其他资料
+
+博客园,早期架构搭建:[博客园](https://www.cnblogs.com/laozhang-is-phi/p/9495618.html)
+公众号,后期调整:[文章](https://mvp.neters.club/MVP_aspnetcore_2020/2020)
+视频:[B站](https://www.bilibili.com/video/BV1vC4y1p7Za)
+
+
+## 配套站点
+
+本资源服务器,配合多个项目,构建前后端权限一体化平台,前端用 `VUE` 框架。
+前端-客户端:[预览](https://vueadmin.neters.club/)、[源码](https://github.com/anjoy8/Blog.Admin)
+前端-管理后台:[预览](http://vueblog.neters.club/)、[源码](https://github.com/anjoy8/Blog.Vue)
+认证平台:[预览](https://ids.neters.club/)、[源码](https://github.com/anjoy8/Blog.IdentityServer)
+
### 为什么选择 ASPNET.Core
1、【开源】`ASPNET.NET Core` 是由 `Microsoft` 和 `.NET` 社区在 `GitHub` 上开源并维护的一个跨平台(支持 Windows、macOS 和 Linux)的新一代高性能框架,
diff --git a/.docs/contents/guide/cheat-sheet.md b/.docs/contents/guide/cheat-sheet.md
index c99b5398..36f95e36 100644
--- a/.docs/contents/guide/cheat-sheet.md
+++ b/.docs/contents/guide/cheat-sheet.md
@@ -158,7 +158,7 @@ services.AddIpPolicyRateLimitSetup(Configuration);
```
-然后在 `IdentityServer4` 项目中,做指定的修改,配置 `8081` 的回调地址:
+然后在 `IdentityServer4` 项目中,做指定的修改,配置 `9291` 的回调地址:
```
new Client {
@@ -171,7 +171,7 @@ services.AddIpPolicyRateLimitSetup(Configuration);
{
"http://vueadmin.neters.club/callback",
// 这里要配置回调地址
- "http://localhost:8081/oauth2-redirect.html"
+ "http://localhost:9291/oauth2-redirect.html"
},
PostLogoutRedirectUris = { "http://vueadmin.neters.club" },
AllowedCorsOrigins = { "http://vueadmin.neters.club" },
diff --git a/.docs/contents/guide/function-sheet.md b/.docs/contents/guide/function-sheet.md
index 2a902c55..d81ad13f 100644
--- a/.docs/contents/guide/function-sheet.md
+++ b/.docs/contents/guide/function-sheet.md
@@ -212,7 +212,7 @@ http {
#access_log logs/host.access.log main;
location / {
root html;
- proxy_pass http://localhost:8081;
+ proxy_pass http://localhost:9291;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection keep-alive;
@@ -253,7 +253,7 @@ http {
location /api/ {
rewrite ^.+apb/?(.*)$ /$1 break;
include uwsgi_params;
- proxy_pass http://localhost:8081;
+ proxy_pass http://localhost:9291;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
#proxy_set_header Connection "upgrade";
@@ -265,7 +265,7 @@ http {
location /api2/ {
rewrite ^.+apb/?(.*)$ /$1 break;
include uwsgi_params;
- proxy_pass http://localhost:8081;
+ proxy_pass http://localhost:9291;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
@@ -276,7 +276,7 @@ http {
location /images/ {
include uwsgi_params;
- proxy_pass http://localhost:8081;
+ proxy_pass http://localhost:9291;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
#proxy_set_header Connection "upgrade";
@@ -361,7 +361,7 @@ http {
location /api {
rewrite ^.+apb/?(.*)$ /$1 break;
include uwsgi_params;
- proxy_pass http://localhost:8081;
+ proxy_pass http://localhost:9291;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
@@ -369,7 +369,7 @@ http {
location /images {
include uwsgi_params;
- proxy_pass http://localhost:8081;
+ proxy_pass http://localhost:9291;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
diff --git a/.docs/contents/guide/getting-started.md b/.docs/contents/guide/getting-started.md
index 8da8bb70..9c4f6b0d 100644
--- a/.docs/contents/guide/getting-started.md
+++ b/.docs/contents/guide/getting-started.md
@@ -14,7 +14,7 @@ Gitee(国内) 下载 [https://gitee.com/laozhangIsPhi/Blog.Core](https://git
## 编译与运行
1、拿到项目后,双击 `Blog.Core.sln` 解决方案;
2、首先 `F6` 编译,看是否有错误;
-3、然后 `F5` 运行,调起 `8081` 端口,浏览器查看效果;
+3、然后 `F5` 运行,调起 `9291` 端口,浏览器查看效果;
4、因为系统默认的是 `sqlite` 数据库,如果你想换其他数据库,请看下边;
5、注意:本系统是直接自动生成数据库和数据的,不用手动创建数据库;
@@ -78,7 +78,7 @@ Gitee(国内) 下载 [https://gitee.com/laozhangIsPhi/Blog.Core](https://git
```
## 如何配置项目端口号
-1、在 `Blog.Core` 层下的 `program.cs` 文件中,将 `8081`端口,修改为自己想要的端口号;
+1、在 `Blog.Core` 层下的 `program.cs` 文件中,将 `9291`端口,修改为自己想要的端口号;
2、或者在 `launchSettings.json` 中设置(`注意,如果仅仅修改这里,publish后,端口访问无效`);
## 如何项目重命名
diff --git a/Blog.Core.Api/Controllers/BlogController.cs b/Blog.Core.Api/Controllers/BlogController.cs
index 577e80bb..24860971 100644
--- a/Blog.Core.Api/Controllers/BlogController.cs
+++ b/Blog.Core.Api/Controllers/BlogController.cs
@@ -176,12 +176,20 @@ public MessageModel V2_Blogtest()
[Authorize]
public async Task> Post([FromBody] BlogArticle blogArticle)
{
- blogArticle.bCreateTime = DateTime.Now;
- blogArticle.bUpdateTime = DateTime.Now;
- blogArticle.IsDeleted = false;
- blogArticle.bcategory = "技术博文";
- var id = (await _blogArticleServices.Add(blogArticle));
- return id > 0 ? Success(id.ObjToString()) : Failed("添加失败");
+ if (blogArticle.btitle.Length > 5 && blogArticle.bcontent.Length > 50)
+ {
+
+ blogArticle.bCreateTime = DateTime.Now;
+ blogArticle.bUpdateTime = DateTime.Now;
+ blogArticle.IsDeleted = false;
+ blogArticle.bcategory = "技术博文";
+ var id = (await _blogArticleServices.Add(blogArticle));
+ return id > 0 ? Success(id.ObjToString()) : Failed("添加失败");
+ }
+ else
+ {
+ return Failed("文章标题不能少于5个字符,内容不能少于50个字符!");
+ }
}
diff --git a/Blog.Core.Api/Controllers/LoginController.cs b/Blog.Core.Api/Controllers/LoginController.cs
index 686c6431..e007cc6d 100644
--- a/Blog.Core.Api/Controllers/LoginController.cs
+++ b/Blog.Core.Api/Controllers/LoginController.cs
@@ -14,6 +14,7 @@
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
+
namespace Blog.Core.Controllers
{
@@ -61,10 +62,11 @@ public LoginController(ISysUserInfoServices sysUserInfoServices, IUserRoleServic
[Route("Token")]
public async Task> GetJwtStr(string name, string pass)
{
+
string jwtStr = string.Empty;
bool suc = false;
//这里就是用户登陆以后,通过数据库去调取数据,分配权限的操作
-
+
var user = await _sysUserInfoServices.GetUserRoleNameStr(name, MD5Helper.MD5Encrypt32(pass));
if (user != null)
{
diff --git a/Blog.Core.Api/Controllers/MonitorController.cs b/Blog.Core.Api/Controllers/MonitorController.cs
index b06af190..28ff3265 100644
--- a/Blog.Core.Api/Controllers/MonitorController.cs
+++ b/Blog.Core.Api/Controllers/MonitorController.cs
@@ -105,13 +105,43 @@ public MessageModel GetAccessApiByHour()
};
}
+ private List GetAccessLogsToday(IWebHostEnvironment environment)
+ {
+ List userAccessModels = new();
+ var accessLogs = LogLock.ReadLog(
+ Path.Combine(environment.ContentRootPath, "Log"), "RecordAccessLogs_", Encoding.UTF8, ReadType.PrefixLatest
+ ).ObjToString();
+ try
+ {
+ return JsonConvert.DeserializeObject>("[" + accessLogs + "]");
+ }
+ catch (Exception)
+ {
+ var accLogArr = accessLogs.Split("\n");
+ foreach (var item in accLogArr)
+ {
+ if (item.ObjToString() != "")
+ {
+ try
+ {
+ var accItem = JsonConvert.DeserializeObject(item.TrimEnd(','));
+ userAccessModels.Add(accItem);
+ }
+ catch (Exception)
+ {
+ }
+ }
+ }
+
+ }
+
+ return userAccessModels;
+ }
+
[HttpGet]
public MessageModel GetActiveUsers([FromServices] IWebHostEnvironment environment)
{
- var accessLogsToday = JsonConvert.DeserializeObject>("[" + LogLock.ReadLog(
- Path.Combine(environment.ContentRootPath, "Log"), "RecordAccessLogs_", Encoding.UTF8, ReadType.PrefixLatest
- ) + "]")
- .Where(d => d.BeginTime.ObjToDate() >= DateTime.Today);
+ var accessLogsToday = GetAccessLogsToday(environment).Where(d => d.BeginTime.ObjToDate() >= DateTime.Today);
var Logs = accessLogsToday.OrderByDescending(d => d.BeginTime).Take(50).ToList();
diff --git a/Blog.Core.Api/Controllers/NacosController.cs b/Blog.Core.Api/Controllers/NacosController.cs
index 8c824296..6aac936a 100644
--- a/Blog.Core.Api/Controllers/NacosController.cs
+++ b/Blog.Core.Api/Controllers/NacosController.cs
@@ -45,7 +45,7 @@ public NacosController(INacosNamingService nacosNamingService)
///
[HttpGet]
- public async Task> checkSystemStartFinish()
+ public MessageModel CheckSystemStartFinish()
{
//********************* 用当前接口做基本健康检查 确定 基础服务 数据库 缓存都已正常启动*****
// 然后再进行服务上线
diff --git a/Blog.Core.Api/Controllers/ValuesController.cs b/Blog.Core.Api/Controllers/ValuesController.cs
index 7399d8f7..002f1e62 100644
--- a/Blog.Core.Api/Controllers/ValuesController.cs
+++ b/Blog.Core.Api/Controllers/ValuesController.cs
@@ -1,4 +1,5 @@
using AutoMapper;
+using Blog.Core.Common;
using Blog.Core.Common.HttpContextUser;
using Blog.Core.Common.HttpRestSharp;
using Blog.Core.Common.WebApiClients.HttpApis;
@@ -12,6 +13,7 @@
using Blog.Core.Model.ViewModels;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
+using Microsoft.Extensions.Configuration;
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
@@ -349,5 +351,26 @@ public void Put(int id, [FromBody] string value)
public void Delete(int id)
{
}
+
+ #region Apollo 配置
+ ///
+ /// 测试接入Apollo获取配置信息
+ ///
+ [HttpGet("/apollo")]
+ [AllowAnonymous]
+ public async Task>> GetAllConfigByAppllo([FromServices]IConfiguration configuration)
+ {
+ return await Task.FromResult(configuration.AsEnumerable());
+ }
+ ///
+ /// 通过此处的key格式为 xx:xx:x
+ ///
+ [HttpGet("/apollo/{key}")]
+ [AllowAnonymous]
+ public async Task GetConfigByAppllo(string key)
+ {
+ return await Task.FromResult(Appsettings.app(key));
+ }
+ #endregion
}
}
diff --git a/Blog.Core.Api/Dockerfile b/Blog.Core.Api/Dockerfile
index 2e25ef5a..43618077 100644
--- a/Blog.Core.Api/Dockerfile
+++ b/Blog.Core.Api/Dockerfile
@@ -37,5 +37,5 @@ RUN echo 'Asia/Shanghai' >/etc/timezone
#&& supervisord -c /etc/supervisord.conf
WORKDIR /app
COPY . .
-EXPOSE 8081
+EXPOSE 9291
ENTRYPOINT ["dotnet", "Blog.Core.Api.dll","-b","0.0.0.0"]
\ No newline at end of file
diff --git a/Blog.Core.Api/Program.cs b/Blog.Core.Api/Program.cs
index 30615a39..9e416297 100644
--- a/Blog.Core.Api/Program.cs
+++ b/Blog.Core.Api/Program.cs
@@ -1,4 +1,5 @@
using Autofac.Extensions.DependencyInjection;
+using Blog.Core.Extensions.Apollo;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Hosting;
@@ -25,8 +26,10 @@ public static void Main(string[] args)
config.AddJsonFile("appsettings.json", optional: true, reloadOnChange: false)
//.AddJsonFile($"appsettings{ GetAppSettingsConfigName() }json", optional: true, reloadOnChange: false)
;
+ //接入Apollo配置中心
+ config.AddConfigurationApollo("appsettings.apollo.json");
})
- .UseUrls("http://*:8081")
+ .UseUrls("http://*:9291")
.ConfigureLogging((hostingContext, builder) =>
{
// 1.过滤掉系统默认的一些日志
diff --git a/Blog.Core.Api/Properties/launchSettings.json b/Blog.Core.Api/Properties/launchSettings.json
index 75116a3b..9b02dcc0 100644
--- a/Blog.Core.Api/Properties/launchSettings.json
+++ b/Blog.Core.Api/Properties/launchSettings.json
@@ -13,9 +13,9 @@
"commandName": "Project",
"launchBrowser": true,
"environmentVariables": {
- "ASPNETCORE_ENVIRONMENT": "dev"
+ "ASPNETCORE_ENVIRONMENT": ""
},
- "applicationUrl": "http://localhost:8081"
+ "applicationUrl": "http://localhost:9291"
},
"IIS Express": {
"commandName": "IISExpress",
diff --git a/Blog.Core.Api/Startup.cs b/Blog.Core.Api/Startup.cs
index 14a30aeb..599d3760 100644
--- a/Blog.Core.Api/Startup.cs
+++ b/Blog.Core.Api/Startup.cs
@@ -68,6 +68,7 @@ public void ConfigureServices(IServiceCollection services)
services.AddRedisInitMqSetup();
services.AddRabbitMQSetup();
+ services.AddKafkaSetup(Configuration);
services.AddEventBusSetup();
services.AddNacosSetup(Configuration);
diff --git a/Blog.Core.Api/appsettings.apollo.json b/Blog.Core.Api/appsettings.apollo.json
new file mode 100644
index 00000000..826c75ca
--- /dev/null
+++ b/Blog.Core.Api/appsettings.apollo.json
@@ -0,0 +1,18 @@
+{
+ //apollo 配置
+ "Apollo": {
+ "Enable": false,
+ "Config": {
+ "AppId": "blog.core",
+ "Env": "DEV",
+ "MetaServer": "http://localhost:8080/",
+ "ConfigServer": [ "http://localhost:8080/" ]
+ },
+ "Namespaces": [ //Namespaces的数据格式Properties,Xml,Json,Yml,Yaml,Txt
+ {
+ "Name": "test",
+ "Format": "json"
+ }
+ ]
+ }
+}
\ No newline at end of file
diff --git a/Blog.Core.Api/appsettings.json b/Blog.Core.Api/appsettings.json
index b39bce54..c31755df 100644
--- a/Blog.Core.Api/appsettings.json
+++ b/Blog.Core.Api/appsettings.json
@@ -1,5 +1,5 @@
{
- "urls": "http://*:8081", //web服务端口,如果用IIS部署,把这个去掉
+ "urls": "http://*:9291", //web服务端口,如果用IIS部署,把这个去掉
"Logging": {
"LogLevel": {
"Default": "Information", //加入Default否则log4net本地写入不了日志
@@ -31,6 +31,13 @@
"UserName": "",
"Password": "!",
"RetryCount": 3
+ },
+ "Kafka": {
+ "Enabled": false,
+ "Servers": "localhost:9092",
+ "Topic": "blog",
+ "GroupId": "blog-consumer",
+ "NumPartitions": 3 //主题分区数量
},
"EventBus": {
"Enabled": false,
@@ -245,7 +252,7 @@
"ConsulSetting": {
"ServiceName": "BlogCoreService",
"ServiceIP": "localhost",
- "ServicePort": "8081",
+ "ServicePort": "9291",
"ServiceHealthCheck": "/healthcheck",
"ConsulAddress": "http://localhost:8500"
},
@@ -264,7 +271,17 @@
"Namespace": "public", // 命名空间
"ListenInterval": 10000, // 监听的频率
"ServiceName": "blog.Core.Api", // 服务名
- "Port": "8081", // 服务端口号
+ "Port": "9291", // 服务端口号
"RegisterEnabled": true // 是否直接注册nacos
+ },
+ "LogFiedOutPutConfigs": {
+ "tcpAddressHost": "", // 输出elk的tcp连接地址
+ "tcpAddressPort": 0, // 输出elk的tcp端口号
+ "ConfigsInfo": [ // 配置的输出elk节点内容 常用语动态标识
+ {
+ "FiedName": "applicationName",
+ "FiedValue": "Blog.Core.Api"
+ }
+ ]
}
}
diff --git a/Blog.Core.Api/wwwroot/CorsPost.html b/Blog.Core.Api/wwwroot/CorsPost.html
index cf160d5c..8ebbf01a 100644
--- a/Blog.Core.Api/wwwroot/CorsPost.html
+++ b/Blog.Core.Api/wwwroot/CorsPost.html
@@ -15,13 +15,13 @@
$(document).ready(function () {
$("#jsonp").click(function () {
- $.getJSON("http://localhost:8081/api/Login/jsonp?callBack=?", function (data) {
+ $.getJSON("http://localhost:9291/api/Login/jsonp?callBack=?", function (data) {
$("#data-jsonp").html("数据: " + data.value);
});
});
$("#cors").click(function () {
- $.get("http://localhost:8081/api/Login/Token", function (data, status) {
+ $.get("http://localhost:9291/api/Login/Token", function (data, status) {
console.log(data);
$("#status-cors").html("状态: " + status);
$("#data-cors").html("数据: " + data? data.token:"失败");
@@ -43,7 +43,7 @@
};
$.ajax({
type: 'post',
- url: 'http://localhost:8081/api/Values',
+ url: 'http://localhost:9291/api/Values',
contentType: 'application/json',
data: JSON.stringify(postdata),
success: function (data, status) {
diff --git a/Blog.Core.Api/wwwroot/index.html b/Blog.Core.Api/wwwroot/index.html
index cf47942a..2e1be63e 100644
--- a/Blog.Core.Api/wwwroot/index.html
+++ b/Blog.Core.Api/wwwroot/index.html
@@ -18,7 +18,7 @@
"bRemark": "string"
};
$.ajax({
- url: "http://localhost:8081/api/Values",
+ url: "http://localhost:9291/api/Values",
type: "POST",
contentType: "application/json; charset=utf-8",
data: JSON.stringify(postdata),
@@ -34,7 +34,7 @@
-
diff --git a/Blog.Core.Build.bat b/Blog.Core.Build.bat
index c6163e9a..632e841c 100644
--- a/Blog.Core.Build.bat
+++ b/Blog.Core.Build.bat
@@ -2,7 +2,7 @@ git pull
@echo off
-for /f "tokens=5" %%i in ('netstat -aon ^| findstr ":8081"') do (
+for /f "tokens=5" %%i in ('netstat -aon ^| findstr ":9291"') do (
set n=%%i
)
taskkill /f /pid %n%
diff --git a/Blog.Core.Common/Helper/JsonConfigUtils.cs b/Blog.Core.Common/Helper/JsonConfigUtils.cs
index f04fff19..b49024b3 100644
--- a/Blog.Core.Common/Helper/JsonConfigUtils.cs
+++ b/Blog.Core.Common/Helper/JsonConfigUtils.cs
@@ -101,7 +101,6 @@ public ConfigurationManager(IConfigurationRoot _config)
}
catch (Exception ex)
{
- Serilog.Log.Information($"配置文件管理器异常:,{ ex.ToString() }");
value = defaultValue;
}
diff --git a/Blog.Core.Common/LogHelper/LogLock.cs b/Blog.Core.Common/LogHelper/LogLock.cs
index adeb0e11..dc2d158a 100644
--- a/Blog.Core.Common/LogHelper/LogLock.cs
+++ b/Blog.Core.Common/LogHelper/LogLock.cs
@@ -150,6 +150,37 @@ public static string ReadLog(string folderPath, string fileName, Encoding encode
return s;
}
+ private static List GetRequestInfo(ReadType readType)
+ {
+ List requestInfos = new();
+ var accessLogs = ReadLog(Path.Combine(_contentRoot, "Log"), "RequestIpInfoLog_", Encoding.UTF8, readType).ObjToString();
+ try
+ {
+ return JsonConvert.DeserializeObject>("[" + accessLogs + "]");
+ }
+ catch (Exception)
+ {
+ var accLogArr = accessLogs.Split("\r\n");
+ foreach (var item in accLogArr)
+ {
+ if (item.ObjToString() != "")
+ {
+ try
+ {
+ var accItem = JsonConvert.DeserializeObject(item.TrimEnd(','));
+ requestInfos.Add(accItem);
+ }
+ catch (Exception)
+ {
+ }
+ }
+ }
+
+ }
+
+ return requestInfos;
+ }
+
public static List GetLogData()
{
@@ -232,7 +263,7 @@ public static List GetLogData()
try
{
- var Logs = JsonConvert.DeserializeObject>("[" + ReadLog(Path.Combine(_contentRoot, "Log"), "RequestIpInfoLog_", Encoding.UTF8, ReadType.PrefixLatest) + "]");
+ var Logs = GetRequestInfo(ReadType.PrefixLatest);
Logs = Logs.Where(d => d.Datetime.ObjToDate() >= DateTime.Today).ToList();
@@ -276,7 +307,7 @@ public static RequestApiWeekView RequestApiinfoByWeek()
try
{
- Logs = JsonConvert.DeserializeObject>("[" + ReadLog(Path.Combine(_contentRoot, "Log"), "RequestIpInfoLog_", Encoding.UTF8, ReadType.Prefix) + "]");
+ Logs = GetRequestInfo(ReadType.Prefix);
apiWeeks = (from n in Logs
group n by new { n.Week, n.Url } into g
@@ -347,8 +378,8 @@ public static AccessApiDateView AccessApiByDate()
List apiDates = new List();
try
{
- Logs = JsonConvert.DeserializeObject>("[" + ReadLog(Path.Combine(_contentRoot, "Log"), "RequestIpInfoLog_", Encoding.UTF8, ReadType.Prefix) + "]");
-
+ Logs = GetRequestInfo(ReadType.Prefix);
+
apiDates = (from n in Logs
group n by new { n.Date } into g
select new ApiDate
@@ -377,7 +408,7 @@ public static AccessApiDateView AccessApiByHour()
List apiDates = new List();
try
{
- Logs = JsonConvert.DeserializeObject>("[" + ReadLog(Path.Combine(_contentRoot, "Log"), "RequestIpInfoLog_", Encoding.UTF8, ReadType.Prefix) + "]");
+ Logs = GetRequestInfo(ReadType.Prefix);
apiDates = (from n in Logs
where n.Datetime.ObjToDate() >= DateTime.Today
diff --git a/Blog.Core.Common/LogHelper/Seri/SerilogServer.cs b/Blog.Core.Common/LogHelper/Seri/SerilogServer.cs
index fcdbfd84..2c70532d 100644
--- a/Blog.Core.Common/LogHelper/Seri/SerilogServer.cs
+++ b/Blog.Core.Common/LogHelper/Seri/SerilogServer.cs
@@ -1,7 +1,8 @@
using Blog.Core.Common.Helper;
+using Blog.Core.Serilog.Es;
+using Blog.Core.Serilog.Es.Formatters;
using Serilog;
using Serilog.Events;
-using Serilog.Sinks.Elasticsearch;
using System;
using System.IO;
@@ -18,6 +19,8 @@ public class SerilogServer
public static void WriteLog(string filename, string[] dataParas, bool IsHeader = true, string defaultFolder = "", bool isJudgeJsonFormat = false)
{
Log.Logger = new LoggerConfiguration()
+ // TCPSink 集成Serilog 使用tcp的方式向elk 输出log日志 LogstashJsonFormatter 这个是按照自定义格式化输出内容
+ .WriteTo.TCPSink(new LogstashJsonFormatter())
.MinimumLevel.Debug()
.MinimumLevel.Override("Microsoft", LogEventLevel.Error)
//.WriteTo.File(Path.Combine($"log/Serilog/{filename}/", ".log"), rollingInterval: RollingInterval.Day, outputTemplate: "{Timestamp:yyyy-MM-dd HH:mm:ss.fff} [{Level}] {Message}{NewLine}{Exception}")
@@ -54,7 +57,11 @@ public static void WriteLog(string filename, string[] dataParas, bool IsHeader =
String.Join("\r\n", dataParas) + "\r\n"
);
}
+ // 展示elk支持输出4种日志级别
Log.Information(logContent);
+ Log.Warning(logContent);
+ Log.Error(logContent);
+ Log.Debug(logContent);
}
else
{
diff --git a/Blog.Core.EventBus/Blog.Core.EventBus.csproj b/Blog.Core.EventBus/Blog.Core.EventBus.csproj
index d15a0109..b71254af 100644
--- a/Blog.Core.EventBus/Blog.Core.EventBus.csproj
+++ b/Blog.Core.EventBus/Blog.Core.EventBus.csproj
@@ -8,11 +8,13 @@
+
+
diff --git a/Blog.Core.EventBus/EventBusKafka/EventBusKafka.cs b/Blog.Core.EventBus/EventBusKafka/EventBusKafka.cs
new file mode 100644
index 00000000..6b2dd0fb
--- /dev/null
+++ b/Blog.Core.EventBus/EventBusKafka/EventBusKafka.cs
@@ -0,0 +1,118 @@
+using Blog.Core.Common.Extensions;
+using Confluent.Kafka;
+using Microsoft.Extensions.Logging;
+using Microsoft.Extensions.Options;
+using Newtonsoft.Json;
+using System;
+
+namespace Blog.Core.EventBus
+{
+ ///
+ /// 基于Kafka的事件总线
+ ///
+ public class EventBusKafka : IEventBus
+ {
+ private readonly ILogger _logger;
+ private readonly IEventBusSubscriptionsManager _subsManager;
+ private readonly IKafkaConnectionPool _connectionPool;
+ private readonly KafkaOptions _options;
+ public EventBusKafka(ILogger logger,
+ IEventBusSubscriptionsManager subsManager,
+ IKafkaConnectionPool connectionPool,
+ IOptions options)
+ {
+ _logger = logger;
+ _subsManager = subsManager;
+ _connectionPool = connectionPool;
+ _options = options.Value;
+ }
+ ///
+ /// 发布
+ ///
+ public void Publish(IntegrationEvent @event)
+ {
+ var producer = _connectionPool.Producer();
+ try
+ {
+ var eventName = @event.GetType().Name;
+ var body = Protobuf.Serialize(JsonConvert.SerializeObject(@event));
+ DeliveryResult result = producer.ProduceAsync(_options.Topic, new Message
+ {
+ Key = eventName,
+ Value = body
+ }).ConfigureAwait(false).GetAwaiter().GetResult();
+ }
+ catch (Exception ex)
+ {
+ _logger.LogWarning($"Could not publish event: {@event.Id.ToString("N")} ({ex.Message}); Message:{ JsonConvert.SerializeObject(@event)}");
+ }
+ finally
+ {
+ //放入连接池中
+ _connectionPool.Return(producer);
+ }
+ }
+
+ ///
+ /// 订阅
+ /// 动态
+ ///
+ /// 事件处理器
+ /// 事件名
+ public void SubscribeDynamic| (string eventName)
+ where TH : IDynamicIntegrationEventHandler
+ {
+ _logger.LogInformation("Subscribing to dynamic event {EventName} with {EventHandler}", eventName, typeof(TH).GetGenericTypeName());
+
+ _subsManager.AddDynamicSubscription | (eventName);
+ }
+
+ ///
+ /// 订阅
+ ///
+ /// 约束:事件模型
+ /// 约束:事件处理器<事件模型>
+ public void Subscribe()
+ where T : IntegrationEvent
+ where TH : IIntegrationEventHandler
+ {
+ var eventName = _subsManager.GetEventKey();
+
+ _logger.LogInformation("Subscribing to event {EventName} with {EventHandler}", eventName, typeof(TH).GetGenericTypeName());
+
+ _subsManager.AddSubscription();
+ }
+
+ ///
+ /// 取消订阅
+ ///
+ ///
+ ///
+ public void Unsubscribe()
+ where T : IntegrationEvent
+ where TH : IIntegrationEventHandler
+ {
+ var eventName = _subsManager.GetEventKey();
+
+ _logger.LogInformation("Unsubscribing from event {EventName}", eventName);
+
+ _subsManager.RemoveSubscription();
+ }
+
+ public void UnsubscribeDynamic| (string eventName)
+ where TH : IDynamicIntegrationEventHandler
+ {
+ _subsManager.RemoveDynamicSubscription | (eventName);
+ }
+
+ public void Dispose()
+ {
+ if (_connectionPool != null)
+ {
+ _connectionPool.Dispose();
+ }
+ _subsManager.Clear();
+ }
+
+ }
+}
diff --git a/Blog.Core.EventBus/EventBusKafka/IKafkaConnectionPool.cs b/Blog.Core.EventBus/EventBusKafka/IKafkaConnectionPool.cs
new file mode 100644
index 00000000..0968e0e3
--- /dev/null
+++ b/Blog.Core.EventBus/EventBusKafka/IKafkaConnectionPool.cs
@@ -0,0 +1,25 @@
+using Confluent.Kafka;
+using System;
+
+
+namespace Blog.Core.EventBus
+{
+ ///
+ /// Kafka连接池
+ ///
+ public interface IKafkaConnectionPool:IDisposable
+ {
+ ///
+ /// 取对象
+ ///
+ ///
+ IProducer Producer();
+
+ ///
+ /// 将对象放入连接池
+ ///
+ ///
+ ///
+ bool Return(IProducer producer);
+ }
+}
diff --git a/Blog.Core.EventBus/EventBusKafka/KafkaConnectionPool.cs b/Blog.Core.EventBus/EventBusKafka/KafkaConnectionPool.cs
new file mode 100644
index 00000000..addd1f6b
--- /dev/null
+++ b/Blog.Core.EventBus/EventBusKafka/KafkaConnectionPool.cs
@@ -0,0 +1,79 @@
+using Confluent.Kafka;
+using Microsoft.Extensions.Logging;
+using Microsoft.Extensions.Options;
+using System.Collections.Concurrent;
+using System.Threading;
+
+
+namespace Blog.Core.EventBus
+{
+ ///
+ /// Kafka producer 连接池管理
+ /// 可以使用微软官方的对象池进行构造ObjectPool
+ ///
+ public class KafkaConnectionPool : IKafkaConnectionPool
+ {
+ private readonly KafkaOptions _options;
+ private ConcurrentQueue> _producerPool = new();
+ private int _currentCount;
+ private int _maxSize;
+ public KafkaConnectionPool(IOptions options)
+ {
+ _options = options.Value;
+ _maxSize = _options.ConnectionPoolSize;
+ }
+
+ ///
+ /// 取对象
+ ///
+ ///
+ public IProducer Producer()
+ {
+ if (_producerPool.TryDequeue(out var producer))
+ {
+ Interlocked.Decrement(ref _currentCount);
+ return producer;
+ }
+
+ var config = new ProducerConfig()
+ {
+ BootstrapServers = _options.Servers,
+ QueueBufferingMaxMessages = 10,
+ MessageTimeoutMs = 5000,
+ RequestTimeoutMs = 3000
+ };
+
+ producer = new ProducerBuilder(config)
+ .Build();
+ return producer;
+ }
+ ///
+ /// 将对象放入连接池
+ ///
+ ///
+ ///
+ public bool Return(IProducer producer)
+ {
+ if (Interlocked.Increment(ref _currentCount) <= _maxSize)
+ {
+ _producerPool.Enqueue(producer);
+ return true;
+ }
+
+ producer.Dispose();
+ Interlocked.Decrement(ref _currentCount);
+
+ return false;
+ }
+ public void Dispose()
+ {
+ _maxSize = 0;
+ _currentCount = 0;
+ while (_producerPool.TryDequeue(out var context))
+ {
+ context?.Dispose();
+ }
+ }
+
+ }
+}
diff --git a/Blog.Core.EventBus/EventBusKafka/KafkaConsumerHostService.cs b/Blog.Core.EventBus/EventBusKafka/KafkaConsumerHostService.cs
new file mode 100644
index 00000000..27fcd000
--- /dev/null
+++ b/Blog.Core.EventBus/EventBusKafka/KafkaConsumerHostService.cs
@@ -0,0 +1,162 @@
+using Autofac;
+using Confluent.Kafka;
+using Confluent.Kafka.Admin;
+using Microsoft.Extensions.Hosting;
+using Microsoft.Extensions.Logging;
+using Microsoft.Extensions.Options;
+using Newtonsoft.Json;
+using Newtonsoft.Json.Linq;
+using System;
+using System.Linq;
+using System.Threading;
+using System.Threading.Tasks;
+
+namespace Blog.Core.EventBus
+{
+ ///
+ /// Kafka consumer 监听服务
+ ///
+ public class KafkaConsumerHostService : BackgroundService
+ {
+ private readonly string AUTOFAC_SCOPE_NAME = "blogcore_event_bus";
+ private readonly ILogger _logger;
+ private readonly IConsumer _consumer;
+ private readonly KafkaOptions _options;
+ private readonly IEventBusSubscriptionsManager _subsManager;
+ private readonly ILifetimeScope _autofac;
+ private CancellationTokenSource cts = new();
+ public KafkaConsumerHostService(ILogger logger,
+ IOptions options,
+ IEventBusSubscriptionsManager eventBusSubscriptionsManager,
+ ILifetimeScope autofac)
+ {
+ _autofac = autofac;
+ _subsManager = eventBusSubscriptionsManager;
+ _logger = logger;
+ _options = options.Value;
+ _consumer = new ConsumerBuilder(new ConsumerConfig
+ {
+ BootstrapServers = _options.Servers,
+ GroupId = _options.GroupId,
+ AutoOffsetReset = AutoOffsetReset.Earliest,
+ AllowAutoCreateTopics = true,
+ EnableAutoCommit = false,
+ LogConnectionClose = false
+ }).SetErrorHandler(ConsumerClient_OnConsumeError)
+ .Build();
+ }
+ protected override async Task ExecuteAsync(CancellationToken stoppingToken)
+ {
+ var result = await FetchTopicAsync();
+ if (result)
+ {
+ _consumer.Subscribe(_options.Topic);
+ while (!cts.Token.IsCancellationRequested)
+ {
+ var consumerResult = _consumer.Consume(cts.Token);
+ try
+ {
+ if (consumerResult.IsPartitionEOF || consumerResult.Message.Value == null) continue;
+
+ var @event = Protobuf.Deserialize(consumerResult.Message.Value);
+ await ProcessEvent(consumerResult.Message.Key, @event);
+ }
+ catch (ConsumeException e)
+ {
+ _logger.LogError($"Error occured: {e.Error.Reason}");
+ }
+ finally
+ {
+ _consumer.Commit(consumerResult);
+ }
+ }
+ }
+ }
+ public override Task StopAsync(CancellationToken cancellationToken)
+ {
+ cts.Cancel();
+ _logger.LogInformation("kafka consumer stop and disposable");
+ _consumer.Dispose();
+ return base.StopAsync(cancellationToken);
+ }
+ ///
+ /// 检测当前Topic是否存在
+ ///
+ ///
+ private async Task FetchTopicAsync()
+ {
+ if (string.IsNullOrEmpty(_options.Topic))
+ throw new ArgumentNullException(nameof(_options.Topic));
+
+ try
+ {
+ var config = new AdminClientConfig { BootstrapServers = _options.Servers };
+ using var adminClient = new AdminClientBuilder(config).Build();
+ await adminClient.CreateTopicsAsync(Enumerable.Range(0,1).Select(u=> new TopicSpecification
+ {
+ Name = _options.Topic,
+ NumPartitions = _options.NumPartitions
+ }));
+ }
+ catch (CreateTopicsException ex) when (ex.Message.Contains("already exists"))
+ {
+ }
+ catch (Exception ex)
+ {
+ _logger.LogError("An error was encountered when automatically creating topic! -->" + ex.Message);
+ return false;
+ }
+ return true;
+ }
+ ///
+ /// 接收到消息进行处理
+ ///
+ /// 事件名称
+ /// 消息内容
+ ///
+ private async Task ProcessEvent(string eventName, string message)
+ {
+ _logger.LogTrace("Processing Kafka event: {EventName}", eventName);
+
+ if (_subsManager.HasSubscriptionsForEvent(eventName))
+ {
+ using (var scope = _autofac.BeginLifetimeScope(AUTOFAC_SCOPE_NAME))
+ {
+ var subscriptions = _subsManager.GetHandlersForEvent(eventName);
+ foreach (var subscription in subscriptions)
+ {
+ if (subscription.IsDynamic)
+ {
+ var handler = scope.ResolveOptional(subscription.HandlerType) as IDynamicIntegrationEventHandler;
+ if (handler == null) continue;
+ dynamic eventData = JObject.Parse(message);
+
+ await Task.Yield();
+ await handler.Handle(eventData);
+ }
+ else
+ {
+ var handler = scope.ResolveOptional(subscription.HandlerType);
+ if (handler == null) continue;
+ var eventType = _subsManager.GetEventTypeByName(eventName);
+ var integrationEvent = JsonConvert.DeserializeObject(message, eventType);
+ var concreteType = typeof(IIntegrationEventHandler<>).MakeGenericType(eventType);
+
+ await Task.Yield();
+ await (Task)concreteType.GetMethod("Handle").Invoke(handler, new object[] { integrationEvent });
+ }
+ }
+ }
+ }
+ else
+ {
+ _logger.LogWarning("No subscription for Kafka event: {EventName}", eventName);
+ }
+ }
+
+ private void ConsumerClient_OnConsumeError(IConsumer consumer, Error e)
+ {
+ _logger.LogError("An error occurred during connect kafka:" + e.Reason);
+ }
+ }
+}
diff --git a/Blog.Core.EventBus/EventBusKafka/KafkaOptions.cs b/Blog.Core.EventBus/EventBusKafka/KafkaOptions.cs
new file mode 100644
index 00000000..637da2aa
--- /dev/null
+++ b/Blog.Core.EventBus/EventBusKafka/KafkaOptions.cs
@@ -0,0 +1,28 @@
+
+
+namespace Blog.Core.EventBus
+{
+ ///
+ /// Kafka 配置项
+ ///
+ public class KafkaOptions
+ {
+ public int ConnectionPoolSize { get; set; } = 10;
+ ///
+ /// 地址
+ ///
+ public string Servers { get; set; }
+ ///
+ /// 主题
+ ///
+ public string Topic { get; set; }
+ ///
+ /// 消费者组Id
+ ///
+ public string GroupId { get; set; }
+ ///
+ /// 主题分区
+ ///
+ public int NumPartitions { get; set; }
+ }
+}
diff --git a/Blog.Core.EventBus/EventBusKafka/ProtobufTransfer.cs b/Blog.Core.EventBus/EventBusKafka/ProtobufTransfer.cs
new file mode 100644
index 00000000..c365db12
--- /dev/null
+++ b/Blog.Core.EventBus/EventBusKafka/ProtobufTransfer.cs
@@ -0,0 +1,32 @@
+using System;
+using System.IO;
+namespace Blog.Core.EventBus
+{
+ public class Protobuf
+ {
+ ///
+ /// Protobuf 反序列化
+ ///
+ public static T Deserialize(ReadOnlySpan data)
+ {
+ Stream stream = new MemoryStream(data.ToArray());
+ var info = ProtoBuf.Serializer.Deserialize(stream);
+ return info;
+ }
+ ///
+ /// 通过Protobuf 转字节
+ ///
+ public static byte[] Serialize(T data)
+ {
+ byte[] datas;
+ using (var stream = new MemoryStream())
+ {
+ ProtoBuf.Serializer.Serialize(stream, data);
+ datas = stream.ToArray();
+ }
+ return datas;
+
+
+ }
+ }
+}
diff --git a/Blog.Core.Extensions/Apollo/ApolloOptions.cs b/Blog.Core.Extensions/Apollo/ApolloOptions.cs
new file mode 100644
index 00000000..6610ba47
--- /dev/null
+++ b/Blog.Core.Extensions/Apollo/ApolloOptions.cs
@@ -0,0 +1,27 @@
+
+using System.Collections.Generic;
+
+
+namespace Blog.Core.Extensions.Apollo
+{
+ ///
+ /// Apollo配置项
+ ///
+ public class ApolloOptions
+ {
+ public bool Enable { get; set; }
+ public List Namespaces { get; set; }
+
+ public class ChildNamespace
+ {
+ ///
+ /// 命名空间名字
+ ///
+ public string Name { get; set; }
+ ///
+ /// 数据格式 Json/Yml/Yaml等
+ ///
+ public string Format { get; set; }
+ }
+ }
+}
diff --git a/Blog.Core.Extensions/Apollo/ConfigurationBuilderExtensions.cs b/Blog.Core.Extensions/Apollo/ConfigurationBuilderExtensions.cs
new file mode 100644
index 00000000..909e9a19
--- /dev/null
+++ b/Blog.Core.Extensions/Apollo/ConfigurationBuilderExtensions.cs
@@ -0,0 +1,84 @@
+using Com.Ctrip.Framework.Apollo;
+using Microsoft.Extensions.Configuration;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using Com.Ctrip.Framework.Apollo.Enums;
+using Com.Ctrip.Framework.Apollo.Logging;
+using Microsoft.Extensions.Primitives;
+using System.Reflection;
+
+namespace Blog.Core.Extensions.Apollo
+{
+ public static class ConfigurationBuilderExtensions
+ {
+ ///
+ /// 接入Apollo
+ ///
+ ///
+ /// apollo配置文件路径 如果写入appsettings.json中 则jsonPath传null即可
+ public static void AddConfigurationApollo(this IConfigurationBuilder builder,string jsonPath)
+ {
+ if (!string.IsNullOrEmpty(jsonPath))
+ {
+ builder.AddJsonFile(jsonPath, true, false);
+ }
+ //阿波罗的日志级别调整
+ LogManager.UseConsoleLogging(LogLevel.Warn);
+ var options = new ApolloOptions();
+ var root = builder.Build();
+ root.Bind("Apollo", options);
+ if (options.Enable)
+ {
+ var apolloBuilder = builder.AddApollo(root.GetSection("Apollo:Config"));
+
+ foreach (var item in options.Namespaces)
+ {
+ apolloBuilder.AddNamespace(item.Name, MatchConfigFileFormat(item.Format));
+ }
+ //监听apollo配置
+ Monitor(builder.Build());
+ }
+
+ }
+ #region private
+ ///
+ /// 监听配置
+ ///
+ private static void Monitor(IConfigurationRoot root)
+ {
+ //TODO 需要根据改变执行特定的操作 如 mq redis 等其他跟配置相关的中间件
+ //TODO 初步思路:将需要执行特定的操作key和value放入内存字典中,在赋值操作时通过标准事件来执行特定的操作。
+
+ //要重新Build 此时才将Apollo provider加入到ConfigurationBuilder中
+ ChangeToken.OnChange(() => root.GetReloadToken(), () =>
+ {
+ foreach (var apolloProvider in root.Providers.Where(p => p is ApolloConfigurationProvider))
+ {
+ var property = apolloProvider.GetType().BaseType.GetProperty("Data", BindingFlags.Instance | BindingFlags.NonPublic);
+ var data = property.GetValue(apolloProvider) as IDictionary;
+ foreach (var item in data)
+ {
+ Console.WriteLine($"key {item.Key} value {item.Value}");
+ }
+ }
+ });
+ }
+
+ //匹配格式
+ private static ConfigFileFormat MatchConfigFileFormat(string value) => value switch
+ {
+ "json" => ConfigFileFormat.Json,
+ "properties" => ConfigFileFormat.Properties,
+ "xml" => ConfigFileFormat.Xml,
+ "yml" => ConfigFileFormat.Yml,
+ "yaml" => ConfigFileFormat.Yaml,
+ "txt" => ConfigFileFormat.Txt,
+ _ => throw new FormatException($"与apollo命名空间的所允许的类型不匹配:{string.Join(",", GetConfigFileFormat())}"),
+ };
+ //获取数据格式对应的枚举
+ private static IEnumerable GetConfigFileFormat() => Enum.GetValues().Select(u => u.ToString().ToLower());
+ #endregion
+
+ }
+}
diff --git a/Blog.Core.Extensions/Blog.Core.Extensions.csproj b/Blog.Core.Extensions/Blog.Core.Extensions.csproj
index e10b8f57..76ce50ee 100644
--- a/Blog.Core.Extensions/Blog.Core.Extensions.csproj
+++ b/Blog.Core.Extensions/Blog.Core.Extensions.csproj
@@ -8,8 +8,10 @@
+
+
-
+
diff --git a/Blog.Core.Extensions/Middlewares/IPLogMildd.cs b/Blog.Core.Extensions/Middlewares/IPLogMildd.cs
index 08791669..eda2e369 100644
--- a/Blog.Core.Extensions/Middlewares/IPLogMildd.cs
+++ b/Blog.Core.Extensions/Middlewares/IPLogMildd.cs
@@ -1,5 +1,4 @@
using Blog.Core.Common;
-using Blog.Core.Common.Helper;
using Blog.Core.Common.LogHelper;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
@@ -57,24 +56,24 @@ public async Task InvokeAsync(HttpContext context)
if (!string.IsNullOrEmpty(requestInfo))
{
// 自定义log输出
- //Parallel.For(0, 1, e =>
- //{
- // LogLock.OutSql2Log("RequestIpInfoLog", new string[] { requestInfo + "," }, false);
- //});
-
- try
- {
- var testLogMatchRequestInfo = JsonConvert.DeserializeObject(requestInfo);
- if (testLogMatchRequestInfo != null)
- {
- var logFileName = FileHelper.GetAvailableFileNameWithPrefixOrderSize(_environment.ContentRootPath, "RequestIpInfoLog");
- SerilogServer.WriteLog(logFileName, new string[] { requestInfo + "," }, false, "", true);
- }
- }
- catch (Exception e)
+ Parallel.For(0, 1, e =>
{
- log.Error(requestInfo + "\r\n" + e.GetBaseException().ToString());
- }
+ LogLock.OutSql2Log("RequestIpInfoLog", new string[] { requestInfo + "," }, false);
+ });
+
+ //try
+ //{
+ // var testLogMatchRequestInfo = JsonConvert.DeserializeObject(requestInfo);
+ // if (testLogMatchRequestInfo != null)
+ // {
+ // var logFileName = FileHelper.GetAvailableFileNameWithPrefixOrderSize(_environment.ContentRootPath, "RequestIpInfoLog");
+ // SerilogServer.WriteLog(logFileName, new string[] { requestInfo + "," }, false, "", true);
+ // }
+ //}
+ //catch (Exception e)
+ //{
+ // log.Error(requestInfo + "\r\n" + e.GetBaseException().ToString());
+ //}
request.Body.Position = 0;
diff --git a/Blog.Core.Extensions/NacosConfig/NacosListenConfigurationTask.cs b/Blog.Core.Extensions/NacosConfig/NacosListenConfigurationTask.cs
index 919cc634..d1554d15 100644
--- a/Blog.Core.Extensions/NacosConfig/NacosListenConfigurationTask.cs
+++ b/Blog.Core.Extensions/NacosConfig/NacosListenConfigurationTask.cs
@@ -41,9 +41,8 @@ protected override async Task ExecuteAsync(CancellationToken stoppingToken)
// Add listener
await _configClient.AddListener("blog.Core.Api.json", "DEFAULT_GROUP", nacosConfigListener);
}
- catch (Exception ex)
+ catch (Exception)
{
- Serilog.Log.Information($"Nacos配置文件获取异常!!! " + ex.ToString());
}
}
diff --git a/Blog.Core.Extensions/NacosConfig/NacosListenNamingTask.cs b/Blog.Core.Extensions/NacosConfig/NacosListenNamingTask.cs
index d2228673..60657bb5 100644
--- a/Blog.Core.Extensions/NacosConfig/NacosListenNamingTask.cs
+++ b/Blog.Core.Extensions/NacosConfig/NacosListenNamingTask.cs
@@ -50,6 +50,7 @@ protected override async Task ExecuteAsync(CancellationToken stoppingToken)
Metadata = JsonConfigSettings.NacosMetadata
};
await _nacosNamingService.RegisterInstance(JsonConfigSettings.NacosServiceName, Nacos.V2.Common.Constants.DEFAULT_GROUP, instance);
+ ConsoleHelper.WriteSuccessLine($"Nacos connect: Success!");
}
// 程序停止
@@ -87,9 +88,6 @@ public Task OnEvent(Nacos.V2.IEvent @event)
// 配置有变动后 刷新redis配置 刷新 mq配置
//_redisCachqManager.DisposeRedisConnection();
-
-
- Serilog.Log.Information($"收到服务变更事件!!! {DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")} [{e}]");
}
return Task.CompletedTask;
diff --git a/Blog.Core.Extensions/Redis/RedisBasketRepository.cs b/Blog.Core.Extensions/Redis/RedisBasketRepository.cs
index 02809bcb..31c7a030 100644
--- a/Blog.Core.Extensions/Redis/RedisBasketRepository.cs
+++ b/Blog.Core.Extensions/Redis/RedisBasketRepository.cs
@@ -59,8 +59,16 @@ public async Task Set(string key, object value, TimeSpan cacheTime)
{
if (value != null)
{
- //序列化,将object值生成RedisValue
- await _database.StringSetAsync(key, SerializeHelper.Serialize(value), cacheTime);
+ if (value is string cacheValue)
+ {
+ // 字符串无需序列化
+ await _database.StringSetAsync(key, cacheValue, cacheTime);
+ }
+ else
+ {
+ //序列化,将object值生成RedisValue
+ await _database.StringSetAsync(key, SerializeHelper.Serialize(value), cacheTime);
+ }
}
}
diff --git a/Blog.Core.Extensions/Redis/RedisCacheManager.cs b/Blog.Core.Extensions/Redis/RedisCacheManager.cs
index 040d79c4..ab4704df 100644
--- a/Blog.Core.Extensions/Redis/RedisCacheManager.cs
+++ b/Blog.Core.Extensions/Redis/RedisCacheManager.cs
@@ -137,8 +137,16 @@ public void Set(string key, object value, TimeSpan cacheTime)
{
if (value != null)
{
- //序列化,将object值生成RedisValue
- redisConnection.GetDatabase().StringSet(key, SerializeHelper.Serialize(value), cacheTime);
+ if (value is string cacheValue)
+ {
+ // 字符串无需序列化
+ redisConnection.GetDatabase().StringSet(key, cacheValue, cacheTime);
+ }
+ else
+ {
+ //序列化,将object值生成RedisValue
+ redisConnection.GetDatabase().StringSet(key, SerializeHelper.Serialize(value), cacheTime);
+ }
}
}
diff --git a/Blog.Core.Extensions/ServiceExtensions/EventBusSetup.cs b/Blog.Core.Extensions/ServiceExtensions/EventBusSetup.cs
index 2d74c3ee..197803c1 100644
--- a/Blog.Core.Extensions/ServiceExtensions/EventBusSetup.cs
+++ b/Blog.Core.Extensions/ServiceExtensions/EventBusSetup.cs
@@ -18,41 +18,47 @@ public static void AddEventBusSetup(this IServiceCollection services)
{
if (services == null) throw new ArgumentNullException(nameof(services));
- if (Appsettings.app(new string[] { "RabbitMQ", "Enabled" }).ObjToBool() && Appsettings.app(new string[] { "EventBus", "Enabled" }).ObjToBool())
+ if (Appsettings.app(new string[] { "EventBus", "Enabled" }).ObjToBool())
{
var subscriptionClientName = Appsettings.app(new string[] { "EventBus", "SubscriptionClientName" });
-
services.AddSingleton();
services.AddTransient();
-
- services.AddSingleton(sp =>
+ if (Appsettings.app(new string[] { "RabbitMQ", "Enabled" }).ObjToBool())
{
- var rabbitMQPersistentConnection = sp.GetRequiredService();
- var iLifetimeScope = sp.GetRequiredService();
- var logger = sp.GetRequiredService>();
- var eventBusSubcriptionsManager = sp.GetRequiredService();
-
- var retryCount = 5;
- if (!string.IsNullOrEmpty(Appsettings.app(new string[] { "RabbitMQ", "RetryCount" })))
+ services.AddSingleton(sp =>
{
- retryCount = int.Parse(Appsettings.app(new string[] { "RabbitMQ", "RetryCount" }));
- }
+ var rabbitMQPersistentConnection = sp.GetRequiredService();
+ var iLifetimeScope = sp.GetRequiredService();
+ var logger = sp.GetRequiredService>();
+ var eventBusSubcriptionsManager = sp.GetRequiredService();
- return new EventBusRabbitMQ(rabbitMQPersistentConnection, logger, iLifetimeScope, eventBusSubcriptionsManager, subscriptionClientName, retryCount);
- });
+ var retryCount = 5;
+ if (!string.IsNullOrEmpty(Appsettings.app(new string[] { "RabbitMQ", "RetryCount" })))
+ {
+ retryCount = int.Parse(Appsettings.app(new string[] { "RabbitMQ", "RetryCount" }));
+ }
+
+ return new EventBusRabbitMQ(rabbitMQPersistentConnection, logger, iLifetimeScope, eventBusSubcriptionsManager, subscriptionClientName, retryCount);
+ });
+ }
+ if(Appsettings.app(new string[] { "Kafka", "Enabled" }).ObjToBool())
+ {
+ services.AddHostedService();
+ services.AddSingleton();
+ }
}
}
public static void ConfigureEventBus(this IApplicationBuilder app)
{
- if (Appsettings.app(new string[] { "RabbitMQ", "Enabled" }).ObjToBool() && Appsettings.app(new string[] { "EventBus", "Enabled" }).ObjToBool())
+ if (Appsettings.app(new string[] { "EventBus", "Enabled" }).ObjToBool())
{
var eventBus = app.ApplicationServices.GetRequiredService();
- eventBus.Subscribe();
+ eventBus.Subscribe();
}
}
}
diff --git a/Blog.Core.Extensions/ServiceExtensions/KafkaSetup.cs b/Blog.Core.Extensions/ServiceExtensions/KafkaSetup.cs
new file mode 100644
index 00000000..79e60b94
--- /dev/null
+++ b/Blog.Core.Extensions/ServiceExtensions/KafkaSetup.cs
@@ -0,0 +1,26 @@
+using Blog.Core.Common;
+using Blog.Core.EventBus;
+using Microsoft.Extensions.Configuration;
+using Microsoft.Extensions.DependencyInjection;
+using Microsoft.Extensions.Logging;
+using System;
+
+namespace Blog.Core.Extensions
+{
+ ///
+ /// 注入Kafka相关配置
+ ///
+ public static class KafkaSetup
+ {
+ public static void AddKafkaSetup(this IServiceCollection services,IConfiguration configuration)
+ {
+ if (services == null) throw new ArgumentNullException(nameof(services));
+
+ if (Appsettings.app(new string[] { "Kafka", "Enabled" }).ObjToBool())
+ {
+ services.Configure(configuration.GetSection("kafka"));
+ services.AddSingleton();
+ }
+ }
+ }
+}
diff --git a/Blog.Core.Extensions/ServiceExtensions/NacosSetup.cs b/Blog.Core.Extensions/ServiceExtensions/NacosSetup.cs
index e3b95c20..d314f6ea 100644
--- a/Blog.Core.Extensions/ServiceExtensions/NacosSetup.cs
+++ b/Blog.Core.Extensions/ServiceExtensions/NacosSetup.cs
@@ -9,7 +9,7 @@
namespace Blog.Core.Extensions
{
///
- /// Memory缓存 启动服务
+ /// Nacos
///
public static class NacosSetup
{
@@ -19,9 +19,7 @@ public static void AddNacosSetup(this IServiceCollection services, IConfiguratio
// 在实际生产工作中 本地开发是不需要注册nacos的 所以根据环境变量去判断
// 比如 开发环境 dev 测试环境 test 生产 prod 只有这几种环境变量的时候才需要去注册nacos
- if (Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT") != null
- && Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT") != ""
- && Appsettings.app(new string[] { "Startup", "Nacos", "Enabled" }).ObjToBool())
+ if (Appsettings.app(new string[] { "Startup", "Nacos", "Enabled" }).ObjToBool())
{
// 从当前配置取文件去注册naocs
services.AddNacosV2Config(x =>
diff --git a/Blog.Core.Gateway/Blog.Core.Gateway.csproj b/Blog.Core.Gateway/Blog.Core.Gateway.csproj
index 84713355..0dba222a 100644
--- a/Blog.Core.Gateway/Blog.Core.Gateway.csproj
+++ b/Blog.Core.Gateway/Blog.Core.Gateway.csproj
@@ -14,7 +14,7 @@
-
+
diff --git a/Blog.Core.Gateway/Controllers/UserController.cs b/Blog.Core.Gateway/Controllers/UserController.cs
index df715f30..8a2d7fa3 100644
--- a/Blog.Core.Gateway/Controllers/UserController.cs
+++ b/Blog.Core.Gateway/Controllers/UserController.cs
@@ -4,7 +4,6 @@
using Microsoft.AspNetCore.Mvc;
using System.Collections.Generic;
using System.Linq;
-using System.Security.Claims;
namespace Blog.Core.Gateway.Controllers
{
diff --git a/Blog.Core.Gateway/Startup.cs b/Blog.Core.Gateway/Startup.cs
index 64e7b48e..eddcdeb5 100644
--- a/Blog.Core.Gateway/Startup.cs
+++ b/Blog.Core.Gateway/Startup.cs
@@ -6,8 +6,6 @@
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
-using Ocelot.DependencyInjection;
-using Ocelot.Provider.Consul;
namespace Blog.Core.AdminMvc
{
diff --git a/Blog.Core.Gateway/ocelot.Development.json b/Blog.Core.Gateway/ocelot.Development.json
index 3889dfb6..88475e25 100644
--- a/Blog.Core.Gateway/ocelot.Development.json
+++ b/Blog.Core.Gateway/ocelot.Development.json
@@ -16,7 +16,7 @@
"DownstreamHostAndPorts": [
{
"Host": "localhost",
- "Port": 8081
+ "Port": 9291
}
]
},
diff --git a/Blog.Core.Gateway/ocelot.json b/Blog.Core.Gateway/ocelot.json
index 362529e1..c9612a60 100644
--- a/Blog.Core.Gateway/ocelot.json
+++ b/Blog.Core.Gateway/ocelot.json
@@ -16,7 +16,7 @@
"DownstreamHostAndPorts": [
{
"Host": "localhost",
- "Port": 8081
+ "Port": 9291
}
]
},
diff --git a/Blog.Core.Publish.Docker.Jenkins.sh b/Blog.Core.Publish.Docker.Jenkins.sh
index cc953102..42f074a7 100644
--- a/Blog.Core.Publish.Docker.Jenkins.sh
+++ b/Blog.Core.Publish.Docker.Jenkins.sh
@@ -17,4 +17,4 @@ chmod 777 StopContainerImg.sh
./StopContainerImg.sh apkcontainer laozhangisphi/apkimg
docker build -t laozhangisphi/apkimg .
-docker run --name=apkcontainer -d -v /data/blogcore/appsettings.json:/app/appsettings.json -v /data/blogcore/Log/:/app/Log -v /etc/localtime:/etc/localtime -it -p 8081:8081 laozhangisphi/apkimg
\ No newline at end of file
+docker run --name=apkcontainer -d -v /data/blogcore/appsettings.json:/app/appsettings.json -v /data/blogcore/Log/:/app/Log -v /etc/localtime:/etc/localtime -it -p 9291:9291 laozhangisphi/apkimg
\ No newline at end of file
diff --git a/Blog.Core.Publish.Docker.sh b/Blog.Core.Publish.Docker.sh
index d4ae6246..eadc23c4 100644
--- a/Blog.Core.Publish.Docker.sh
+++ b/Blog.Core.Publish.Docker.sh
@@ -13,6 +13,6 @@ cd /home/Blog.Core/.PublishFiles
# 编译镜像
docker build -t laozhangisphi/apkimg .
# 生成容器
-docker run --name=apkcontainer -d -v /etc/localtime:/etc/localtime -it -p 8081:8081 laozhangisphi/apkimg
+docker run --name=apkcontainer -d -v /etc/localtime:/etc/localtime -it -p 9291:9291 laozhangisphi/apkimg
# 启动容器
docker start apkcontainer
diff --git a/Blog.Core.Serilog.Es/AppSettingsFileNameConfig.cs b/Blog.Core.Serilog.Es/AppSettingsFileNameConfig.cs
new file mode 100644
index 00000000..c4f2cda0
--- /dev/null
+++ b/Blog.Core.Serilog.Es/AppSettingsFileNameConfig.cs
@@ -0,0 +1,30 @@
+using System;
+
+namespace Blog.Core.Serilog.Es
+{
+ public class AppSettingsFileNameConfig
+ {
+ ///
+ /// 配置文件名称常量
+ ///
+ public static string AppSettingsFileName = $"appsettings{ GetAppSettingsConfigName() }json";
+
+
+ ///
+ /// 根据环境变量定向配置文件名称
+ ///
+ ///
+ private static string GetAppSettingsConfigName()
+ {
+ if (Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT") != null
+ && Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT") != "")
+ {
+ return $".{Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT")}.";
+ }
+ else
+ {
+ return ".";
+ }
+ }
+ }
+}
diff --git a/Blog.Core.Serilog.Es/Blog.Core.Serilog.Es.csproj b/Blog.Core.Serilog.Es/Blog.Core.Serilog.Es.csproj
new file mode 100644
index 00000000..b5c2e0ed
--- /dev/null
+++ b/Blog.Core.Serilog.Es/Blog.Core.Serilog.Es.csproj
@@ -0,0 +1,17 @@
+
+
+
+ net5.0
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Blog.Core.Serilog.Es/Formatters/JsonConfigUtils.cs b/Blog.Core.Serilog.Es/Formatters/JsonConfigUtils.cs
new file mode 100644
index 00000000..e9425040
--- /dev/null
+++ b/Blog.Core.Serilog.Es/Formatters/JsonConfigUtils.cs
@@ -0,0 +1,66 @@
+using Microsoft.Extensions.Configuration;
+using Microsoft.Extensions.Configuration.Json;
+using Microsoft.Extensions.DependencyInjection;
+using Microsoft.Extensions.Options;
+
+namespace Blog.Core.Serilog.Es.Formatters
+{
+ ///
+ /// Json 配置文件通用类
+ ///
+ public static class JsonConfigUtils
+ {
+ #region 变量
+
+ ///
+ /// 锁
+ ///
+ private static object __Lock__ = new object();
+
+ // 读取到的系统配置信息
+ public static IConfiguration Configuration { get; set; }
+
+ #endregion
+
+ ///
+ /// 读取配置文件的信息
+ ///
+ ///
+ /// 要读取json的名称
+ /// 要读取的json节点名称
+ ///
+ public static T GetAppSettings(string AppSettingsFileName, string key) where T : class, new()
+ {
+ lock (__Lock__)
+ {
+ if (Configuration == null)
+ {
+ Configuration = new ConfigurationBuilder()
+ .Add(new JsonConfigurationSource
+ {
+ Path = AppSettingsFileName,
+ Optional = false,
+ ReloadOnChange = true
+ })
+ .Build();
+ }
+ var appconfig = new ServiceCollection()
+ .AddOptions()
+ .Configure(Configuration.GetSection(key))
+ .BuildServiceProvider()
+ .GetService>()
+ .Value;
+
+ return appconfig;
+ }
+ }
+
+
+ public static string GetJson(string jsonPath, string key)
+ {
+ IConfiguration config = new ConfigurationBuilder().AddJsonFile(jsonPath).Build(); //json文件地址
+ string s = config.GetSection(key).Value; //json某个对象
+ return s;
+ }
+ }
+}
diff --git a/Blog.Core.Serilog.Es/Formatters/LogConfigRootDTO.cs b/Blog.Core.Serilog.Es/Formatters/LogConfigRootDTO.cs
new file mode 100644
index 00000000..36a9916c
--- /dev/null
+++ b/Blog.Core.Serilog.Es/Formatters/LogConfigRootDTO.cs
@@ -0,0 +1,26 @@
+using System.Collections.Generic;
+
+namespace Blog.Core.Serilog.Es.Formatters
+{
+
+ public class LogConfigRootDTO
+ {
+ ///
+ /// tcp日志的host地址
+ ///
+ public string tcpAddressHost { set; get; }
+
+ ///
+ /// tcp日志的port地址
+ ///
+ public int tcpAddressPort { set; get; }
+
+ public List ConfigsInfo { get; set; }
+ }
+
+ public class Configsinfo
+ {
+ public string FiedName { get; set; }
+ public string FiedValue { get; set; }
+ }
+}
diff --git a/Blog.Core.Serilog.Es/Formatters/LogstashJsonFormatter.cs b/Blog.Core.Serilog.Es/Formatters/LogstashJsonFormatter.cs
new file mode 100644
index 00000000..f123c177
--- /dev/null
+++ b/Blog.Core.Serilog.Es/Formatters/LogstashJsonFormatter.cs
@@ -0,0 +1,152 @@
+// Adapted from RawJsonFormatter in Serilog.Sinks.Seq Copyright 2016 Serilog Contributors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using Serilog.Events;
+using Serilog.Formatting;
+using Serilog.Formatting.Json;
+using Blog.Core.Serilog.Es.HttpInfo;
+
+namespace Blog.Core.Serilog.Es.Formatters
+{
+ public class LogstashJsonFormatter : ITextFormatter
+ {
+ private static readonly JsonValueFormatter ValueFormatter = new JsonValueFormatter();
+
+ public void Format(LogEvent logEvent, TextWriter output)
+ {
+ FormatContent(logEvent, output);
+
+ output.WriteLine();
+ }
+
+
+ ///
+ /// 格式化 最终输出到elk的核心部分
+ ///
+ ///
+ ///
+ private static void FormatContent(LogEvent logEvent, TextWriter output)
+ {
+ if (logEvent == null) throw new ArgumentNullException(nameof(logEvent));
+ if (output == null) throw new ArgumentNullException(nameof(output));
+
+ output.Write('{');
+
+ // 读取相关配置
+ var logConfigRootDTOInfo = JsonConfigUtils.GetAppSettings(AppSettingsFileNameConfig.AppSettingsFileName, "LogFiedOutPutConfigs");
+ if (logConfigRootDTOInfo == null)
+ {
+ return;
+ }
+
+ // 写入所有的项目配置项的字段 在appsetting中配置的 输出elk节点的数据字段
+ foreach (var item in logConfigRootDTOInfo.ConfigsInfo)
+ {
+ switch (item.FiedName)
+ {
+ //case "orgid":
+ // WritePropertyAndValue(output, "method", HttpContextProvider.GetCurrent().Request.Method);
+ // output.Write(",");
+ // break;
+ default:
+ WritePropertyAndValue(output, item.FiedName, item.FiedValue);
+ output.Write(",");
+ break;
+ }
+ }
+ // 写入http对应的信息数据
+ if (HttpContextProvider.GetCurrent()!=null && HttpContextProvider.GetCurrent().Request!=null)
+ {
+ if (!string.IsNullOrEmpty(HttpContextProvider.GetCurrent().Request.Method))
+ {
+ WritePropertyAndValue(output, "method", HttpContextProvider.GetCurrent().Request.Method);
+ output.Write(",");
+ }
+ // 输出请求页面url
+ if (!string.IsNullOrEmpty(HttpContextProvider.GetCurrent().Request.Path))
+ {
+ WritePropertyAndValue(output, "requestUrl", HttpContextProvider.GetCurrent().Request.Path.ToString());
+ output.Write(",");
+ }
+ // 输出携带token
+ if (HttpContextProvider.GetCurrent().Request.Headers["Authorization"].FirstOrDefault() != null)
+ {
+ WritePropertyAndValue(output, "Authorization", HttpContextProvider.GetCurrent().Request.Headers["Authorization"].FirstOrDefault());
+ output.Write(",");
+ }
+ // 输出请求参数
+ if (!string.IsNullOrEmpty(HttpContextProvider.GetCurrent().Request.Method))
+ {
+ string contentFromBody = ParamsHelper.GetParams(HttpContextProvider.GetCurrent());
+ WritePropertyAndValue(output, "requestParam", contentFromBody);
+ output.Write(",");
+ }
+ // 输出请求方法类型
+ if (!string.IsNullOrEmpty(HttpContextProvider.GetCurrent().Request.Method))
+ {
+ WritePropertyAndValue(output, "method", HttpContextProvider.GetCurrent().Request.Method);
+ output.Write(",");
+ }
+ }
+ // 输出请求时间戳
+ WritePropertyAndValue(output, "timestamp", logEvent.Timestamp.ToString("o"));
+ output.Write(",");
+
+ // 输出日志级别
+ WritePropertyAndValue(output, "level", logEvent.Level.ToString());
+ output.Write(",");
+
+ // 输出log内容
+ WritePropertyAndValue(output, "executeResult", logEvent.MessageTemplate.Render(logEvent.Properties));
+
+ if (logEvent.Exception != null)
+ {
+ output.Write(",");
+ WritePropertyAndValue(output, "exception", logEvent.Exception.ToString());
+ }
+
+ WriteProperties(logEvent.Properties, output);
+
+ output.Write('}');
+ }
+
+ private static void WritePropertyAndValue(TextWriter output, string propertyKey, string propertyValue)
+ {
+ JsonValueFormatter.WriteQuotedJsonString(propertyKey, output);
+ output.Write(":");
+ JsonValueFormatter.WriteQuotedJsonString(propertyValue, output);
+ }
+
+ private static void WriteProperties(IReadOnlyDictionary properties, TextWriter output)
+ {
+ if (properties.Any()) output.Write(",");
+
+ var precedingDelimiter = "";
+ foreach (var property in properties)
+ {
+ output.Write(precedingDelimiter);
+ precedingDelimiter = ",";
+
+ var camelCasePropertyKey = property.Key[0].ToString().ToLower() + property.Key.Substring(1);
+ JsonValueFormatter.WriteQuotedJsonString(camelCasePropertyKey, output);
+ output.Write(':');
+ ValueFormatter.Format(property.Value, output);
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/Blog.Core.Serilog.Es/HttpInfo/HttpContextProvider.cs b/Blog.Core.Serilog.Es/HttpInfo/HttpContextProvider.cs
new file mode 100644
index 00000000..612f20b5
--- /dev/null
+++ b/Blog.Core.Serilog.Es/HttpInfo/HttpContextProvider.cs
@@ -0,0 +1,20 @@
+using Microsoft.AspNetCore.Http;
+
+namespace Blog.Core.Serilog.Es.HttpInfo
+{
+ public static class HttpContextProvider
+ {
+ private static IHttpContextAccessor _accessor;
+
+ public static HttpContext GetCurrent()
+ {
+ var context = _accessor?.HttpContext;
+ return context;
+ }
+ public static void ConfigureAccessor(IHttpContextAccessor accessor)
+ {
+ _accessor = accessor;
+ }
+ }
+
+}
diff --git a/Blog.Core.Serilog.Es/HttpInfo/ParamsHelper.cs b/Blog.Core.Serilog.Es/HttpInfo/ParamsHelper.cs
new file mode 100644
index 00000000..3b39c0bf
--- /dev/null
+++ b/Blog.Core.Serilog.Es/HttpInfo/ParamsHelper.cs
@@ -0,0 +1,82 @@
+using Microsoft.AspNetCore.Http;
+using System;
+using System.Collections.Generic;
+using System.Collections.Specialized;
+using System.IO;
+using System.Text;
+using System.Web;
+
+namespace Blog.Core.Serilog.Es.HttpInfo
+{
+ ///
+ /// 获取参数帮助类
+ ///
+ public class ParamsHelper
+ {
+ ///
+ /// 获取参数值
+ ///
+ ///
+ ///
+ public static string GetParams(HttpContext context)
+ {
+ try
+ {
+ NameValueCollection form = HttpUtility.ParseQueryString(context.Request.QueryString.ToString());
+ HttpRequest request = context.Request;
+
+ string data = string.Empty;
+ switch (request.Method)
+ {
+ case "POST":
+
+ request.Body.Position = 0;
+ using (var ms = new MemoryStream())
+ {
+ request.Body.CopyTo(ms);
+ var b = ms.ToArray();
+ data = Encoding.UTF8.GetString(b); //把body赋值给bodyStr
+
+ }
+ break;
+ case "GET":
+ //第一步:取出所有get参数
+ IDictionary parameters = new Dictionary();
+ for (int f = 0; f < form.Count; f++)
+ {
+ string key = form.Keys[f];
+ parameters.Add(key, form[key]);
+ }
+
+ // 第二步:把字典按Key的字母顺序排序
+ IDictionary sortedParams = new SortedDictionary(parameters);
+ IEnumerator> dem = sortedParams.GetEnumerator();
+
+ // 第三步:把所有参数名和参数值串在一起
+ StringBuilder query = new StringBuilder();
+ while (dem.MoveNext())
+ {
+ string key = dem.Current.Key;
+ string value = dem.Current.Value;
+ if (!string.IsNullOrEmpty(key))
+ {
+ query.Append(key).Append("=").Append(value).Append("&");
+ }
+ }
+ data = query.ToString().TrimEnd('&');
+ break;
+ default:
+ data = string.Empty;
+
+ break;
+ }
+ return data;
+ }
+ catch(Exception ex)
+ {
+ return string.Empty;
+ }
+ }
+
+ }
+}
diff --git a/Blog.Core.Serilog.Es/NetworkLoggerConfigurationExtensions.cs b/Blog.Core.Serilog.Es/NetworkLoggerConfigurationExtensions.cs
new file mode 100644
index 00000000..d77f80f2
--- /dev/null
+++ b/Blog.Core.Serilog.Es/NetworkLoggerConfigurationExtensions.cs
@@ -0,0 +1,102 @@
+using System;
+using System.Linq;
+using System.Net;
+using Serilog;
+using Serilog.Configuration;
+using Serilog.Debugging;
+using Serilog.Events;
+using Serilog.Formatting;
+using Blog.Core.Serilog.Es.Formatters;
+using Blog.Core.Serilog.Es.Sinks.TCP;
+
+namespace Blog.Core.Serilog.Es
+{
+ ///
+ /// Extends Serilog configuration to write events to the network.
+ ///
+ public static class NetworkLoggerConfigurationExtensions
+ {
+ private static string TcpAddressHost = "";
+ private static int TcpAddressProt = 0;
+ ///
+ /// 获得tcpAddress
+ ///
+ private static void GetTcpAddress()
+ {
+ // 读取相关配置
+ var logConfigRootDTOInfo = JsonConfigUtils.GetAppSettings(AppSettingsFileNameConfig.AppSettingsFileName, "LogFiedOutPutConfigs");
+ if (logConfigRootDTOInfo == null)
+ {
+ return;
+ }
+ TcpAddressHost = logConfigRootDTOInfo.tcpAddressHost;
+ TcpAddressProt = logConfigRootDTOInfo.tcpAddressPort;
+ }
+
+ public static LoggerConfiguration TCPSink(
+ this LoggerSinkConfiguration loggerConfiguration,
+ ITextFormatter textFormatter = null,
+ LogEventLevel restrictedToMinimumLevel = LevelAlias.Minimum)
+ {
+ GetTcpAddress();
+ if (!string.IsNullOrEmpty(TcpAddressHost))
+ {
+ var sink = new TCPSink(BuildUri($"tcp://{TcpAddressHost}:{TcpAddressProt}"), textFormatter ?? new LogstashJsonFormatter());
+ return loggerConfiguration.Sink(sink, restrictedToMinimumLevel);
+ }
+ else {
+ return new LoggerConfiguration();
+ }
+ }
+
+ private static IPAddress ResolveAddress(string uri)
+ {
+ // Check if it is IP address
+ IPAddress address;
+
+ if (IPAddress.TryParse(uri, out address))
+ return address;
+
+ address = ResolveIP(uri);
+ if (address != null)
+ return address;
+
+ SelfLog.WriteLine("Unable to determine the destination IP-Address");
+ return IPAddress.Loopback;
+ }
+
+ private static IPAddress ResolveIP(string uri)
+ {
+ try
+ {
+ var ipHostEntry = Dns.GetHostEntryAsync(uri).Result;
+ if (!ipHostEntry.AddressList.Any())
+ return null;
+ return ipHostEntry.AddressList.First();
+ }
+ catch (Exception)
+ {
+ SelfLog.WriteLine("Could not resolve " + uri);
+ return null;
+ }
+ }
+
+ private static Uri BuildUri(string s)
+ {
+ Uri uri;
+ try
+ {
+ uri = new Uri(s);
+ }
+ catch (UriFormatException ex)
+ {
+ throw new ArgumentNullException("Uri should be in the format tcp://server:port", ex);
+ }
+ if (uri.Port == 0)
+ throw new UriFormatException("Uri port cannot be 0");
+ if (!(uri.Scheme.ToLower() == "tcp" || uri.Scheme.ToLower() == "tls"))
+ throw new UriFormatException("Uri scheme must be tcp or tls");
+ return uri;
+ }
+ }
+}
\ No newline at end of file
diff --git a/Blog.Core.Serilog.Es/Sinks/TCP/TCPSink.cs b/Blog.Core.Serilog.Es/Sinks/TCP/TCPSink.cs
new file mode 100644
index 00000000..fc5a43c9
--- /dev/null
+++ b/Blog.Core.Serilog.Es/Sinks/TCP/TCPSink.cs
@@ -0,0 +1,44 @@
+using System;
+using System.IO;
+using System.Net;
+using System.Text;
+using Serilog.Core;
+using Serilog.Events;
+using Serilog.Formatting;
+
+namespace Blog.Core.Serilog.Es.Sinks.TCP
+{
+ public class TCPSink : ILogEventSink, IDisposable
+ {
+ private readonly ITextFormatter _formatter;
+ private readonly TcpSocketWriter _socketWriter;
+
+ public TCPSink(IPAddress ipAddress, int port, ITextFormatter formatter)
+ {
+ _socketWriter = new TcpSocketWriter(new Uri($"tcp://{ipAddress}:{port}"));
+ _formatter = formatter;
+ }
+
+ public TCPSink(Uri uri, ITextFormatter formatter)
+ {
+ _socketWriter = new TcpSocketWriter(uri);
+ _formatter = formatter;
+ }
+
+ public void Emit(LogEvent logEvent)
+ {
+ var sb = new StringBuilder();
+
+ using (var sw = new StringWriter(sb))
+ _formatter.Format(logEvent, sw);
+
+ sb.Replace("RenderedMessage", "message");
+ _socketWriter.Enqueue(sb.ToString());
+ }
+
+ public void Dispose()
+ {
+ _socketWriter.Dispose();
+ }
+ }
+}
\ No newline at end of file
diff --git a/Blog.Core.Serilog.Es/Sinks/TCP/TCPSocketWriter.cs b/Blog.Core.Serilog.Es/Sinks/TCP/TCPSocketWriter.cs
new file mode 100644
index 00000000..f1f592c9
--- /dev/null
+++ b/Blog.Core.Serilog.Es/Sinks/TCP/TCPSocketWriter.cs
@@ -0,0 +1,325 @@
+/*
+ * Copyright 2014 Splunk, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"): you may
+ * not use this file except in compliance with the License. You may obtain
+ * a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ */
+
+using Serilog;
+using System;
+using System.Collections.Concurrent;
+using System.IO;
+using System.Net;
+using System.Net.Security;
+using System.Net.Sockets;
+using System.Security.Authentication;
+using System.Text;
+using System.Text.RegularExpressions;
+using System.Threading;
+using System.Threading.Tasks;
+
+namespace Blog.Core.Serilog.Es.Sinks.TCP
+{
+ ///
+ /// TcpSocketWriter encapsulates queueing strings to be written to a TCP _socket
+ /// and handling reconnections (according to a TcpConnectionPolicy object passed
+ /// to it) when a TCP session drops.
+ ///
+ ///
+ /// TcpSocketWriter maintains a fixed sized queue of strings to be sent via
+ /// the TCP _port and, while the _socket is open, sends them as quickly as possible.
+ ///
+ /// If the TCP session drops, TcpSocketWriter will stop pulling strings off the
+ /// queue until it can reestablish a connection. Any SocketErrors emitted during this
+ /// process will be passed as arguments to invocations of LoggingFailureHandler.
+ /// If the TcpConnectionPolicy.Connect method throws an exception (in particular,
+ /// TcpReconnectFailure to indicate that the policy has reached a point where it
+ /// will no longer try to establish a connection) then the LoggingFailureHandler
+ /// event is invoked, and no further attempt to log anything will be made.
+ ///
+ public class TcpSocketWriter : IDisposable
+ {
+ private readonly FixedSizeQueue _eventQueue;
+ private readonly ExponentialBackoffTcpReconnectionPolicy _reconnectPolicy = new ExponentialBackoffTcpReconnectionPolicy();
+ private readonly CancellationTokenSource _tokenSource; // Must be private or Dispose will not function properly.
+ private readonly TaskCompletionSource _disposed = new TaskCompletionSource();
+
+ private Stream _stream;
+
+ ///
+ /// Event that is invoked when reconnecting after a TCP session is dropped fails.
+ ///
+ public event Action LoggingFailureHandler = ex =>
+ {
+ UnexpectedErrorLogger(
+ ex,
+ (x, socketError) =>
+ {
+ if (socketError == null)
+ {
+ //Log.Error(x, "failure inside TCP socket: {message}", x.Message);
+ }
+ else
+ {
+ //Log.Error(
+ // x,
+ // "failure inside TCP socket: {message} - socket error found {socketErrorCode}",
+ // x.Message,
+ // socketError);
+ }
+
+ });
+ };
+
+ public static void UnexpectedErrorLogger(Exception ex, Action log)
+ {
+ SocketError? socketErrorCode = null;
+ var current = ex;
+ do
+ {
+ if (current is SocketException)
+ {
+ socketErrorCode = ((SocketException) current).SocketErrorCode;
+ }
+
+ current = current.InnerException;
+ } while (socketErrorCode == null && current != null);
+
+ log(ex, socketErrorCode);
+ }
+
+ ///
+ /// Construct a TCP _socket writer that writes to the given endPoint and _port.
+ ///
+ /// Uri to open a TCP socket to.
+ /// The maximum number of log entries to queue before starting to drop entries.
+ public TcpSocketWriter(Uri uri, int maxQueueSize = 5000)
+ {
+ _eventQueue = new FixedSizeQueue(maxQueueSize);
+ _tokenSource = new CancellationTokenSource();
+
+ Func> tryOpenSocket = async h =>
+ {
+ try
+ {
+ TcpClient client = new TcpClient();
+ await client.ConnectAsync(uri.Host, uri.Port);
+ Stream stream = client.GetStream();
+ if (uri.Scheme.ToLower() != "tls")
+ return stream;
+
+ var sslStream = new SslStream(client.GetStream(), false, null, null);
+ await sslStream.AuthenticateAsClientAsync(uri.Host);
+ return sslStream;
+ }
+ catch (Exception e)
+ {
+ LoggingFailureHandler(e);
+ throw;
+ }
+ };
+
+ var threadReady = new TaskCompletionSource();
+
+ Task queueListener = Task.Factory.StartNew(async () =>
+ {
+ try
+ {
+ bool sslEnabled = uri.Scheme.ToLower() == "tls";
+ _stream = await _reconnectPolicy.ConnectAsync(tryOpenSocket, uri, _tokenSource.Token);
+ threadReady.SetResult(true); // Signal the calling thread that we are ready.
+
+ string entry = null;
+ while (_stream != null) // null indicates that the thread has been cancelled and cleaned up.
+ {
+ if (_tokenSource.Token.IsCancellationRequested)
+ {
+ _eventQueue.CompleteAdding();
+ // Post-condition: no further items will be added to the queue, so there will be a finite number of items to handle.
+ while (_eventQueue.Count > 0)
+ {
+ entry = _eventQueue.Dequeue();
+ try
+ {
+ byte[] messsage = Encoding.UTF8.GetBytes(entry);
+ await _stream.WriteAsync(messsage, 0, messsage.Length);
+ await _stream.FlushAsync();
+ }
+ catch (SocketException ex)
+ {
+ LoggingFailureHandler(ex);
+ }
+ }
+ break;
+ }
+ if (entry == null)
+ {
+ entry = _eventQueue.Dequeue(_tokenSource.Token);
+ }
+ else
+ {
+ try
+ {
+ byte[] messsage = Encoding.UTF8.GetBytes(entry);
+ await _stream.WriteAsync(messsage, 0, messsage.Length);
+ await _stream.FlushAsync();
+ // No exception, it was sent
+ entry = null;
+ }
+ catch (IOException ex)
+ {
+ LoggingFailureHandler(ex);
+ _stream = await _reconnectPolicy.ConnectAsync(tryOpenSocket, uri, _tokenSource.Token);
+ }
+ catch (SocketException ex)
+ {
+ LoggingFailureHandler(ex);
+ _stream = await _reconnectPolicy.ConnectAsync(tryOpenSocket, uri, _tokenSource.Token);
+ }
+ }
+ }
+ }
+ catch (Exception e)
+ {
+ LoggingFailureHandler(e);
+ }
+ finally
+ {
+ if (_stream != null)
+ {
+ _stream.Dispose();
+ }
+
+ _disposed.SetResult(true);
+ }
+ }, CancellationToken.None, TaskCreationOptions.LongRunning, TaskScheduler.Default);
+ threadReady.Task.Wait(TimeSpan.FromSeconds(5));
+ }
+
+ public void Dispose()
+ {
+ // The following operations are idempotent. Issue a cancellation to tell the
+ // writer thread to stop the queue from accepting entries and write what it has
+ // before cleaning up, then wait until that cleanup is finished.
+ _tokenSource.Cancel();
+ Task.Run(async () => await _disposed.Task).Wait();
+ }
+
+ ///
+ /// Push a string onto the queue to be written.
+ ///
+ /// The string to be written to the TCP _socket.
+ public void Enqueue(string entry)
+ {
+ _eventQueue.Enqueue(entry);
+ }
+ }
+
+ ///
+ /// TcpConnectionPolicy implementation that tries to reconnect after
+ /// increasingly long intervals.
+ ///
+ ///
+ /// The intervals double every time, starting from 0s, 1s, 2s, 4s, ...
+ /// until 10 minutes between connections, when it plateaus and does
+ /// not increase the interval length any further.
+ ///
+ public class ExponentialBackoffTcpReconnectionPolicy
+ {
+ private readonly int ceiling = 10 * 60; // 10 minutes in seconds
+
+ public async Task ConnectAsync(Func> connect, Uri host, CancellationToken cancellationToken)
+ {
+ int delay = 1; // in seconds
+ while (!cancellationToken.IsCancellationRequested)
+ {
+ try
+ {
+ //Log.Debug("Attempting to connect to TCP endpoint {host} after delay of {delay} seconds", host, delay);
+ return await connect(host);
+ }
+ catch (SocketException) { }
+
+ // If this is cancelled via the cancellationToken instead of
+ // completing its delay, the next while-loop test will fail,
+ // the loop will terminate, and the method will return null
+ // with no additional connection attempts.
+ await Task.Delay(delay * 1000, cancellationToken);
+ // The nth delay is min(10 minutes, 2^n - 1 seconds).
+ delay = Math.Min((delay + 1) * 2 - 1, ceiling);
+ }
+
+ // cancellationToken has been cancelled.
+ return null;
+ }
+ }
+
+ ///
+ /// A queue with a maximum size. When the queue is at its maximum size
+ /// and a new item is queued, the oldest item in the queue is dropped.
+ ///
+ ///
+ internal class FixedSizeQueue
+ {
+ private int Size { get; }
+ private readonly IProgress _progress = new Progress();
+ private bool IsCompleted { get; set; }
+
+ private readonly BlockingCollection _collection = new BlockingCollection();
+
+ public FixedSizeQueue(int size)
+ {
+ Size = size;
+ IsCompleted = false;
+ }
+
+ public void Enqueue(T obj)
+ {
+ lock (this)
+ {
+ if (IsCompleted)
+ {
+ throw new InvalidOperationException("Tried to add an item to a completed queue.");
+ }
+
+ _collection.Add(obj);
+
+ while (_collection.Count > Size)
+ {
+ _collection.Take();
+ }
+ _progress.Report(true);
+ }
+ }
+
+ public void CompleteAdding()
+ {
+ lock (this)
+ {
+ IsCompleted = true;
+ }
+ }
+
+ public T Dequeue(CancellationToken cancellationToken)
+ {
+ return _collection.Take(cancellationToken);
+ }
+
+ public T Dequeue()
+ {
+ return _collection.Take();
+ }
+
+
+ public decimal Count => _collection.Count;
+ }
+}
\ No newline at end of file
diff --git a/Blog.Core.Serilog.Es/Sinks/UDP/UDPSink.cs b/Blog.Core.Serilog.Es/Sinks/UDP/UDPSink.cs
new file mode 100644
index 00000000..f07c24e1
--- /dev/null
+++ b/Blog.Core.Serilog.Es/Sinks/UDP/UDPSink.cs
@@ -0,0 +1,42 @@
+using System;
+using System.IO;
+using System.Net;
+using System.Net.Sockets;
+using System.Text;
+using Serilog.Core;
+using Serilog.Events;
+using Serilog.Formatting;
+
+
+namespace Serilog.Sinks.Network.Sinks.UDP
+{
+ public class UDPSink : ILogEventSink, IDisposable
+ {
+ private Socket _socket = new Socket(SocketType.Dgram, ProtocolType.Udp);
+ private readonly ITextFormatter _formatter;
+
+ public UDPSink(IPAddress ipAddress, int port, ITextFormatter formatter)
+ {
+ _socket.Connect(ipAddress, port);
+ _formatter = formatter;
+ }
+
+ public void Emit(LogEvent logEvent)
+ {
+ var sb = new StringBuilder();
+
+ using (var sw = new StringWriter(sb))
+ _formatter.Format(logEvent, sw);
+
+ sb.Replace("RenderedMessage", "message");
+
+ _socket.Send(Encoding.UTF8.GetBytes(sb.ToString()));
+ }
+
+ public void Dispose()
+ {
+ _socket?.Dispose();
+ _socket = null;
+ }
+ }
+}
diff --git a/Blog.Core.Tests/appsettings.json b/Blog.Core.Tests/appsettings.json
index a1edb353..95a95f16 100644
--- a/Blog.Core.Tests/appsettings.json
+++ b/Blog.Core.Tests/appsettings.json
@@ -197,7 +197,7 @@
"ConsulSetting": {
"ServiceName": "BlogCoreService",
"ServiceIP": "localhost",
- "ServicePort": "8081",
+ "ServicePort": "9291",
"ServiceHealthCheck": "/healthcheck",
"ConsulAddress": "http://localhost:8500"
}
diff --git a/Blog.Core.sln b/Blog.Core.sln
index 2446fd7a..e587ddae 100644
--- a/Blog.Core.sln
+++ b/Blog.Core.sln
@@ -31,6 +31,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "SolutionItems", "SolutionIt
Blog.Core.Publish.Linux.sh = Blog.Core.Publish.Linux.sh
codecov.yml = codecov.yml
CreateYourProject.bat = CreateYourProject.bat
+ DockerBuild.bat = DockerBuild.bat
+ Dockerfile = Dockerfile
nuget.config = nuget.config
README.md = README.md
EndProjectSection
@@ -53,6 +55,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Blog.Core.ConsoleApp", "Blo
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Blog.Core.Gateway", "Blog.Core.Gateway\Blog.Core.Gateway.csproj", "{A11C0DF2-1E13-4EED-BA49-44A57136B189}"
EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Blog.Core.Serilog.Es", "Blog.Core.Serilog.Es\Blog.Core.Serilog.Es.csproj", "{52AFAB53-D1CA-4014-8B63-3550FDCDA6E1}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -111,6 +115,10 @@ Global
{A11C0DF2-1E13-4EED-BA49-44A57136B189}.Debug|Any CPU.Build.0 = Debug|Any CPU
{A11C0DF2-1E13-4EED-BA49-44A57136B189}.Release|Any CPU.ActiveCfg = Release|Any CPU
{A11C0DF2-1E13-4EED-BA49-44A57136B189}.Release|Any CPU.Build.0 = Release|Any CPU
+ {52AFAB53-D1CA-4014-8B63-3550FDCDA6E1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {52AFAB53-D1CA-4014-8B63-3550FDCDA6E1}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {52AFAB53-D1CA-4014-8B63-3550FDCDA6E1}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {52AFAB53-D1CA-4014-8B63-3550FDCDA6E1}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
diff --git a/CreateYourProject.bat b/CreateYourProject.bat
index 43a2a429..8f5b5ca7 100644
--- a/CreateYourProject.bat
+++ b/CreateYourProject.bat
@@ -3,9 +3,9 @@ echo "if u install template error,pls use:>>dotnet new -i .template.config\Blog.
color 3
-dotnet new -i Blog.Core.Webapi.Template::2.5.3
+dotnet new -i Blog.Core.Webapi.Template::2.5.4
-set /p OP=Please set your project name(for example:Baidu.Api):
+set /p OP=Please set your project name(for example:BlogMicService):
md .1YourProject
diff --git a/DockerBuild.bat b/DockerBuild.bat
new file mode 100644
index 00000000..7617488c
--- /dev/null
+++ b/DockerBuild.bat
@@ -0,0 +1,18 @@
+echo off
+echo "Press B to build images, P to push to registry, any other key to cancel"
+set /p op= :
+if "%op%"=="B" goto build
+if "%op%"=="P" goto push
+exit
+
+:build
+docker rmi laozhangisphi/apkimg
+docker build -f "Dockerfile" --force-rm -t laozhangisphi/apkimg .
+goto end
+
+:push
+docker push laozhangisphi/apkimg
+goto end
+
+:end
+pause
\ No newline at end of file
diff --git a/Dockerfile b/Dockerfile
index e6719f2e..7445e602 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -1,7 +1,7 @@
#See https://aka.ms/containerfastmode to understand how Visual Studio uses this Dockerfile to build your images for faster debugging.
#这种模式是直接在构建镜像的内部编译发布dotnet项目。
-#注意下容器内输出端口是8081
+#注意下容器内输出端口是9291
#如果你想先手动dotnet build成可执行的二进制文件,然后再构建镜像,请看.Api层下的dockerfile。
@@ -31,5 +31,5 @@ RUN dotnet publish "Blog.Core.Api.csproj" -c Release -o /app/publish
FROM base AS final
WORKDIR /app
COPY --from=publish /app/publish .
-EXPOSE 8081
+EXPOSE 9291
ENTRYPOINT ["dotnet", "Blog.Core.Api.dll"]
\ No newline at end of file
diff --git a/README.md b/README.md
index af5ee5e4..a83e2042 100644
--- a/README.md
+++ b/README.md
@@ -73,14 +73,18 @@ Blog.Core 开箱即用的企业级前后端分离【 .NET Core5.0 Api + Vue 2.x
- [x] 新增 Redis 消息队列 ✨;
- [x] 新增 RabbitMQ 消息队列 ✨;
- [x] 新增 EventBus 事件总线 ✨;
-- [x] 调试中 - 统一聚合支付;
+- [x] 新增 - 统一聚合支付;
+- [x] 新增 - Nacos注册中心配置;
+- [x] 新增 - ES 搜索配置;
+- [x] 新增 - Apollo 配置;
+- [x] 新增 Kafka 消息队列,并配合实现EventBus ✨;
- [ ] 计划 - 数据部门权限;
-- [ ] 计划 - ES 搜索;
微服务模块:
- [x] 可配合 Docker 实现容器化;
- [x] 可配合 Jenkins 实现CI / CD;
- [x] 可配合 Consul 实现服务发现;
+- [x] 可配合 Nacos 实现服务发现;
- [x] 可配合 Ocelot 实现网关处理;
- [x] 可配合 Nginx 实现负载均衡;
- [x] 可配合 Ids4 实现认证中心;
@@ -94,13 +98,14 @@ Blog.Core 开箱即用的企业级前后端分离【 .NET Core5.0 Api + Vue 2.x
## 贡献者们
-Thanks goes to these wonderful people ([✨](https://github.com/anjoy8/Blog.Core/graphs/contributors)):
+Thanks goes to these wonderful people ([✨](https://github.com/anjoy8/Blog.Core/graphs/contributors)):(排名暂时按提交顺序)
-| [ anjoy8](https://github.com/anjoy8) 💻📖 💡 | [ hudingwen](https://github.com/hudingwen) 💻 👀 | [ binyly ](https://github.com/binyly) 💻 👀 📖 🤔 | [ wuare ](https://github.com/wuare) 💻 🐛 🤔 | [ skang0401 ](https://github.com/skang0401) 📖| [ Jamnine](https://github.com/Jamnine) 💻 🌍|
+| [ anjoy8](https://github.com/anjoy8) 💻📖 💡 | [ hudingwen](https://github.com/hudingwen) 💻 👀 | [ binyly ](https://github.com/binyly) 💻 👀 📖 👍 | [ wuare ](https://github.com/wuare) 💻😀 | [ skang0401 ](https://github.com/skang0401) 📖| [ Jamnine](https://github.com/Jamnine) 💻 🌍|
| :---: | :---: | :---: | :---: | :---: | :---: |
-|[ aion1998 ](https://github.com/aion1998) 🐛|[ RLei123 ](https://github.com/RLei123) 💻|[ cluyun ](https://github.com/cluyun) 🌍|[ blue20171027 ](https://github.com/blue20171027) 💻|[ anewboyz ](https://github.com/anewboyz) 💻|[ jxd728 ](https://github.com/jxd728) 🌍|
-|[ wmchuang ](https://github.com/wmchuang) 🌍|[ liuzhenyulive ](https://github.com/liuzhenyulive) 💻|[ JsonBy ](https://github.com/JsonBy) 💻 💡 🤔|[ hsxian ](https://github.com/hsxian) 🌍|[ cuno92 ](https://github.com/cuno92) 📖|[ 317447880 ](https://github.com/317447880) 💻|
+|[ aion1998 ](https://github.com/aion1998) 👍|[ RLei123 ](https://github.com/RLei123) 😄|[ cluyun ](https://github.com/cluyun) 🍬|[ blue20171027 ](https://github.com/blue20171027) ✈|[ anewboyz ](https://github.com/anewboyz) 💻|[ jxd728 ](https://github.com/jxd728) 🌍|
+|[ wmchuang ](https://github.com/wmchuang) 🍟|[ liuzhenyulive ](https://github.com/liuzhenyulive) 💻|[ JsonBy ](https://github.com/JsonBy) 💻 💡 🤔|[ hsxian ](https://github.com/hsxian) 🎉|[ cuno92 ](https://github.com/cuno92) 📖|[ 317447880 ](https://github.com/317447880) 💻|
+|[ Shuisen ](https://github.com/Shuisen) 💻|[ www5255977 ](https://github.com/www5255977) 🌍|[ 867824092 ](https://github.com/867824092) 🍳|
This project follows the [all-contributors](https://github.com/anjoy8/Blog.Core/graphs/contributors) specification.
From 26ba3b2afb89f1d10055616287e1fa726cd6821f Mon Sep 17 00:00:00 2001
From: hudingwen <765472804@qq.com>
Date: Thu, 2 Sep 2021 15:40:17 +0800
Subject: [PATCH 086/456] fix dependency
---
Blog.Core.Common/Blog.Core.Common.csproj | 1 +
1 file changed, 1 insertion(+)
diff --git a/Blog.Core.Common/Blog.Core.Common.csproj b/Blog.Core.Common/Blog.Core.Common.csproj
index 5bc856c1..27b90d2f 100644
--- a/Blog.Core.Common/Blog.Core.Common.csproj
+++ b/Blog.Core.Common/Blog.Core.Common.csproj
@@ -33,6 +33,7 @@
+
From c332fed2c7fa748b9a8b6d219addac0f421fb91f Mon Sep 17 00:00:00 2001
From: anjoy8 <3143422472@qq.com>
Date: Thu, 9 Sep 2021 14:07:17 +0800
Subject: [PATCH 087/456] Update README.md
---
.docs/contents/Contribution/README.md | 42 +++++++++++++++++++++++++--
1 file changed, 40 insertions(+), 2 deletions(-)
diff --git a/.docs/contents/Contribution/README.md b/.docs/contents/Contribution/README.md
index 027e74b3..0d30f24b 100644
--- a/.docs/contents/Contribution/README.md
+++ b/.docs/contents/Contribution/README.md
@@ -3,7 +3,7 @@
欢迎一起完善文档,
参与打赏的小可爱名单如下(单位:元),你们的贡献是我继续的动力:
-(2021年1月14日 10点25分)
+(2021年9月9日 13点53分)
|序号|微信昵称|助力值|备注|
@@ -99,6 +99,44 @@
|89|Mr * * 宋|50||
|90|布 * * 布|10||
|91|s * * s|6.6||
-|92|V * * V|50||
+|92|V * * V|50||
+|93|o**o|50||
+|94|书**6|6.6||
+|95|精**E|50||
+|96|有**幸|10||
+|97|r**y|10||
+|98|v**c|5||
+|99|j**n|20||
+|100|贾**琪|100||
+|101|a**s|20||
+|102|狂**牛|10||
+|103|风**宜|10||
+|104|鸠**夜|5||
+|105|大**灰|15||
+|106|不**懂|100||
+|107|圣**旨|50||
+|108|A**n|50||
+|109|薛**猫|100||
+|110|岁**叁|10||
+|111|K**g|100||
+|112|琛**田|30||
+|113|L**s|20||
+|114|小**哥|10||
+|115|G**e|10||
+|116|s**o|30||
+|117|大**白|50||
+|118|星**星|20||
+|119|沙**锋|200||
+|120|词**意|11||
+|121|A**N|20||
+|122|像**恋|10||
+|123|M**o|10||
+|124|风**虹|50||
+|125|健**诚|10||
+|126|**|5||
+|127|何**玖|6.66||
+|128|A**g|10||
+|129|高**广|20||
+
From e80dbd575f2042e00336ff47977b72f4fbbf283e Mon Sep 17 00:00:00 2001
From: ansonzhang <3143422472@qq.com>
Date: Fri, 10 Sep 2021 11:25:47 +0800
Subject: [PATCH 088/456] Update dotnetcore.yml
---
.github/workflows/dotnetcore.yml | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/.github/workflows/dotnetcore.yml b/.github/workflows/dotnetcore.yml
index 80289a98..6aed122f 100644
--- a/.github/workflows/dotnetcore.yml
+++ b/.github/workflows/dotnetcore.yml
@@ -15,3 +15,9 @@ jobs:
dotnet-version: 5.0.100
- name: Build with dotnet
run: dotnet build --configuration Release
+ - name: Build image
+ run: docker build -f "Dockerfile" --force-rm -t laozhangisphi/apkimg .
+ - name: Log into registry
+ run: echo "${{ secrets.ACCESS_TOKEN }}" | docker login -u laozhangisphi --password-stdin
+ - name: Push image
+ run: docker push laozhangisphi/apkimg
From c7f022800895cc3cca2021d1d1a88ff0c6eaefb0 Mon Sep 17 00:00:00 2001
From: ansonzhang <3143422472@qq.com>
Date: Fri, 10 Sep 2021 11:45:01 +0800
Subject: [PATCH 089/456] Update README.md
---
README.md | 16 +++++++++++-----
1 file changed, 11 insertions(+), 5 deletions(-)
diff --git a/README.md b/README.md
index a83e2042..205208b9 100644
--- a/README.md
+++ b/README.md
@@ -34,11 +34,17 @@ Blog.Core 开箱即用的企业级前后端分离【 .NET Core5.0 Api + Vue 2.x
-#### 联系我
-如果你对BCVP框架感兴趣,并有一定的框架设计经验,,欢迎加入架构师交流群,只要交流心得都可以进入,如果单纯提问问题的就算了哈。
-
-
-
+#### Dokcer 快速启动
+如果想在服务器或者本地快速查看接口效果,直接Docker启动容器即可:
+```
+ # 可以挂载配置文件和日志文件
+ # 这里只是接口效果,想看前端效果,可以异步Blog.Admin查看后台管理系统
+ docker run --name=apkcontainer -d \
+ -v /data/appsettings.json:/app/appsettings.json \
+ -v /data/Log/:/app/Log \
+ -it -p 9291:9291 laozhangisphi/apkimg
+```
+
### 功能与进度
From a2738e9be9a6a3bd14d7732477d9224d1b8c6d6b Mon Sep 17 00:00:00 2001
From: anjoy8 <3143422472@qq.com>
Date: Wed, 15 Sep 2021 11:49:10 +0800
Subject: [PATCH 090/456] =?UTF-8?q?fix=EF=BC=9Amvp=E9=A1=B9=E7=9B=AE?=
=?UTF-8?q?=E6=8E=A5=E5=8F=A3=EF=BC=8C=E5=80=92=E5=8F=99=E5=8A=A0=E8=BD=BD?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
Blog.Core.Api/Controllers/BlogController.cs | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/Blog.Core.Api/Controllers/BlogController.cs b/Blog.Core.Api/Controllers/BlogController.cs
index 24860971..ecc3a4f8 100644
--- a/Blog.Core.Api/Controllers/BlogController.cs
+++ b/Blog.Core.Api/Controllers/BlogController.cs
@@ -132,7 +132,7 @@ public async Task>> GetBlogsByTypesForMVP(string
{
if (types.IsNotEmptyOrNull())
{
- var blogs = await _blogArticleServices.Query(d => d.bcategory != null && types.Contains(d.bcategory) && d.IsDeleted == false);
+ var blogs = await _blogArticleServices.Query(d => d.bcategory != null && types.Contains(d.bcategory) && d.IsDeleted == false, d => d.bID, false);
return Success(blogs);
}
return Success(new List() { });
From c7f0ca3a6ea64f59fd96b6f6f54dac48d4292e7d Mon Sep 17 00:00:00 2001
From: anjoy8 <3143422472@qq.com>
Date: Wed, 15 Sep 2021 19:27:11 +0800
Subject: [PATCH 091/456] Fixed #209 bug
---
Blog.Core.Api/Controllers/LoginController.cs | 2 +-
.../Authorizations/Helpers/JwtHelper.cs | 12 ++++++++++++
2 files changed, 13 insertions(+), 1 deletion(-)
diff --git a/Blog.Core.Api/Controllers/LoginController.cs b/Blog.Core.Api/Controllers/LoginController.cs
index e007cc6d..afb61c6d 100644
--- a/Blog.Core.Api/Controllers/LoginController.cs
+++ b/Blog.Core.Api/Controllers/LoginController.cs
@@ -204,7 +204,7 @@ public async Task> RefreshToken(string token =
if (string.IsNullOrEmpty(token))
return Failed("token无效,请重新登录!");
var tokenModel = JwtHelper.SerializeJwt(token);
- if (tokenModel != null && tokenModel.Uid > 0)
+ if (tokenModel != null && JwtHelper.customSafeVerify(token) && tokenModel.Uid > 0)
{
var user = await _sysUserInfoServices.QueryById(tokenModel.Uid);
if (user != null)
diff --git a/Blog.Core.Extensions/Authorizations/Helpers/JwtHelper.cs b/Blog.Core.Extensions/Authorizations/Helpers/JwtHelper.cs
index 8efc16a9..46edccbe 100644
--- a/Blog.Core.Extensions/Authorizations/Helpers/JwtHelper.cs
+++ b/Blog.Core.Extensions/Authorizations/Helpers/JwtHelper.cs
@@ -96,6 +96,18 @@ public static TokenModelJwt SerializeJwt(string jwtStr)
}
return tokenModelJwt;
}
+
+ public static bool customSafeVerify(string token)
+ {
+ var jwtHandler = new JwtSecurityTokenHandler();
+ var symmetricKeyAsBase64 = AppSecretConfig.Audience_Secret_String;
+ var keyByteArray = Encoding.ASCII.GetBytes(symmetricKeyAsBase64);
+ var signingKey = new SymmetricSecurityKey(keyByteArray);
+ var signingCredentials = new SigningCredentials(signingKey, SecurityAlgorithms.HmacSha256);
+
+ var jwt = jwtHandler.ReadJwtToken(token);
+ return jwt.RawSignature == Microsoft.IdentityModel.JsonWebTokens.JwtTokenUtilities.CreateEncodedSignature(jwt.RawHeader + "." + jwt.RawPayload, signingCredentials);
+ }
}
///
From b2dbd11f7163758eb907bc2fd4ab34098fd3d6ae Mon Sep 17 00:00:00 2001
From: anjoy8 <3143422472@qq.com>
Date: Thu, 16 Sep 2021 11:26:00 +0800
Subject: [PATCH 092/456] =?UTF-8?q?feat=EF=BC=9Aadd=20access=20trend=20log?=
=?UTF-8?q?=20qurtz?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
Blog.Core.Api/Blog.Core.Model.xml | 50 ++++++++
Blog.Core.Common/LogHelper/LogLock.cs | 6 +-
.../IAccessTrendLogServices.cs | 14 +++
Blog.Core.Model/Models/AccessTrendLog.cs | 57 +++++++++
Blog.Core.Services/AccessTrendLogServices.cs | 18 +++
.../Jobs/Job_AccessTrendLog_Quartz.cs | 118 ++++++++++++++++++
6 files changed, 261 insertions(+), 2 deletions(-)
create mode 100644 Blog.Core.IServices/IAccessTrendLogServices.cs
create mode 100644 Blog.Core.Model/Models/AccessTrendLog.cs
create mode 100644 Blog.Core.Services/AccessTrendLogServices.cs
create mode 100644 Blog.Core.Tasks/QuartzNet/Jobs/Job_AccessTrendLog_Quartz.cs
diff --git a/Blog.Core.Api/Blog.Core.Model.xml b/Blog.Core.Api/Blog.Core.Model.xml
index 575f738b..9dda8493 100644
--- a/Blog.Core.Api/Blog.Core.Model.xml
+++ b/Blog.Core.Api/Blog.Core.Model.xml
@@ -165,6 +165,56 @@
返回数据集合
+
+
+ 用户访问趋势日志
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 创建时间
+
+
广告图片
diff --git a/Blog.Core.Common/LogHelper/LogLock.cs b/Blog.Core.Common/LogHelper/LogLock.cs
index dc2d158a..8aeaac70 100644
--- a/Blog.Core.Common/LogHelper/LogLock.cs
+++ b/Blog.Core.Common/LogHelper/LogLock.cs
@@ -82,7 +82,7 @@ public static void OutSql2Log(string prefix, string[] dataParas, bool IsHeader =
/// 编码
/// 读取类型(0:精准,1:前缀模糊)
///
- public static string ReadLog(string folderPath, string fileName, Encoding encode, ReadType readType = ReadType.Accurate)
+ public static string ReadLog(string folderPath, string fileName, Encoding encode, ReadType readType = ReadType.Accurate, int takeOnlyTop = -1)
{
string s = "";
try
@@ -112,6 +112,8 @@ public static string ReadLog(string folderPath, string fileName, Encoding encode
var allFiles = new DirectoryInfo(folderPath);
var selectFiles = allFiles.GetFiles().Where(fi => fi.Name.ToLower().Contains(fileName.ToLower())).ToList();
+ selectFiles = takeOnlyTop > 0 ? selectFiles.Take(takeOnlyTop).ToList() : selectFiles;
+
foreach (var item in selectFiles)
{
if (File.Exists(item.FullName))
@@ -379,7 +381,7 @@ public static AccessApiDateView AccessApiByDate()
try
{
Logs = GetRequestInfo(ReadType.Prefix);
-
+
apiDates = (from n in Logs
group n by new { n.Date } into g
select new ApiDate
diff --git a/Blog.Core.IServices/IAccessTrendLogServices.cs b/Blog.Core.IServices/IAccessTrendLogServices.cs
new file mode 100644
index 00000000..e902f399
--- /dev/null
+++ b/Blog.Core.IServices/IAccessTrendLogServices.cs
@@ -0,0 +1,14 @@
+using Blog.Core.IServices.BASE;
+using Blog.Core.Model.Models;
+
+namespace Blog.Core.IServices
+{
+ ///
+ /// IAccessTrendLogServices
+ ///
+ public interface IAccessTrendLogServices : IBaseServices
+ {
+
+ }
+}
+
\ No newline at end of file
diff --git a/Blog.Core.Model/Models/AccessTrendLog.cs b/Blog.Core.Model/Models/AccessTrendLog.cs
new file mode 100644
index 00000000..a3924c24
--- /dev/null
+++ b/Blog.Core.Model/Models/AccessTrendLog.cs
@@ -0,0 +1,57 @@
+using SqlSugar;
+using System;
+
+namespace Blog.Core.Model.Models
+{
+ ///
+ /// 用户访问趋势日志
+ ///
+ public class AccessTrendLog : RootEntityTkey
+ {
+ ///
+ ///
+ ///
+ [SugarColumn(Length = 128, IsNullable = true, ColumnDataType = "nvarchar")]
+ public string User { get; set; }
+ ///
+ ///
+ ///
+ [SugarColumn(Length = 128, IsNullable = true, ColumnDataType = "nvarchar")]
+ public string IP { get; set; }
+ ///
+ ///
+ ///
+ [SugarColumn(Length = 128, IsNullable = true, ColumnDataType = "nvarchar")]
+ public string API { get; set; }
+ ///
+ ///
+ ///
+ [SugarColumn(Length = 128, IsNullable = true, ColumnDataType = "nvarchar")]
+ public string BeginTime { get; set; }
+ ///
+ ///
+ ///
+ [SugarColumn(Length = 128, IsNullable = true, ColumnDataType = "nvarchar")]
+ public string OPTime { get; set; }
+ ///
+ ///
+ ///
+ [SugarColumn(Length = 128, IsNullable = true, ColumnDataType = "nvarchar")]
+ public string RequestMethod { get; set; }
+ ///
+ ///
+ ///
+ [SugarColumn(Length = 256, IsNullable = true, ColumnDataType = "nvarchar")]
+ public string RequestData { get; set; }
+ ///
+ ///
+ ///
+ [SugarColumn(Length = 256, IsNullable = true, ColumnDataType = "nvarchar")]
+ public string Agent { get; set; }
+
+ ///
+ /// 创建时间
+ ///
+ public DateTime Createdate { get; set; } = DateTime.Now;
+ }
+}
diff --git a/Blog.Core.Services/AccessTrendLogServices.cs b/Blog.Core.Services/AccessTrendLogServices.cs
new file mode 100644
index 00000000..38c643f4
--- /dev/null
+++ b/Blog.Core.Services/AccessTrendLogServices.cs
@@ -0,0 +1,18 @@
+using Blog.Core.IRepository.Base;
+using Blog.Core.IServices;
+using Blog.Core.Model.Models;
+using Blog.Core.Services.BASE;
+
+namespace Blog.Core.Services
+{
+ public partial class AccessTrendLogServices : BaseServices, IAccessTrendLogServices
+ {
+ IBaseRepository _dal;
+ public AccessTrendLogServices(IBaseRepository dal)
+ {
+ this._dal = dal;
+ base.BaseDal = dal;
+ }
+
+ }
+}
diff --git a/Blog.Core.Tasks/QuartzNet/Jobs/Job_AccessTrendLog_Quartz.cs b/Blog.Core.Tasks/QuartzNet/Jobs/Job_AccessTrendLog_Quartz.cs
new file mode 100644
index 00000000..a2924804
--- /dev/null
+++ b/Blog.Core.Tasks/QuartzNet/Jobs/Job_AccessTrendLog_Quartz.cs
@@ -0,0 +1,118 @@
+using Blog.Core.Common.LogHelper;
+using Blog.Core.IServices;
+using Blog.Core.Model.Models;
+using Microsoft.AspNetCore.Hosting;
+using Newtonsoft.Json;
+using Quartz;
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+///
+/// 这里要注意下,命名空间和程序集是一样的,不然反射不到
+///
+namespace Blog.Core.Tasks
+{
+ public class Job_AccessTrendLog_Quartz : JobBase, IJob
+ {
+ private readonly IAccessTrendLogServices _accessTrendLogServices;
+ private readonly IWebHostEnvironment _environment;
+
+ public Job_AccessTrendLog_Quartz(IAccessTrendLogServices accessTrendLogServices, ITasksQzServices tasksQzServices, IWebHostEnvironment environment)
+ {
+ _accessTrendLogServices = accessTrendLogServices;
+ _environment = environment;
+ _tasksQzServices = tasksQzServices;
+ }
+ public async Task Execute(IJobExecutionContext context)
+ {
+ var executeLog = await ExecuteJob(context, async () => await Run(context));
+ }
+ public async Task Run(IJobExecutionContext context)
+ {
+
+ // 可以直接获取 JobDetail 的值
+ var jobKey = context.JobDetail.Key;
+ var jobId = jobKey.Name;
+ // 也可以通过数据库配置,获取传递过来的参数
+ JobDataMap data = context.JobDetail.JobDataMap;
+
+ var lastestLogDatetime = (await _accessTrendLogServices.Query(null, d => d.Createdate, false)).FirstOrDefault()?.Createdate;
+ if (lastestLogDatetime == null)
+ {
+ lastestLogDatetime = Convert.ToDateTime("2021-08-01");
+ }
+
+ var accLogs = GetAccessLogs().Where(d => d.BeginTime.ObjToDate() >= lastestLogDatetime).ToList();
+
+ var accTrendLogs = new List() { };
+ accLogs.ForEach(m =>
+ {
+ accTrendLogs.Add(new AccessTrendLog()
+ {
+ User = m.User,
+ API = m.API,
+ BeginTime = m.BeginTime,
+ Createdate = DateTime.Now,
+ IP = m.IP,
+ RequestMethod = m.RequestMethod?.Length > 50 ? m.RequestMethod.Substring(0, 50) : m.RequestMethod
+ });
+ });
+
+
+ if (accTrendLogs.Count > 0)
+ {
+ var logsIds = await _accessTrendLogServices.Add(accTrendLogs);
+ }
+ }
+
+ private List GetAccessLogs()
+ {
+ List userAccessModels = new();
+ var accessLogs = LogLock.ReadLog(
+ Path.Combine(_environment.ContentRootPath, "Log"), "RecordAccessLogs_", Encoding.UTF8, ReadType.Prefix
+ ).ObjToString().TrimEnd(',');
+
+ try
+ {
+ return JsonConvert.DeserializeObject>("[" + accessLogs + "]");
+ }
+ catch (Exception)
+ {
+ var accLogArr = accessLogs.Split("\n");
+ foreach (var item in accLogArr)
+ {
+ if (item.ObjToString() != "")
+ {
+ try
+ {
+ var accItem = JsonConvert.DeserializeObject(item.TrimEnd(','));
+ userAccessModels.Add(accItem);
+ }
+ catch (Exception)
+ {
+ }
+ }
+ }
+
+ }
+
+ return userAccessModels;
+ }
+
+ }
+ public class UserAccessFromFIles
+ {
+ public string User { get; set; }
+ public string IP { get; set; }
+ public string API { get; set; }
+ public string BeginTime { get; set; }
+ public string OPTime { get; set; }
+ public string RequestMethod { get; set; } = "";
+ public string Agent { get; set; }
+ }
+
+}
From ad3e1704aab74cb66fb71104de3bcc97dc84fb0e Mon Sep 17 00:00:00 2001
From: anjoy8 <3143422472@qq.com>
Date: Thu, 16 Sep 2021 11:41:59 +0800
Subject: [PATCH 093/456] Update Job_AccessTrendLog_Quartz.cs
---
Blog.Core.Tasks/QuartzNet/Jobs/Job_AccessTrendLog_Quartz.cs | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/Blog.Core.Tasks/QuartzNet/Jobs/Job_AccessTrendLog_Quartz.cs b/Blog.Core.Tasks/QuartzNet/Jobs/Job_AccessTrendLog_Quartz.cs
index a2924804..0e9e06f6 100644
--- a/Blog.Core.Tasks/QuartzNet/Jobs/Job_AccessTrendLog_Quartz.cs
+++ b/Blog.Core.Tasks/QuartzNet/Jobs/Job_AccessTrendLog_Quartz.cs
@@ -73,7 +73,7 @@ private List GetAccessLogs()
{
List userAccessModels = new();
var accessLogs = LogLock.ReadLog(
- Path.Combine(_environment.ContentRootPath, "Log"), "RecordAccessLogs_", Encoding.UTF8, ReadType.Prefix
+ Path.Combine(_environment.ContentRootPath, "Log"), "RecordAccessLogs_", Encoding.UTF8, ReadType.Prefix,2
).ObjToString().TrimEnd(',');
try
From a51c19f72e670340e7726cf50e8307ada050de90 Mon Sep 17 00:00:00 2001
From: anjoy8 <3143422472@qq.com>
Date: Thu, 16 Sep 2021 13:23:43 +0800
Subject: [PATCH 094/456] =?UTF-8?q?fix=EF=BC=9Alog=20bug?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
Blog.Core.Api/Blog.Core.xml | 2 +-
Blog.Core.Common/LogHelper/LogLock.cs | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/Blog.Core.Api/Blog.Core.xml b/Blog.Core.Api/Blog.Core.xml
index 87df176e..69f0c97d 100644
--- a/Blog.Core.Api/Blog.Core.xml
+++ b/Blog.Core.Api/Blog.Core.xml
@@ -695,7 +695,7 @@
Values控制器
-
+
ValuesController
diff --git a/Blog.Core.Common/LogHelper/LogLock.cs b/Blog.Core.Common/LogHelper/LogLock.cs
index 8aeaac70..89b7980b 100644
--- a/Blog.Core.Common/LogHelper/LogLock.cs
+++ b/Blog.Core.Common/LogHelper/LogLock.cs
@@ -112,7 +112,7 @@ public static string ReadLog(string folderPath, string fileName, Encoding encode
var allFiles = new DirectoryInfo(folderPath);
var selectFiles = allFiles.GetFiles().Where(fi => fi.Name.ToLower().Contains(fileName.ToLower())).ToList();
- selectFiles = takeOnlyTop > 0 ? selectFiles.Take(takeOnlyTop).ToList() : selectFiles;
+ selectFiles = takeOnlyTop > 0 ? selectFiles.OrderByDescending(d => d.Name).Take(takeOnlyTop).ToList() : selectFiles;
foreach (var item in selectFiles)
{
From 5c71b10d8e1f4d01c2785024591c19d9986e0d68 Mon Sep 17 00:00:00 2001
From: anjoy8 <3143422472@qq.com>
Date: Thu, 16 Sep 2021 13:29:31 +0800
Subject: [PATCH 095/456] Update Job_AccessTrendLog_Quartz.cs
---
Blog.Core.Tasks/QuartzNet/Jobs/Job_AccessTrendLog_Quartz.cs | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/Blog.Core.Tasks/QuartzNet/Jobs/Job_AccessTrendLog_Quartz.cs b/Blog.Core.Tasks/QuartzNet/Jobs/Job_AccessTrendLog_Quartz.cs
index 0e9e06f6..3facdbb2 100644
--- a/Blog.Core.Tasks/QuartzNet/Jobs/Job_AccessTrendLog_Quartz.cs
+++ b/Blog.Core.Tasks/QuartzNet/Jobs/Job_AccessTrendLog_Quartz.cs
@@ -46,7 +46,7 @@ public async Task Run(IJobExecutionContext context)
lastestLogDatetime = Convert.ToDateTime("2021-08-01");
}
- var accLogs = GetAccessLogs().Where(d => d.BeginTime.ObjToDate() >= lastestLogDatetime).ToList();
+ var accLogs = GetAccessLogs().Where(d => d.User != "" && d.BeginTime.ObjToDate() >= lastestLogDatetime).ToList();
var accTrendLogs = new List() { };
accLogs.ForEach(m =>
@@ -73,7 +73,7 @@ private List GetAccessLogs()
{
List userAccessModels = new();
var accessLogs = LogLock.ReadLog(
- Path.Combine(_environment.ContentRootPath, "Log"), "RecordAccessLogs_", Encoding.UTF8, ReadType.Prefix,2
+ Path.Combine(_environment.ContentRootPath, "Log"), "RecordAccessLogs_", Encoding.UTF8, ReadType.Prefix, 2
).ObjToString().TrimEnd(',');
try
From 71693070a445964cf0424b1af501e49daed960e4 Mon Sep 17 00:00:00 2001
From: anjoy8 <3143422472@qq.com>
Date: Thu, 16 Sep 2021 14:06:59 +0800
Subject: [PATCH 096/456] =?UTF-8?q?feat=EF=BC=9Aadd=20logo=20count?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
Blog.Core.Common/LogHelper/LogLock.cs | 11 +++++++++--
.../QuartzNet/Jobs/Job_AccessTrendLog_Quartz.cs | 15 +++++++++++++++
2 files changed, 24 insertions(+), 2 deletions(-)
diff --git a/Blog.Core.Common/LogHelper/LogLock.cs b/Blog.Core.Common/LogHelper/LogLock.cs
index 89b7980b..b936a262 100644
--- a/Blog.Core.Common/LogHelper/LogLock.cs
+++ b/Blog.Core.Common/LogHelper/LogLock.cs
@@ -22,7 +22,7 @@ public LogLock(string contentPath)
_contentRoot = contentPath;
}
- public static void OutSql2Log(string prefix, string[] dataParas, bool IsHeader = true)
+ public static void OutSql2Log(string prefix, string[] dataParas, bool IsHeader = true, bool isWrt = false)
{
try
{
@@ -55,8 +55,15 @@ public static void OutSql2Log(string prefix, string[] dataParas, bool IsHeader =
//{
// logContent = logContent.Substring(0, 500) + "\r\n";
//}
+ if (isWrt)
+ {
+ File.WriteAllText(logFilePath, logContent);
- File.AppendAllText(logFilePath, logContent);
+ }
+ else
+ {
+ File.AppendAllText(logFilePath, logContent);
+ }
WritedCount++;
}
catch (Exception e)
diff --git a/Blog.Core.Tasks/QuartzNet/Jobs/Job_AccessTrendLog_Quartz.cs b/Blog.Core.Tasks/QuartzNet/Jobs/Job_AccessTrendLog_Quartz.cs
index 3facdbb2..f2c28c53 100644
--- a/Blog.Core.Tasks/QuartzNet/Jobs/Job_AccessTrendLog_Quartz.cs
+++ b/Blog.Core.Tasks/QuartzNet/Jobs/Job_AccessTrendLog_Quartz.cs
@@ -67,6 +67,21 @@ public async Task Run(IJobExecutionContext context)
{
var logsIds = await _accessTrendLogServices.Add(accTrendLogs);
}
+
+ var accessLogsToday = await _accessTrendLogServices.Query();
+ var activeUsers = (from n in accessLogsToday
+ group n by new { n.User } into g
+ select new ActiveUserVM
+ {
+ user = g.Key.User,
+ count = g.Count(),
+ }).ToList();
+ activeUsers = activeUsers.OrderByDescending(d => d.count).Take(10).ToList();
+
+ Parallel.For(0, 1, e =>
+ {
+ LogLock.OutSql2Log("ACCESSTRENDLOG", new string[] { JsonConvert.SerializeObject(activeUsers) }, false, true);
+ });
}
private List GetAccessLogs()
From 6696cb1cc94be013f6e50018f0f2dbfb72218c33 Mon Sep 17 00:00:00 2001
From: anjoy8 <3143422472@qq.com>
Date: Thu, 16 Sep 2021 14:46:06 +0800
Subject: [PATCH 097/456] =?UTF-8?q?feat=EF=BC=9Aadd=20access=20log=20trend?=
=?UTF-8?q?=20in=20index=20page?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
Blog.Core.Api/Blog.Core.xml | 2 +-
.../Controllers/MonitorController.cs | 36 ++++++++++++++++++-
2 files changed, 36 insertions(+), 2 deletions(-)
diff --git a/Blog.Core.Api/Blog.Core.xml b/Blog.Core.Api/Blog.Core.xml
index 69f0c97d..87df176e 100644
--- a/Blog.Core.Api/Blog.Core.xml
+++ b/Blog.Core.Api/Blog.Core.xml
@@ -695,7 +695,7 @@
Values控制器
-
+
ValuesController
diff --git a/Blog.Core.Api/Controllers/MonitorController.cs b/Blog.Core.Api/Controllers/MonitorController.cs
index 28ff3265..350013bd 100644
--- a/Blog.Core.Api/Controllers/MonitorController.cs
+++ b/Blog.Core.Api/Controllers/MonitorController.cs
@@ -137,6 +137,38 @@ private List GetAccessLogsToday(IWebHostEnvironment environment
return userAccessModels;
}
+ private List GetAccessLogsTrend(IWebHostEnvironment environment)
+ {
+ List userAccessModels = new();
+ var accessLogs = LogLock.ReadLog(
+ Path.Combine(environment.ContentRootPath, "Log"), "ACCESSTRENDLOG_", Encoding.UTF8, ReadType.PrefixLatest
+ ).ObjToString();
+ try
+ {
+ return JsonConvert.DeserializeObject>(accessLogs);
+ }
+ catch (Exception)
+ {
+ var accLogArr = accessLogs.Split("\n");
+ foreach (var item in accLogArr)
+ {
+ if (item.ObjToString() != "")
+ {
+ try
+ {
+ var accItem = JsonConvert.DeserializeObject(item.TrimStart('[').TrimEnd(']'));
+ userAccessModels.Add(accItem);
+ }
+ catch (Exception)
+ {
+ }
+ }
+ }
+
+ }
+
+ return userAccessModels;
+ }
[HttpGet]
public MessageModel GetActiveUsers([FromServices] IWebHostEnvironment environment)
@@ -169,7 +201,8 @@ public MessageModel GetActiveUsers([FromServices] IWebHostEnvir
activeUsers = activeUsers,
activeUserCount = activeUsersCount,
errorCount = errorCountToday,
- logs = Logs
+ logs = Logs,
+ activeCount = GetAccessLogsTrend(environment)
}
};
}
@@ -223,6 +256,7 @@ public class WelcomeInitData
public int activeUserCount { get; set; }
public List logs { get; set; }
public int errorCount { get; set; }
+ public List activeCount { get; set; }
}
}
From 698b3da74343286761e45c07746313650fefe377 Mon Sep 17 00:00:00 2001
From: ansonzhang <3143422472@qq.com>
Date: Fri, 17 Sep 2021 00:18:08 +0800
Subject: [PATCH 098/456] Update README.md
---
README.md | 9 +++++++++
1 file changed, 9 insertions(+)
diff --git a/README.md b/README.md
index 205208b9..772ac302 100644
--- a/README.md
+++ b/README.md
@@ -29,6 +29,15 @@ Blog.Core 开箱即用的企业级前后端分离【 .NET Core5.0 Api + Vue 2.x
项目单体部署,并发在400~500,一切正常(不保证自己的各种错误写法)。
如果搭配负载,效果更好。
+
+#### ❤ 真实用户反馈 ❤
+```
+1、A~CoderDong:
+应用场景:使用Blog.Core为基础骨架开发,搭建Client监控类守护进程项目,To C 客户群,
+并发情况:目前压测并发5000正常8秒处理完,并发10000可15秒处理完毕,异常不会丢失。
+生产配置:一台服务器(Linux环境 + 强2核的16G内存 + mysql数据库 + 3台Nginx负载)
+
+```
From c8125fad1acab71fafe3bc586a9204a3dac8915a Mon Sep 17 00:00:00 2001
From: anjoy8 <3143422472@qq.com>
Date: Fri, 17 Sep 2021 15:25:19 +0800
Subject: [PATCH 099/456] fix: accessTrend Table
---
Blog.Core.Api/Blog.Core.Model.xml | 40 ++-----------
Blog.Core.Model/Models/AccessTrendLog.cs | 42 ++------------
.../Jobs/Job_AccessTrendLog_Quartz.cs | 56 ++++++++++---------
3 files changed, 41 insertions(+), 97 deletions(-)
diff --git a/Blog.Core.Api/Blog.Core.Model.xml b/Blog.Core.Api/Blog.Core.Model.xml
index 9dda8493..695e6cd8 100644
--- a/Blog.Core.Api/Blog.Core.Model.xml
+++ b/Blog.Core.Api/Blog.Core.Model.xml
@@ -172,47 +172,17 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+ 用户
-
+
-
+ 次数
-
+
-
-
-
-
-
- 创建时间
+ 更新时间
diff --git a/Blog.Core.Model/Models/AccessTrendLog.cs b/Blog.Core.Model/Models/AccessTrendLog.cs
index a3924c24..0bad6836 100644
--- a/Blog.Core.Model/Models/AccessTrendLog.cs
+++ b/Blog.Core.Model/Models/AccessTrendLog.cs
@@ -9,49 +9,19 @@ namespace Blog.Core.Model.Models
public class AccessTrendLog : RootEntityTkey
{
///
- ///
+ /// 用户
///
[SugarColumn(Length = 128, IsNullable = true, ColumnDataType = "nvarchar")]
public string User { get; set; }
+
///
- ///
- ///
- [SugarColumn(Length = 128, IsNullable = true, ColumnDataType = "nvarchar")]
- public string IP { get; set; }
- ///
- ///
- ///
- [SugarColumn(Length = 128, IsNullable = true, ColumnDataType = "nvarchar")]
- public string API { get; set; }
- ///
- ///
- ///
- [SugarColumn(Length = 128, IsNullable = true, ColumnDataType = "nvarchar")]
- public string BeginTime { get; set; }
- ///
- ///
- ///
- [SugarColumn(Length = 128, IsNullable = true, ColumnDataType = "nvarchar")]
- public string OPTime { get; set; }
- ///
- ///
- ///
- [SugarColumn(Length = 128, IsNullable = true, ColumnDataType = "nvarchar")]
- public string RequestMethod { get; set; }
- ///
- ///
- ///
- [SugarColumn(Length = 256, IsNullable = true, ColumnDataType = "nvarchar")]
- public string RequestData { get; set; }
- ///
- ///
+ /// 次数
///
- [SugarColumn(Length = 256, IsNullable = true, ColumnDataType = "nvarchar")]
- public string Agent { get; set; }
+ public int Count { get; set; }
///
- /// 创建时间
+ /// 更新时间
///
- public DateTime Createdate { get; set; } = DateTime.Now;
+ public DateTime UpdateTime { get; set; } = DateTime.Now;
}
}
diff --git a/Blog.Core.Tasks/QuartzNet/Jobs/Job_AccessTrendLog_Quartz.cs b/Blog.Core.Tasks/QuartzNet/Jobs/Job_AccessTrendLog_Quartz.cs
index f2c28c53..cd093d1d 100644
--- a/Blog.Core.Tasks/QuartzNet/Jobs/Job_AccessTrendLog_Quartz.cs
+++ b/Blog.Core.Tasks/QuartzNet/Jobs/Job_AccessTrendLog_Quartz.cs
@@ -40,47 +40,51 @@ public async Task Run(IJobExecutionContext context)
// 也可以通过数据库配置,获取传递过来的参数
JobDataMap data = context.JobDetail.JobDataMap;
- var lastestLogDatetime = (await _accessTrendLogServices.Query(null, d => d.Createdate, false)).FirstOrDefault()?.Createdate;
+ var lastestLogDatetime = (await _accessTrendLogServices.Query(null, d => d.UpdateTime, false)).FirstOrDefault()?.UpdateTime;
if (lastestLogDatetime == null)
{
- lastestLogDatetime = Convert.ToDateTime("2021-08-01");
+ lastestLogDatetime = Convert.ToDateTime("2021-09-01");
}
var accLogs = GetAccessLogs().Where(d => d.User != "" && d.BeginTime.ObjToDate() >= lastestLogDatetime).ToList();
+ var logUpdate = DateTime.Now;
- var accTrendLogs = new List() { };
- accLogs.ForEach(m =>
- {
- accTrendLogs.Add(new AccessTrendLog()
- {
- User = m.User,
- API = m.API,
- BeginTime = m.BeginTime,
- Createdate = DateTime.Now,
- IP = m.IP,
- RequestMethod = m.RequestMethod?.Length > 50 ? m.RequestMethod.Substring(0, 50) : m.RequestMethod
- });
- });
-
-
- if (accTrendLogs.Count > 0)
- {
- var logsIds = await _accessTrendLogServices.Add(accTrendLogs);
- }
-
- var accessLogsToday = await _accessTrendLogServices.Query();
- var activeUsers = (from n in accessLogsToday
+ var activeUsers = (from n in accLogs
group n by new { n.User } into g
select new ActiveUserVM
{
user = g.Key.User,
count = g.Count(),
}).ToList();
- activeUsers = activeUsers.OrderByDescending(d => d.count).Take(10).ToList();
+
+ foreach (var item in activeUsers)
+ {
+ var user = (await _accessTrendLogServices.Query(d => d.User != "" && d.User == item.user)).FirstOrDefault();
+ if (user != null)
+ {
+ user.Count += item.count;
+ user.UpdateTime = logUpdate;
+ }
+ await _accessTrendLogServices.Update(user);
+ }
+
+ // 重新拉取
+ var actUsers = await _accessTrendLogServices.Query(d => d.User != "", d => d.Count, false);
+ actUsers = actUsers.Take(10).ToList();
+
+ List activeUserVMs = new();
+ foreach (var item in actUsers)
+ {
+ activeUserVMs.Add(new ActiveUserVM()
+ {
+ user = item.User,
+ count = item.Count
+ });
+ }
Parallel.For(0, 1, e =>
{
- LogLock.OutSql2Log("ACCESSTRENDLOG", new string[] { JsonConvert.SerializeObject(activeUsers) }, false, true);
+ LogLock.OutSql2Log("ACCESSTRENDLOG", new string[] { JsonConvert.SerializeObject(activeUserVMs) }, false, true);
});
}
From b2fd03d9ba0c0afa749ad299ee6469e89bae9bf0 Mon Sep 17 00:00:00 2001
From: anjoy8 <3143422472@qq.com>
Date: Fri, 17 Sep 2021 15:38:15 +0800
Subject: [PATCH 100/456] Update Job_AccessTrendLog_Quartz.cs
---
.../QuartzNet/Jobs/Job_AccessTrendLog_Quartz.cs | 11 ++++++++++-
1 file changed, 10 insertions(+), 1 deletion(-)
diff --git a/Blog.Core.Tasks/QuartzNet/Jobs/Job_AccessTrendLog_Quartz.cs b/Blog.Core.Tasks/QuartzNet/Jobs/Job_AccessTrendLog_Quartz.cs
index cd093d1d..09a3c6ac 100644
--- a/Blog.Core.Tasks/QuartzNet/Jobs/Job_AccessTrendLog_Quartz.cs
+++ b/Blog.Core.Tasks/QuartzNet/Jobs/Job_AccessTrendLog_Quartz.cs
@@ -64,8 +64,17 @@ public async Task Run(IJobExecutionContext context)
{
user.Count += item.count;
user.UpdateTime = logUpdate;
+ await _accessTrendLogServices.Update(user);
+ }
+ else
+ {
+ await _accessTrendLogServices.Add(new AccessTrendLog()
+ {
+ Count = item.count,
+ UpdateTime = logUpdate,
+ User = item.user
+ });
}
- await _accessTrendLogServices.Update(user);
}
// 重新拉取
From 0edd932836e68a5bdb502c85fcb0a65558724418 Mon Sep 17 00:00:00 2001
From: ansonzhang <3143422472@qq.com>
Date: Fri, 17 Sep 2021 17:35:12 +0800
Subject: [PATCH 101/456] Update README.md
---
README.md | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/README.md b/README.md
index 772ac302..c75235b0 100644
--- a/README.md
+++ b/README.md
@@ -34,8 +34,8 @@ Blog.Core 开箱即用的企业级前后端分离【 .NET Core5.0 Api + Vue 2.x
```
1、A~CoderDong:
应用场景:使用Blog.Core为基础骨架开发,搭建Client监控类守护进程项目,To C 客户群,
-并发情况:目前压测并发5000正常8秒处理完,并发10000可15秒处理完毕,异常不会丢失。
-生产配置:一台服务器(Linux环境 + 强2核的16G内存 + mysql数据库 + 3台Nginx负载)
+并发情况:目前压测并发5k正常8秒处理完,并发10k可15秒处理完毕,异常不会丢失。
+生产配置:一台服务器(Linux环境 + 至强8核的16G内存 + mysql数据库 + 3台Nginx负载)
```
From 194ec3d48123e1067d8476cf5c91e755c242d0bf Mon Sep 17 00:00:00 2001
From: anjoy8 <3143422472@qq.com>
Date: Sat, 18 Sep 2021 09:28:46 +0800
Subject: [PATCH 102/456] Update Job_AccessTrendLog_Quartz.cs
---
Blog.Core.Tasks/QuartzNet/Jobs/Job_AccessTrendLog_Quartz.cs | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/Blog.Core.Tasks/QuartzNet/Jobs/Job_AccessTrendLog_Quartz.cs b/Blog.Core.Tasks/QuartzNet/Jobs/Job_AccessTrendLog_Quartz.cs
index 09a3c6ac..225266b6 100644
--- a/Blog.Core.Tasks/QuartzNet/Jobs/Job_AccessTrendLog_Quartz.cs
+++ b/Blog.Core.Tasks/QuartzNet/Jobs/Job_AccessTrendLog_Quartz.cs
@@ -79,7 +79,7 @@ await _accessTrendLogServices.Add(new AccessTrendLog()
// 重新拉取
var actUsers = await _accessTrendLogServices.Query(d => d.User != "", d => d.Count, false);
- actUsers = actUsers.Take(10).ToList();
+ actUsers = actUsers.Take(15).ToList();
List activeUserVMs = new();
foreach (var item in actUsers)
From 289a17b748e809f3aeea16e7dec0a6714b4a8440 Mon Sep 17 00:00:00 2001
From: anjoy8 <3143422472@qq.com>
Date: Sun, 26 Sep 2021 13:30:41 +0800
Subject: [PATCH 103/456] Fixed #210 bug
---
Blog.Core.Model/Models/sysUserInfo.cs | 1 +
1 file changed, 1 insertion(+)
diff --git a/Blog.Core.Model/Models/sysUserInfo.cs b/Blog.Core.Model/Models/sysUserInfo.cs
index 65b37161..acaae690 100644
--- a/Blog.Core.Model/Models/sysUserInfo.cs
+++ b/Blog.Core.Model/Models/sysUserInfo.cs
@@ -7,6 +7,7 @@ namespace Blog.Core.Model.Models
///
/// 用户信息表
///
+ [SugarTable("SysUserInfo")]
public class sysUserInfo : sysUserInfoRoot
{
public sysUserInfo() { }
From 98068d795c174dd93d3769d65cfc289507ca2a68 Mon Sep 17 00:00:00 2001
From: hudingwen <765472804@qq.com>
Date: Fri, 8 Oct 2021 15:32:11 +0800
Subject: [PATCH 104/456] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E5=8A=A8=E6=80=81lin?=
=?UTF-8?q?q=E6=9F=A5=E8=AF=A2=20=E6=B7=BB=E5=8A=A0=E5=BE=AE=E4=BF=A1?=
=?UTF-8?q?=E7=AE=A1=E7=90=86?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
Blog.Core.Api/Blog.Core.Model.xml | 1973 +++++++++++++----
Blog.Core.Api/Blog.Core.xml | 301 +++
.../Controllers/PermissionController.cs | 16 +-
.../Controllers/WeChatCompanyController.cs | 94 +
.../Controllers/WeChatConfigController.cs | 94 +
Blog.Core.Api/Controllers/WeChatController.cs | 187 ++
.../Controllers/WeChatPushLogController.cs | 94 +
.../Controllers/WeChatSubController.cs | 94 +
Blog.Core.Api/Properties/launchSettings.json | 2 +-
Blog.Core.Api/Startup.cs | 4 +-
Blog.Core.Api/appsettings.Development.json | 3 +
Blog.Core.Api/appsettings.json | 2 +-
.../wwwroot/BlogCore.Data.json/Modules.tsv | 397 ++++
.../wwwroot/BlogCore.Data.json/Permission.tsv | 597 ++++-
Blog.Core.Common/Helper/DynamicLinqFactory.cs | 551 +++++
Blog.Core.Common/Helper/HttpHelper.cs | 9 +-
Blog.Core.Common/Helper/JsonConfigUtils.cs | 2 +-
Blog.Core.Common/Helper/LinqHelper.cs | 31 +
Blog.Core.Common/Helper/MD5Hepler.cs | 33 +-
Blog.Core.Common/Helper/WeChatHelper.cs | 312 +++
.../ServiceExtensions/AppConfigSetup.cs | 2 +-
Blog.Core.IServices/BASE/IBaseServices.cs | 1 +
Blog.Core.IServices/IWeChatCompanyServices.cs | 16 +
Blog.Core.IServices/IWeChatConfigServices.cs | 102 +
Blog.Core.IServices/IWeChatPushLogServices.cs | 16 +
Blog.Core.IServices/IWeChatSubServices.cs | 16 +
Blog.Core.Model/Models/Advertisement.cs | 8 +-
Blog.Core.Model/Models/BlogArticle.cs | 10 +-
Blog.Core.Model/Models/Guestbook.cs | 10 +-
Blog.Core.Model/Models/ModulePermission.cs | 4 +-
Blog.Core.Model/Models/Modules.cs | 20 +-
Blog.Core.Model/Models/OperateLog.cs | 12 +-
Blog.Core.Model/Models/PasswordLib.cs | 12 +-
Blog.Core.Model/Models/Permission.cs | 14 +-
Blog.Core.Model/Models/Role.cs | 6 +-
.../Models/RoleModulePermission.cs | 4 +-
Blog.Core.Model/Models/TasksQz.cs | 12 +-
Blog.Core.Model/Models/Topic.cs | 10 +-
Blog.Core.Model/Models/TopicDetail.cs | 12 +-
Blog.Core.Model/Models/UserRole.cs | 4 +-
Blog.Core.Model/Models/WeChatCompany.cs | 75 +
Blog.Core.Model/Models/WeChatConfig.cs | 110 +
Blog.Core.Model/Models/WeChatPushLog.cs | 116 +
Blog.Core.Model/Models/WeChatQR.cs | 96 +
Blog.Core.Model/Models/WeChatSub.cs | 104 +
Blog.Core.Model/Models/WeChatUploadFile.cs | 92 +
Blog.Core.Model/Models/sysUserInfo.cs | 12 +-
Blog.Core.Model/PaginationModel.cs | 31 +
Blog.Core.Model/ViewModels/WeChatApiDto.cs | 116 +
.../ViewModels/WeChatCardMsgDataDto.cs | 23 +
.../ViewModels/WeChatCardMsgDataOpenIDDto.cs | 23 +
.../ViewModels/WeChatCardMsgDetailDto.cs | 80 +
.../ViewModels/WeChatMenuButtonDto.cs | 18 +
Blog.Core.Model/ViewModels/WeChatMenuDto.cs | 18 +
.../ViewModels/WeChatOpenIDsDto.cs | 14 +
.../ViewModels/WeChatPushCardMsgDetailDto.cs | 22 +
.../ViewModels/WeChatPushCardMsgDto.cs | 31 +
.../WeChatPushCardMsgValueColorDto.cs | 23 +
.../ViewModels/WeChatPushLinkMsgContentDto.cs | 26 +
.../ViewModels/WeChatPushPictureContentDto.cs | 14 +
.../ViewModels/WeChatPushTestDto.cs | 61 +
.../ViewModels/WeChatPushTextContentDto.cs | 14 +
.../ViewModels/WeChatPushVideoContentDto.cs | 22 +
.../ViewModels/WeChatPushVoiceContentDto.cs | 14 +
.../ViewModels/WeChatQRActionDto.cs | 14 +
.../ViewModels/WeChatQRActionInfoDto.cs | 14 +
Blog.Core.Model/ViewModels/WeChatQRDto.cs | 16 +
.../ViewModels/WeChatResponseUserInfo.cs | 28 +
.../ViewModels/WeChatTemplateList.cs | 15 +
Blog.Core.Model/ViewModels/WeChatUserInfo.cs | 31 +
.../ViewModels/WeChatUserInfoOpenID.cs | 23 +
Blog.Core.Model/ViewModels/WeChatValidDto.cs | 37 +
Blog.Core.Model/ViewModels/WeChatXMLDto.cs | 118 +
Blog.Core.Serilog.Es/HttpInfo/ParamsHelper.cs | 2 +-
Blog.Core.Services/BASE/BaseServices.cs | 8 +-
Blog.Core.Services/WeChatCompanyServices.cs | 34 +
Blog.Core.Services/WeChatConfigServices.cs | 906 ++++++++
Blog.Core.Services/WeChatPushLogServices.cs | 34 +
Blog.Core.Services/WeChatSubServices.cs | 34 +
79 files changed, 7075 insertions(+), 481 deletions(-)
create mode 100644 Blog.Core.Api/Controllers/WeChatCompanyController.cs
create mode 100644 Blog.Core.Api/Controllers/WeChatConfigController.cs
create mode 100644 Blog.Core.Api/Controllers/WeChatController.cs
create mode 100644 Blog.Core.Api/Controllers/WeChatPushLogController.cs
create mode 100644 Blog.Core.Api/Controllers/WeChatSubController.cs
create mode 100644 Blog.Core.Api/appsettings.Development.json
create mode 100644 Blog.Core.Common/Helper/DynamicLinqFactory.cs
create mode 100644 Blog.Core.Common/Helper/LinqHelper.cs
create mode 100644 Blog.Core.Common/Helper/WeChatHelper.cs
create mode 100644 Blog.Core.IServices/IWeChatCompanyServices.cs
create mode 100644 Blog.Core.IServices/IWeChatConfigServices.cs
create mode 100644 Blog.Core.IServices/IWeChatPushLogServices.cs
create mode 100644 Blog.Core.IServices/IWeChatSubServices.cs
create mode 100644 Blog.Core.Model/Models/WeChatCompany.cs
create mode 100644 Blog.Core.Model/Models/WeChatConfig.cs
create mode 100644 Blog.Core.Model/Models/WeChatPushLog.cs
create mode 100644 Blog.Core.Model/Models/WeChatQR.cs
create mode 100644 Blog.Core.Model/Models/WeChatSub.cs
create mode 100644 Blog.Core.Model/Models/WeChatUploadFile.cs
create mode 100644 Blog.Core.Model/PaginationModel.cs
create mode 100644 Blog.Core.Model/ViewModels/WeChatApiDto.cs
create mode 100644 Blog.Core.Model/ViewModels/WeChatCardMsgDataDto.cs
create mode 100644 Blog.Core.Model/ViewModels/WeChatCardMsgDataOpenIDDto.cs
create mode 100644 Blog.Core.Model/ViewModels/WeChatCardMsgDetailDto.cs
create mode 100644 Blog.Core.Model/ViewModels/WeChatMenuButtonDto.cs
create mode 100644 Blog.Core.Model/ViewModels/WeChatMenuDto.cs
create mode 100644 Blog.Core.Model/ViewModels/WeChatOpenIDsDto.cs
create mode 100644 Blog.Core.Model/ViewModels/WeChatPushCardMsgDetailDto.cs
create mode 100644 Blog.Core.Model/ViewModels/WeChatPushCardMsgDto.cs
create mode 100644 Blog.Core.Model/ViewModels/WeChatPushCardMsgValueColorDto.cs
create mode 100644 Blog.Core.Model/ViewModels/WeChatPushLinkMsgContentDto.cs
create mode 100644 Blog.Core.Model/ViewModels/WeChatPushPictureContentDto.cs
create mode 100644 Blog.Core.Model/ViewModels/WeChatPushTestDto.cs
create mode 100644 Blog.Core.Model/ViewModels/WeChatPushTextContentDto.cs
create mode 100644 Blog.Core.Model/ViewModels/WeChatPushVideoContentDto.cs
create mode 100644 Blog.Core.Model/ViewModels/WeChatPushVoiceContentDto.cs
create mode 100644 Blog.Core.Model/ViewModels/WeChatQRActionDto.cs
create mode 100644 Blog.Core.Model/ViewModels/WeChatQRActionInfoDto.cs
create mode 100644 Blog.Core.Model/ViewModels/WeChatQRDto.cs
create mode 100644 Blog.Core.Model/ViewModels/WeChatResponseUserInfo.cs
create mode 100644 Blog.Core.Model/ViewModels/WeChatTemplateList.cs
create mode 100644 Blog.Core.Model/ViewModels/WeChatUserInfo.cs
create mode 100644 Blog.Core.Model/ViewModels/WeChatUserInfoOpenID.cs
create mode 100644 Blog.Core.Model/ViewModels/WeChatValidDto.cs
create mode 100644 Blog.Core.Model/ViewModels/WeChatXMLDto.cs
create mode 100644 Blog.Core.Services/WeChatCompanyServices.cs
create mode 100644 Blog.Core.Services/WeChatConfigServices.cs
create mode 100644 Blog.Core.Services/WeChatPushLogServices.cs
create mode 100644 Blog.Core.Services/WeChatSubServices.cs
diff --git a/Blog.Core.Api/Blog.Core.Model.xml b/Blog.Core.Api/Blog.Core.Model.xml
index 4befdebc..3984a3cb 100644
--- a/Blog.Core.Api/Blog.Core.Model.xml
+++ b/Blog.Core.Api/Blog.Core.Model.xml
@@ -861,873 +861,2066 @@
修改时间
-
+
- ID
+
-
+
- 菜单与按钮关系表
- 父类
+ 公司ID
+
+
+
+
+ 公司名称
-
+
- 菜单ID
+ 公司IP
-
+
- 按钮ID
+ 公司备注
-
+
- 接口API地址信息表
- 父类
+ api地址
-
+
- 父ID
+ 是否激活
-
+
- 路由菜单表
+ 创建者id
-
+
- 上一级菜单(0表示上一级无菜单)
+ 创建人
-
+
- 接口api
+ 创建时间
-
+
- 按钮跟权限关联表
- 父类
+ 修改者id
-
+
- 角色ID
+ 修改人
-
+
- 菜单ID
+ 修改时间
-
+
- api ID
+
-
+
- ID
- 泛型主键Tkey
+ 微信公众号唯一标识
-
+
- 用户信息表
+ 微信公众号名称
-
+
- uID
- 泛型主键Tkey
+ 微信账号
-
+
- Tibug 博文
+ 微信名称
-
+
- 用户跟角色关联表
- 父类
+ 应用ID
-
+
- 用户ID
+ 应用秘钥
-
+
- 角色ID
+ 公众号推送token
-
+
- 通用分页信息类
+ 验证秘钥(验证消息是否真实)
-
+
- 当前页标
+ 微信公众号token过期时间
-
+
- 总页数
+ 备注
-
+
- 数据总数
+ 是否激活
-
+
- 每页大小
+ 创建者id
-
+
- 返回数据
+ 创建人
-
+
- 无权限
+ 创建时间
-
+
- 找不到指定资源
+ 修改者id
-
+
- 找不到指定资源
+ 修改人
-
+
- 表格数据,支持分页
+ 修改时间
-
+
- 返回编码
+
-
+
- 返回信息
+ 推送ID
-
+
- 记录总数
+ 来自谁
-
+
- 返回数据集
+ 推送IP
-
+
- 广告类
+ 推送客户
-
+
- 分类ID
+ 推送用户
-
+
- 创建时间
+ 推送模板ID
-
+
- 广告图片
+ 推送内容
-
+
- 广告标题
+ 推送时间
-
+
- 广告链接
+ 推送状态(Y/N)
-
+
备注
-
+
- 博客信息展示类
+ 推送OpenID
-
+
-
+ 推送微信公众号
-
- 创建人
-
+
+
+ 创建者id
-
- 博客标题
-
+
+
+ 创建人
-
- 摘要
+
+
+ 创建时间
+
+
+
+
+ 修改者id
+
+
+
+
+ 修改人
+
+
+
+
+ 修改时间
+
+
+
+
-
+
- 上一篇
+ 主键id,ticket
-
+
- 上一篇id
+ 需要绑定的公司
-
+
- 下一篇
+ 需要绑定的员工id
-
+
- 下一篇id
+ 需要绑定的员工昵称
-
- 类别
-
+
+
+ 创建时间
-
- 内容
-
+
+
+ 关联的公众号
-
+
- 访问量
+ 是否已使用
-
+
- 评论数量
+ 使用时间
-
- 修改时间
-
+
+
+ 关联的微信用户id
-
+
+
+ 创建者id
+
+
+
+
+ 创建人
+
+
+
创建时间
-
- 备注
-
+
+
+ 修改者id
-
+
- 留言信息展示类
+ 修改人
-
- 留言表
-
+
+
+ 修改时间
-
- 博客ID
+
+
-
- 创建时间
-
+
+
+ 来自哪个公众号
-
- 手机
-
+
+
+ 绑定公司id
-
- qq
-
+
+
+ 绑定员工id
-
- 留言内容
-
+
+
+ 绑定微信id
-
- ip地址
-
+
+
+ 绑定微信联合id
-
- 是否显示在前台,0否1是
-
+
+
+ 绑定时间
-
+
- 商户号
-
+ 更新时间
+
-
+
- 柜台号
-
+ 备注
+
-
+
- 分行号
-
+ 是否已解绑
+
-
+
- 集团商户信息
-
+ 上次绑定微信id
+
-
+
- 交易码
-
+ 创建者id
+
-
+
- 商户类型
-
+ 创建人
+
-
+
- 终端编号 1
-
+ 创建时间
+
+
+
+
+ 修改者id
+
+
+
+
+ 修改人
+
+
+
+
+ 修改时间
+
+
+
+
+
+
+
+
+
+ 文件ID
+
+
+
+
+ 文件名称
+
+
+
+
+ 文件大小
+
+
+
+
+ 文件类型
+
+
+
+
+ 文件拓展名
+
+
+
+
+ 文件位置
+
+
+
+
+ 文件上传时间
+
+
+
+
+ 文件备注
+
+
+
+
+ 创建者id
+
+
+
+
+ 创建人
+
+
+
+
+ 创建时间
+
+
+
+
+ 修改者id
+
+
+
+
+ 修改人
+
+
+
+
+ 修改时间
+
+
+
+
+ ID
+
+
+
+
+ 菜单与按钮关系表
+ 父类
+
+
+
+
+ 菜单ID
+
+
+
+
+ 按钮ID
+
+
+
+
+ 接口API地址信息表
+ 父类
+
+
+
+
+ 父ID
+
+
+
+
+ 路由菜单表
+
+
+
+
+ 上一级菜单(0表示上一级无菜单)
+
+
+
+
+ 接口api
+
+
+
+
+ 按钮跟权限关联表
+ 父类
+
+
+
+
+ 角色ID
+
+
+
+
+ 菜单ID
+
+
+
+
+ api ID
+
+
+
+
+ ID
+ 泛型主键Tkey
+
+
+
+
+ 用户信息表
+
+
+
+
+ uID
+ 泛型主键Tkey
+
+
+
+
+ Tibug 博文
+
+
+
+
+ 用户跟角色关联表
+ 父类
+
+
+
+
+ 用户ID
+
+
+
+
+ 角色ID
+
+
+
+
+ 通用分页信息类
+
+
+
+
+ 当前页标
+
+
+
+
+ 总页数
+
+
+
+
+ 数据总数
+
+
+
+
+ 每页大小
+
+
+
+
+ 返回数据
+
+
+
+
+ 所需分页参数
+ 作者:胡丁文
+ 时间:2020-4-3 20:31:26
+
+
+
+
+ 当前页
+
+
+
+
+ 每页大小
+
+
+
+
+ 排序字段(例如:id desc,time asc)
+
+
+
+
+ 查询条件( 例如:id = 1 and name = 小明)
+
+
+
+
+ 无权限
+
+
+
+
+ 找不到指定资源
+
+
+
+
+ 找不到指定资源
+
+
+
+
+ 表格数据,支持分页
+
+
+
+
+ 返回编码
+
+
+
+
+ 返回信息
+
+
+
+
+ 记录总数
+
+
+
+
+ 返回数据集
+
+
+
+
+ 广告类
+
+
+
+
+ 分类ID
+
+
+
+
+ 创建时间
+
+
+
+
+ 广告图片
+
+
+
+
+ 广告标题
+
+
+
+
+ 广告链接
+
+
+
+
+ 备注
+
+
+
+
+ 博客信息展示类
+
+
+
+
+
+
+
+
+ 创建人
+
+
+
+
+ 博客标题
+
+
+
+
+ 摘要
+
+
+
+
+
+ 上一篇
+
+
+
+
+ 上一篇id
+
+
+
+
+ 下一篇
+
+
+
+
+ 下一篇id
+
+
+
+ 类别
+
+
+
+
+ 内容
+
+
+
+
+
+ 访问量
+
+
+
+
+ 评论数量
+
+
+
+ 修改时间
+
+
+
+
+
+ 创建时间
+
+
+
+ 备注
+
+
+
+
+
+ 留言信息展示类
+
+
+
+ 留言表
+
+
+
+
+ 博客ID
+
+
+
+
+ 创建时间
+
+
+
+
+ 手机
+
+
+
+
+ qq
+
+
+
+
+ 留言内容
+
+
+
+
+ ip地址
+
+
+
+
+ 是否显示在前台,0否1是
+
+
+
+
+
+ 商户号
+
+
+
+
+ 柜台号
+
+
+
+
+ 分行号
+
+
+
+
+ 集团商户信息
+
+
+
+
+ 交易码
+
+
+
+
+ 商户类型
+
+
+
+
+ 终端编号 1
+
+
+
+
+ 终端编号 2
+
+
+
+
+ 订单号
+
+
+
+
+ 码信息(一维码、二维码)
+
+
+
+
+ 订单金额,单位:元
+
+
+
+
+ 商品名称
+
+
+
+
+ 备注 1
+
+
+
+
+ 备注 2
+
+
+
+
+ 分账信息一
+
+
+
+
+ 分账信息二
+
+
+
+
+ 子商户公众账号 ID
+
+
+
+
+ 返回信息位图
+
+
+
+
+ 实名支付
+
+
+
+
+ 商品详情
+
+
+
+
+ 订单优惠标记
+
+
+
+
+ 公钥
+
+
+
+
+ 请求地址
+
+
+
+
+ 是否删除空值
+
+
+
+
+ 退款参数
+
+
+
+
+ 订单ID
+
+
+
+
+ 商品名称
+
+
+
+
+ 支付金额(小数点最多两位)
+
+
+
+
+ 二维码/条码信息
+
+
+
+
+ 备注信息1
+
+
+
+
+ 备注信息2
+
+
+
+
+ 订单参数
+
+
+
+
+ 订单号
+
+
+
+
+ 退款金额
+
+
+
+
+ 退款流水号(可选)
+
+
+
+
+ 退款返回消息
+
+
+
+
+ 序列号
+
+
+
+
+ 商户号
+
+
+
+
+ 交易码
+
+
+
+
+ 返回码
+
+
+
+
+ 返回码说明
+
+
+
+
+ 语言
+
+
+
+
+ 订单信息
+
+
+
+
+ 订单信息
+
+
+
+
+ 订单号
+
+
+
+
+ 支付金额
+
+
+
+
+ 退款金额
+
+
+
+
+ 备注1
+
+
+
+
+ 备注2
+
+
+
+
+ 退款返回结果消息
+
+
+
+
+ 订单号
+
+
+
+
+ 支付金额
+
+
+
+
+ 退款金额
+
+
+
+
+ 序列号
+
+
+
+
+ 商户号
+
+
+
+
+ 交易码
+
+
+
+
+ 返回码
+
+
+
+
+ 返回码说明
+
+
+
+
+ 语言
+
+
+
+
+ 支付结果dto
+
+
+
+
+ 支付结果
+ Y:成功
+ N:失败
+ U:不确定
+ Q:待轮询
+
+
+
+
+ 订单ID
+
+
+
+
+ 支付金额
+
+
+
+
+ 二维码类型
+ 1:龙支付
+ 2:微信
+ 3:支付宝
+ 4:银联
+
+
+
+
+ 等待时间-轮询等待时间
+
+
+
+
+ 全局事件跟踪号-建行交易流水号
+
+
+
+
+ 错误码
+
+
+
+
+ 错误信息
+
+
+
+
+ 验证签名-防止伪造攻击
+
+
+
+
+ 返回支付结果
+
+
+
+
+ 发起的订单ID
+
+
+
+
+ 返回支付的金额
+
+
+
+
+ 返回支付的类型 1:龙支付 2:微信 3:支付宝 4:银联
+
+
+
+
+ 返回建行的流水号
+
+
+
+
+ 错误代码
+
+
+
+
+ 错误信息
+
+
+
+
+ 实现IJob的类
+
+
+
+
+ 命名空间
+
+
+
+
+ 类名
+
+
+
+
+ 备注
+
+
+
+
+ 服务器VM
+
+
+
+
+ 环境变量
+
+
+
+
+ 系统架构
+
+
+
+
+ ContentRootPath
+
+
+
+
+ WebRootPath
+
+
+
+
+ .NET Core版本
+
+
+
+
+ 内存占用
+
+
+
+
+ 启动时间
+
+
+
+
+ 菜单展示model
+
+
+
+
+ 调度任务触发器信息实体
+
+
+
+
+ 任务ID
+
+
+
+
+ 任务名称
+
+
+
+
+ 任务分组
+
+
+
+
+ 触发器ID
+
+
+
+
+ 触发器名称
+
+
+
+
+ 触发器分组
+
+
+
+
+ 触发器状态
+
+
+
+
+ 用来测试 RestSharp Get 请求
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 用来测试 RestSharp Post 请求
+
+
+
+
+ 留言排名展示类
+
+
+
+ 博客ID
+
+
+
+
+
+ 评论数量
+
+
+
+ 博客标题
+
+
+
+
+
+ 微信接口消息DTO
+ 作者:胡丁文
+ 时间:2020-03-25
+
+
+
+
+ 微信公众号ID(数据库查询)
+
+
+
+
+ 错误代码
+
+
+
+
+ 错误信息
+
+
+
+
+ token
+
+
+
+
+ 过期时间(秒)
+
+
+
+
+ 用户关注数
+
+
+
+
+ 获取用户数量
+
+
+
+
+ 获取用户OpenIDs
+
+
+
+
+ 下一个关注用户
+
+
+
+
+ 微信消息模板列表
+
+
+
+
+ 微信菜单
+
+
+
+
+ 二维码票据
+
+
+
+
+ 二维码过期时间
+
+
+
+
+ 二维码地址
+
+
+
+
+ 关注状态
+
+
+
+
+ 用户微信ID
+
+
+
+
+ 昵称
+
+
+
+
+ 性别
+
+
+
+
+ 语言
+
+
+
+
+ 城市
+
+
+
+
+ 省份
+
+
+
+
+ 城市
+
+
+
+
+ 头像地址
+
-
+
- 终端编号 2
-
+ 微信推送消息Dto
+ 作者:胡丁文
+ 时间:2020-4-8 09:16:16
+
-
+
- 订单号
-
+ 推送关键信息
+
-
+
- 码信息(一维码、二维码)
-
+ 推送卡片消息Dto
+
-
+
- 订单金额,单位:元
-
+ 微信推送消息Dto
+ 作者:胡丁文
+ 时间:2020-11-23 16:29:05
+
-
+
- 商品名称
-
+ 推送关键信息
+
-
+
- 备注 1
-
+ 推送卡片消息Dto
+
-
+
- 备注 2
-
+ 消息模板dto(如何填写数据,请参考微信模板即可)
+ 作者:胡丁文
+ 时间:2020-4-1 09:32:16
+
-
+
- 分账信息一
-
+ 消息模板
+
-
+
- 分账信息二
-
+ 标题
+
-
+
- 子商户公众账号 ID
-
+ 标题颜色(颜色代码都必须为#开头的16进制代码)
+
-
+
- 返回信息位图
-
+ 内容1
+
-
+
- 实名支付
-
+ 内容1颜色
+
-
+
- 商品详情
-
+ 内容2
+
-
+
- 订单优惠标记
-
+ 内容2颜色
+
-
+
- 公钥
+ 内容3
-
+
- 请求地址
+ 内容3颜色
-
+
- 是否删除空值
+ 内容4
-
+
- 退款参数
+ 内容4颜色
-
+
- 订单ID
+ 内容5
-
+
- 商品名称
+ 内容5颜色
-
+
- 支付金额(小数点最多两位)
+ 备注信息
-
+
- 二维码/条码信息
+ 备注信息颜色
-
+
- 备注信息1
+ 跳转连接
-
+
- 备注信息2
+ 获取微信菜单DTO,用于存放具体菜单内容
-
+
- 订单参数
+ 获取微信菜单DTO
-
+
- 订单号
+ 按钮列表(最多三个)
-
+
- 退款金额
+ 微信OpenID列表Dto
-
+
- 退款流水号(可选)
+ 推送详细数据
+ 作者:胡丁文
+ 时间:2020-4-8 09:16:16
-
+
- 退款返回消息
+ 推送给微信所需Dto
+ 作者:胡丁文
+ 时间:2020-4-8 09:16:16
-
+
- 序列号
+ 推送微信用户ID
-
+
- 商户号
+ 推送的模板ID
-
+
- 交易码
+ 推送URL地址
-
+
- 返回码
+ 推送的数据
-
+
- 返回码说明
+ 微信keyword所需Dto
+ 作者:胡丁文
+ 时间:2020-4-8 09:18:08
-
+
- 语言
+ 内容
-
+
- 订单信息
+ 文字颜色
-
+
- 订单信息
+ 图文链接标题
-
+
- 订单号
+ 图文描述
-
+
- 支付金额
+ 访问URL
-
+
- 退款金额
+ 图片URL
-
+
- 备注1
+ 图片mediaID
-
+
- 备注2
+ 推送模拟消息Dto
+ 作者:胡丁文
+ 时间:2020-4-24 14:52:44
-
+
- 退款返回结果消息
+ 当前选中的微信公众号
-
+
- 订单号
+ 当前选中的操作集合
-
+
- 支付金额
+ 当前选中的绑定还是订阅
-
+
- 退款金额
+ 当前选中的微信客户
-
+
- 序列号
+ 当前选中的消息类型
-
+
- 商户号
+ 当前选中要发送的用户
-
+
- 交易码
+ 文本消息
-
+
- 返回码
+ 图片消息
-
+
- 返回码说明
+ 语音消息
-
+
- 语言
+ 视频消息
-
+
- 支付结果dto
+ 链接消息
-
+
- 支付结果
- Y:成功
- N:失败
- U:不确定
- Q:待轮询
+ 文字消息
-
+
- 订单ID
+ 视频标题
-
+
- 支付金额
+ 视频封面mediaID
-
+
- 二维码类型
- 1:龙支付
- 2:微信
- 3:支付宝
- 4:银联
+ 视频mediaID
-
+
- 等待时间-轮询等待时间
+ 语音mediaID
-
+
- 全局事件跟踪号-建行交易流水号
+ 微信二维码预装发送信息dto
-
+
- 错误码
+ 微信二维码预装具体消息
-
+
- 错误信息
+ 微信二维码预装信息DTO
-
+
| | | |