♻️ feat(新增): 整合日志内容
This commit is contained in:
parent
a5953af186
commit
992b110d1a
|
@ -7,6 +7,7 @@
|
|||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="log4net" Version="2.0.17"/>
|
||||
<PackageReference Include="Microsoft.AspNetCore" Version="2.2.0"/>
|
||||
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="8.0.6"/>
|
||||
<PackageReference Include="Microsoft.AspNetCore.Mvc.Core" Version="2.2.5"/>
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
using Bunny.Common.Interceptor;
|
||||
using Bunny.Dao.Entity.Base;
|
||||
using Bunny.Dao.Entity.System;
|
||||
using log4net;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace Bunny.Common.Context.Database;
|
||||
|
@ -14,6 +15,8 @@ namespace Bunny.Common.Context.Database;
|
|||
/// </summary>
|
||||
public class EfCoreContext : DbContext
|
||||
{
|
||||
private static readonly ILog Log = LogManager.GetLogger(typeof(EfCoreContext));
|
||||
|
||||
public EfCoreContext()
|
||||
{
|
||||
var dataBaseConnection = AppSettings.GetAppConfig<string>("DataBase:DataBaseConnection");
|
||||
|
@ -34,8 +37,8 @@ public class EfCoreContext : DbContext
|
|||
/// </summary>
|
||||
protected override void OnConfiguring(DbContextOptionsBuilder options)
|
||||
{
|
||||
Log.Info("EfCoreContext 数据库连接...");
|
||||
options.UseSqlServer(DbPath).AddInterceptors(new TransactionInterceptor());
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
|
@ -1,10 +1,12 @@
|
|||
using Microsoft.AspNetCore.Builder;
|
||||
using log4net;
|
||||
using Microsoft.AspNetCore.Builder;
|
||||
using Minio;
|
||||
|
||||
namespace Bunny.Common.Context.Middleware;
|
||||
|
||||
public static class MinioContext
|
||||
{
|
||||
private static readonly ILog Log = LogManager.GetLogger(typeof(MinioContext));
|
||||
public static IMinioClient? MinioClient;
|
||||
public static readonly string BucketName = AppSettings.GetConfig("Minio:BucketName");
|
||||
|
||||
|
@ -17,7 +19,6 @@ public static class MinioContext
|
|||
MinioClient = new MinioClient().WithEndpoint(endpoint).WithCredentials(accessKey, secretKey)
|
||||
// .WithSSL() // 使用HTTPS
|
||||
.Build();
|
||||
|
||||
Console.WriteLine($"Minio 初始化...\n初始化桶:{BucketName}");
|
||||
Log.Info($"Minio 初始化...\n初始化桶:{BucketName}");
|
||||
}
|
||||
}
|
|
@ -1,10 +1,12 @@
|
|||
using Microsoft.AspNetCore.Builder;
|
||||
using log4net;
|
||||
using Microsoft.AspNetCore.Builder;
|
||||
using StackExchange.Redis;
|
||||
|
||||
namespace Bunny.Common.Context.Middleware;
|
||||
|
||||
public static class RedisContext
|
||||
{
|
||||
private static readonly ILog Log = LogManager.GetLogger(typeof(RedisContext));
|
||||
public static IDatabase? RedisDatabase;
|
||||
private static readonly EndPointCollection EndPointCollection = new();
|
||||
|
||||
|
@ -34,7 +36,7 @@ public static class RedisContext
|
|||
// 创建连接对象
|
||||
RedisDatabase = connect.GetDatabase();
|
||||
|
||||
Console.WriteLine("Redis 初始化...");
|
||||
Log.Info("Redis 初始化...");
|
||||
});
|
||||
}
|
||||
}
|
|
@ -18,16 +18,14 @@ public class GlobalExceptionFilter(ILogger<GlobalExceptionFilter> logger) : IExc
|
|||
// 错误的消息
|
||||
var message = context.Exception.Message;
|
||||
|
||||
|
||||
// 异常返回结果包装 也可以自定自定义返回类型
|
||||
var result = Result<string>.Error(ExceptionConstant.ServerError);
|
||||
|
||||
// 如果是自己自定义的异常
|
||||
if (context.Exception is BunnyException)
|
||||
if (context.Exception is BunnyException bunnyException)
|
||||
{
|
||||
var contextException = (BunnyException)context.Exception;
|
||||
message = contextException.Message;
|
||||
result = Result<string>.Error(contextException.Code, message);
|
||||
message = bunnyException.Message;
|
||||
result = Result<string>.Error(bunnyException.Code, message);
|
||||
}
|
||||
|
||||
// 日志记录
|
||||
|
|
|
@ -6,9 +6,13 @@ namespace Bunny.Common.Interceptor;
|
|||
|
||||
public class TransactionInterceptor : SaveChangesInterceptor
|
||||
{
|
||||
// 重写 SavingChanges 方法
|
||||
public override InterceptionResult<int> SavingChanges(DbContextEventData eventData, InterceptionResult<int> result)
|
||||
{
|
||||
// 如果当前上下文存在事务,则直接返回结果
|
||||
if (eventData.Context!.Database.CurrentTransaction != null) return result;
|
||||
|
||||
// 开始数据库事务
|
||||
using var transaction = eventData.Context.Database.BeginTransaction();
|
||||
try
|
||||
{
|
||||
|
@ -20,7 +24,7 @@ public class TransactionInterceptor : SaveChangesInterceptor
|
|||
}
|
||||
catch (System.Exception)
|
||||
{
|
||||
// 如果保存更改失败,则回滚事务
|
||||
// 如果保存更改失败,则回滚事务并抛出自定义异常
|
||||
transaction.Rollback();
|
||||
throw new BunnyException(ExceptionConstant.DataBaseError);
|
||||
}
|
||||
|
|
|
@ -1,9 +1,12 @@
|
|||
using Quartz;
|
||||
using log4net;
|
||||
using Quartz;
|
||||
|
||||
namespace Bunny.Service.Job;
|
||||
|
||||
public class CronJob : IJob
|
||||
{
|
||||
private static readonly ILog Log = LogManager.GetLogger(typeof(CronJob));
|
||||
|
||||
public Task Execute(IJobExecutionContext context)
|
||||
{
|
||||
// 工作Map集合
|
||||
|
@ -16,7 +19,7 @@ public class CronJob : IJob
|
|||
var count = dataMap.Get("count");
|
||||
var triggerCount = jobDataMap.Get("triggerCount");
|
||||
|
||||
Console.WriteLine($"CronJob:username:{username},password:{password},count:{count},triggerCount:{triggerCount}");
|
||||
Log.Info($"CronJob:username:{username},password:{password},count:{count},triggerCount:{triggerCount}");
|
||||
|
||||
// 设置 count 值
|
||||
dataMap.Put("count", Convert.ToInt32(count) + 1);
|
||||
|
|
|
@ -1,12 +1,15 @@
|
|||
using Quartz;
|
||||
using log4net;
|
||||
using Quartz;
|
||||
|
||||
namespace Bunny.Service.Job;
|
||||
|
||||
public class HelloJob : IJob
|
||||
{
|
||||
private static readonly ILog Log = LogManager.GetLogger(typeof(HelloJob));
|
||||
|
||||
public Task Execute(IJobExecutionContext context)
|
||||
{
|
||||
Console.WriteLine("Hello World 的自动执行");
|
||||
Log.Debug("Hello World 的自动执行");
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
}
|
|
@ -1,15 +1,18 @@
|
|||
using Quartz;
|
||||
using log4net;
|
||||
using Quartz;
|
||||
|
||||
namespace Bunny.Service.Job;
|
||||
|
||||
public class SimpleJob : IJob
|
||||
{
|
||||
private static readonly ILog Log = LogManager.GetLogger(typeof(SimpleJob));
|
||||
|
||||
public Task Execute(IJobExecutionContext context)
|
||||
{
|
||||
var dataMap = context.JobDetail.JobDataMap;
|
||||
var username = dataMap.GetString("username");
|
||||
var password = dataMap.GetString("password");
|
||||
Console.WriteLine($"SimpleJob:用户名:{username},密码: {password}");
|
||||
Log.Info($"SimpleJob:用户名:{username},密码: {password}");
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
}
|
|
@ -1,9 +1,12 @@
|
|||
using Fleck;
|
||||
using log4net;
|
||||
|
||||
namespace Bunny.Service.WebSocket;
|
||||
|
||||
public static class WebSocketTest
|
||||
{
|
||||
private static readonly ILog Log = LogManager.GetLogger(typeof(WebSocketTest));
|
||||
|
||||
public static void Start()
|
||||
{
|
||||
var webSocketServer = new WebSocketServer("ws://0.0.0.0:8800");
|
||||
|
@ -11,11 +14,11 @@ public static class WebSocketTest
|
|||
webSocketServer.RestartAfterListenError = true;
|
||||
webSocketServer.Start(socket =>
|
||||
{
|
||||
socket.OnOpen = () => Console.WriteLine("Open!");
|
||||
socket.OnClose = () => Console.WriteLine("Close!");
|
||||
socket.OnOpen = () => Log.Debug("Open!");
|
||||
socket.OnClose = () => Log.Debug("Close!");
|
||||
socket.OnMessage = message =>
|
||||
{
|
||||
Console.WriteLine(message);
|
||||
Log.Debug(message);
|
||||
socket.Send(message);
|
||||
};
|
||||
});
|
||||
|
|
|
@ -19,30 +19,29 @@
|
|||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<_WebToolingArtifacts Remove="Properties\launchSettings.json" />
|
||||
<_WebToolingArtifacts Remove="Properties\launchSettings.json"/>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Content Include="Properties\launchSettings.json" />
|
||||
<Content Include="Properties\launchSettings.json"/>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Autofac" Version="8.1.0" />
|
||||
<PackageReference Include="Autofac.Extensions.DependencyInjection" Version="10.0.0" />
|
||||
<PackageReference Include="IGeekFan.AspNetCore.Knife4jUI" Version="0.0.16" />
|
||||
<PackageReference Include="log4net" Version="2.0.17" />
|
||||
<PackageReference Include="Microsoft.Extensions.Logging.Log4Net.AspNetCore" Version="8.0.0" />
|
||||
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.7.3" />
|
||||
<PackageReference Include="System.Data.SqlClient" Version="4.8.6" />
|
||||
<PackageReference Include="Autofac" Version="8.1.0"/>
|
||||
<PackageReference Include="Autofac.Extensions.DependencyInjection" Version="10.0.0"/>
|
||||
<PackageReference Include="IGeekFan.AspNetCore.Knife4jUI" Version="0.0.16"/>
|
||||
<PackageReference Include="Microsoft.Extensions.Logging.Log4Net.AspNetCore" Version="8.0.0"/>
|
||||
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.7.3"/>
|
||||
<PackageReference Include="System.Data.SqlClient" Version="4.8.6"/>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Bunny.Service\Bunny.Service.csproj" />
|
||||
<ProjectReference Include="..\Bunny.Service\Bunny.Service.csproj"/>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<_ContentIncludedByDefault Remove="Config\log4net.config" />
|
||||
<_ContentIncludedByDefault Remove="Config\NLog.config" />
|
||||
<_ContentIncludedByDefault Remove="Config\log4net.config"/>
|
||||
<_ContentIncludedByDefault Remove="Config\NLog.config"/>
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
using Autofac;
|
||||
using Autofac.Extensions.DependencyInjection;
|
||||
using Bunny.Common;
|
||||
using Bunny.Common.Configuration;
|
||||
using Bunny.Common.Context.Middleware;
|
||||
using Bunny.Service.WebSocket;
|
||||
using Microsoft.AspNetCore.Mvc.Controllers;
|
||||
|
@ -20,6 +19,7 @@ public class BaseConfig(WebApplicationBuilder builder)
|
|||
UseCors();
|
||||
// 配置日志相关
|
||||
// builder.Logging.AddLog4Net("Configuration/log4net.config");
|
||||
Log4NetConfiguration.ConfigureLog4Net("Configuration/log4net.config");
|
||||
// 自定义时间格式
|
||||
builder.Services.AddControllers().AddJsonOptions(options =>
|
||||
options.JsonSerializerOptions.Converters.Add(new JsonDateTimeConverter()));
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
using System.Text.Json.Serialization;
|
||||
using Bunny.Dao.Common.Constant;
|
||||
|
||||
namespace Bunny.Common.Configuration;
|
||||
namespace Bunny.WebApi.Configuration;
|
||||
|
||||
/// <summary>
|
||||
/// 自定义Json转换器,用于将DateTime类型转换为JSON格式
|
|
@ -0,0 +1,14 @@
|
|||
using log4net;
|
||||
using log4net.Config;
|
||||
|
||||
namespace Bunny.WebApi.Configuration;
|
||||
|
||||
public class Log4NetConfiguration
|
||||
{
|
||||
private static readonly ILog Log = LogManager.GetLogger(typeof(Log4NetConfiguration));
|
||||
|
||||
public static void ConfigureLog4Net(string configFilePath)
|
||||
{
|
||||
XmlConfigurator.Configure(new FileInfo(configFilePath));
|
||||
}
|
||||
}
|
|
@ -1,8 +1,8 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<log4net>
|
||||
<!-- Define some output appenders -->
|
||||
<appender name="rollingAppender" type="log4net.Appender.RollingFileAppender">
|
||||
<file value="log4\log.txt"/>
|
||||
<appender name="RollingAppender" type="log4net.Appender.RollingFileAppender">
|
||||
<file value="log4net\log4net.log"/>
|
||||
<!--追加日志内容-->
|
||||
<appendToFile value="true"/>
|
||||
|
||||
|
@ -39,7 +39,7 @@
|
|||
|
||||
<!--SqlServer形式-->
|
||||
<!--log4net日志配置:http://logging.apache.org/log4net/release/config-examples.html -->
|
||||
<appender name="AdoNetAppender_SqlServer" type="log4net.Appender.AdoNetAppender">
|
||||
<appender name="AdoNetAppenderSqlServer" type="log4net.Appender.AdoNetAppender">
|
||||
<!--日志缓存写入条数 设置为0时只要有一条就立刻写到数据库-->
|
||||
<bufferSize value="0"/>
|
||||
<!--日志数据库连接串-->
|
||||
|
@ -94,6 +94,13 @@
|
|||
</parameter>
|
||||
</appender>
|
||||
|
||||
<appender name="ConsoleAppender" type="log4net.Appender.ConsoleAppender">
|
||||
<layout type="log4net.Layout.PatternLayout">
|
||||
<!-- 自定义日志格式 -->
|
||||
<conversionPattern value="%date [%thread] %-5level %logger - %message%newline"/>
|
||||
</layout>
|
||||
</appender>
|
||||
|
||||
<root>
|
||||
|
||||
<!--控制级别,由低到高: ALL|DEBUG|INFO|WARN|ERROR|FATAL|OFF-->
|
||||
|
@ -106,8 +113,13 @@
|
|||
<!--ALL: DEBUG,INFO,WARN,ERROR,FATAL-->
|
||||
<priority value="ALL"/>
|
||||
<!-- TODO 修改成你自己的类型 -->
|
||||
<level value="WARN"/>
|
||||
<appender-ref ref="rollingAppender"/>
|
||||
<appender-ref ref="AdoNetAppender_SqlServer"/>
|
||||
<level value="INFO"/>
|
||||
|
||||
<!-- 写入文本文件 -->
|
||||
<appender-ref ref="RollingAppender"/>
|
||||
<!-- TODO 如果需要写入数据库放开这个注释 -->
|
||||
<!-- <appender-ref ref="AdoNetAppenderSqlServer"/> -->
|
||||
<!-- 控制台输出 -->
|
||||
<appender-ref ref="ConsoleAppender"/>
|
||||
</root>
|
||||
</log4net>
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
using Bunny.Dao.Common.Constant.Result;
|
||||
using Bunny.Dao.Common.Result;
|
||||
using Lazy.Captcha.Core;
|
||||
using log4net;
|
||||
using Microsoft.AspNetCore.Components;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
|
||||
|
@ -12,6 +13,7 @@ namespace Bunny.WebApi.Controllers;
|
|||
[Microsoft.AspNetCore.Mvc.Route("/api/[controller]/[action]")]
|
||||
public class CaptchaTestController : ControllerBase
|
||||
{
|
||||
private static readonly ILog Log = LogManager.GetLogger(typeof(CaptchaTestController));
|
||||
[Inject] public required ICaptcha Captcha { get; set; }
|
||||
|
||||
/// <summary>
|
||||
|
@ -27,7 +29,7 @@ public class CaptchaTestController : ControllerBase
|
|||
// 验证码的代码
|
||||
var captchaDataCode = captchaData.Code;
|
||||
|
||||
Console.WriteLine($"验证码的ID:{captchaDataId};验证码的代码:{captchaDataCode}");
|
||||
Log.Debug($"验证码的ID:{captchaDataId};验证码的代码:{captchaDataCode}");
|
||||
|
||||
// 返回验证码图片内容
|
||||
var stream = new MemoryStream(captchaData.Bytes);
|
||||
|
|
|
@ -1,138 +0,0 @@
|
|||
## 后台服务设置
|
||||
|
||||
### Quartz写法
|
||||
|
||||
- 持久化存储生成数据SQL语句参考
|
||||
- https://github.com/quartznet/quartznet/tree/main/database/tables
|
||||
|
||||
### 原生写法
|
||||
|
||||
- 设置每秒执行多少,设置后台服务,原生写法
|
||||
|
||||
```csharp
|
||||
using Microsoft.Extensions.Hosting;
|
||||
|
||||
namespace Bunny.Service.BackgroundModule;
|
||||
|
||||
/// <summary>
|
||||
/// 定时任务
|
||||
/// </summary>
|
||||
public class TemplateBackgroundModule : BackgroundService
|
||||
{
|
||||
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
|
||||
{
|
||||
while (!stoppingToken.IsCancellationRequested)
|
||||
{
|
||||
Console.WriteLine("TemplateService started");
|
||||
await Task.Delay(1000, stoppingToken);
|
||||
await Task.Run(() => { Console.WriteLine("执行了。。。"); }, stoppingToken);
|
||||
await Task.Delay(1000, stoppingToken);
|
||||
Console.WriteLine("--------------------------------");
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 验证码生成
|
||||
|
||||
- 验证码生成相关配置
|
||||
|
||||
```csharp
|
||||
var service = builder.Services;
|
||||
// 使用图形验证码
|
||||
service.AddDistributedMemoryCache();
|
||||
// 验证码相关配置内容
|
||||
service.AddCaptcha(options =>
|
||||
{
|
||||
options.CaptchaType = CaptchaType.DEFAULT; // 验证码类型
|
||||
options.CodeLength = 4; // 验证码长度
|
||||
options.ExpirySeconds = 60; // 过期时间(单位/秒)
|
||||
options.IgnoreCase = true; // 比较忽略大小写
|
||||
options.ImageOption.Animation = true; // 是否启用动画
|
||||
options.ImageOption.Width = 130; // 验证码宽度
|
||||
options.ImageOption.Height = 48; // 验证码高度
|
||||
options.ImageOption.BackgroundColor = SKColors.White;
|
||||
options.ImageOption.BubbleCount = 6; // 气泡数量
|
||||
options.ImageOption.BubbleMinRadius = 2; // 气泡最小半径
|
||||
options.ImageOption.BubbleMaxRadius = 6; // 气泡最大半径
|
||||
options.ImageOption.BubbleThickness = 2; // 气泡边沿厚度
|
||||
options.ImageOption.InterferenceLineCount = 2; // 干扰线数量
|
||||
options.ImageOption.FontSize = 36; // 字体大小
|
||||
options.ImageOption.FontFamily = DefaultFontFamilys.Instance.Kaiti; // 字体,中文使用kaiti,其他字符可根据喜好设置
|
||||
});
|
||||
}
|
||||
```
|
||||
|
||||
## AutoFac配置
|
||||
|
||||
### 自动注入按照名称注入
|
||||
|
||||
**AutoFac配置详情**
|
||||
|
||||
```csharp
|
||||
using Autofac;
|
||||
using Bunny.Common.Attribute;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
|
||||
namespace Bunny.WebApi.Config;
|
||||
|
||||
public static class AddAutofacConfig
|
||||
{
|
||||
/// <summary>
|
||||
/// AutoFac自动注入约定名称
|
||||
/// 接口以Service结尾注入到IOC中
|
||||
/// </summary>
|
||||
/// <param name="builder"></param>
|
||||
public static void BuildContainer(ContainerBuilder builder)
|
||||
{
|
||||
// 扫描所以前缀Bunny的命名空间
|
||||
var assemblies = AppDomain.CurrentDomain.GetAssemblies().Where(t => t.FullName!.StartsWith("Bunny"));
|
||||
|
||||
// 遍历注入服务
|
||||
foreach (var assembly in assemblies)
|
||||
{
|
||||
var types = assembly.GetTypes();
|
||||
|
||||
// 注入Service
|
||||
var serviceTypes = types.Where(t => t.GetCustomAttributes(typeof(ServiceAttribute), false).Length != 0);
|
||||
foreach (var serviceType in serviceTypes)
|
||||
{
|
||||
var interfaces = serviceType.GetInterfaces();
|
||||
builder.RegisterType(serviceType).As(interfaces).InstancePerDependency();
|
||||
}
|
||||
|
||||
// 注入数据库相关
|
||||
var mapperTypes = types.Where(t => t.GetCustomAttributes(typeof(MapperAttribute), false).Length != 0);
|
||||
foreach (var mapperType in mapperTypes)
|
||||
{
|
||||
var interfaces = mapperType.GetInterfaces();
|
||||
builder.RegisterType(mapperType).As(interfaces).InstancePerDependency();
|
||||
}
|
||||
|
||||
// 注入后台服务
|
||||
var componentTypes =
|
||||
types.Where(t => t.GetCustomAttributes(typeof(ComponentAttribute), false).Length != 0);
|
||||
foreach (var componentType in componentTypes)
|
||||
builder.RegisterType(componentType).AsSelf().As<IHostedService>().SingleInstance();
|
||||
}
|
||||
|
||||
// 如果不在在 Controller 层写构造函数可以打开这个,自动完成注入
|
||||
var controllerBaseType = typeof(ControllerBase);
|
||||
builder.RegisterAssemblyTypes(typeof(Program).Assembly)
|
||||
.Where(t => controllerBaseType.IsAssignableFrom(t) && t != controllerBaseType)
|
||||
.PropertiesAutowired(); //支持属性注入
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**主程序入口配置**
|
||||
|
||||
```csharp
|
||||
// 让控制器实例由容器创建
|
||||
builder.Services.Replace(ServiceDescriptor.Transient<IControllerActivator, ServiceBasedControllerActivator>());
|
||||
|
||||
// 如果将Service放在 WebApi同级目录下,可以完成Controller自动注入,不需要写构造函数
|
||||
builder.Services.Replace(ServiceDescriptor.Transient<IControllerActivator, ServiceBasedControllerActivator>());
|
||||
builder.Services.AddControllers().AddJsonOptions(options =>
|
||||
options.JsonSerializerOptions.Converters.Add(new JsonDateTimeConverter()));
|
||||
```
|
|
@ -0,0 +1,331 @@
|
|||
## 基础配置
|
||||
|
||||
基础配置可以看下这个,里面整合几乎这个模板所有的配置。
|
||||
|
||||
![image-20240902231627836](./images/image-20240902231627836.png)
|
||||
|
||||
### 数据库配置
|
||||
|
||||
![image-20240902231720819](./images/image-20240902231720819.png)
|
||||
|
||||
### 中间件配置
|
||||
|
||||
![image-20240902231705133](./images/image-20240902231705133.png)
|
||||
|
||||
## 后台服务设置
|
||||
|
||||
### Quartz写法
|
||||
|
||||
- 持久化存储生成数据SQL语句参考
|
||||
- https://github.com/quartznet/quartznet/tree/main/database/tables
|
||||
|
||||
### 原生写法
|
||||
|
||||
- 设置每秒执行多少,设置后台服务,原生写法
|
||||
|
||||
```csharp
|
||||
using Microsoft.Extensions.Hosting;
|
||||
|
||||
namespace Bunny.Service.BackgroundModule;
|
||||
|
||||
/// <summary>
|
||||
/// 定时任务
|
||||
/// </summary>
|
||||
public class TemplateBackgroundModule : BackgroundService
|
||||
{
|
||||
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
|
||||
{
|
||||
while (!stoppingToken.IsCancellationRequested)
|
||||
{
|
||||
Console.WriteLine("TemplateService started");
|
||||
await Task.Delay(1000, stoppingToken);
|
||||
await Task.Run(() => { Console.WriteLine("执行了。。。"); }, stoppingToken);
|
||||
await Task.Delay(1000, stoppingToken);
|
||||
Console.WriteLine("--------------------------------");
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 验证码生成
|
||||
|
||||
- 验证码生成相关配置
|
||||
|
||||
```csharp
|
||||
var service = builder.Services;
|
||||
// 使用图形验证码
|
||||
service.AddDistributedMemoryCache();
|
||||
// 验证码相关配置内容
|
||||
service.AddCaptcha(options =>
|
||||
{
|
||||
options.CaptchaType = CaptchaType.DEFAULT; // 验证码类型
|
||||
options.CodeLength = 4; // 验证码长度
|
||||
options.ExpirySeconds = 60; // 过期时间(单位/秒)
|
||||
options.IgnoreCase = true; // 比较忽略大小写
|
||||
options.ImageOption.Animation = true; // 是否启用动画
|
||||
options.ImageOption.Width = 130; // 验证码宽度
|
||||
options.ImageOption.Height = 48; // 验证码高度
|
||||
options.ImageOption.BackgroundColor = SKColors.White;
|
||||
options.ImageOption.BubbleCount = 6; // 气泡数量
|
||||
options.ImageOption.BubbleMinRadius = 2; // 气泡最小半径
|
||||
options.ImageOption.BubbleMaxRadius = 6; // 气泡最大半径
|
||||
options.ImageOption.BubbleThickness = 2; // 气泡边沿厚度
|
||||
options.ImageOption.InterferenceLineCount = 2; // 干扰线数量
|
||||
options.ImageOption.FontSize = 36; // 字体大小
|
||||
options.ImageOption.FontFamily = DefaultFontFamilys.Instance.Kaiti; // 字体,中文使用kaiti,其他字符可根据喜好设置
|
||||
});
|
||||
}
|
||||
```
|
||||
|
||||
## AutoFac配置
|
||||
|
||||
### 自动注入按照名称注入
|
||||
|
||||
**AutoFac配置详情**
|
||||
|
||||
```csharp
|
||||
using Autofac;
|
||||
using Bunny.Common.Attribute;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
|
||||
namespace Bunny.WebApi.Config;
|
||||
|
||||
public static class AddAutofacConfig
|
||||
{
|
||||
/// <summary>
|
||||
/// AutoFac自动注入约定名称
|
||||
/// 接口以Service结尾注入到IOC中
|
||||
/// </summary>
|
||||
/// <param name="builder"></param>
|
||||
public static void BuildContainer(ContainerBuilder builder)
|
||||
{
|
||||
// 扫描所以前缀Bunny的命名空间
|
||||
var assemblies = AppDomain.CurrentDomain.GetAssemblies().Where(t => t.FullName!.StartsWith("Bunny"));
|
||||
|
||||
// 遍历注入服务
|
||||
foreach (var assembly in assemblies)
|
||||
{
|
||||
var types = assembly.GetTypes();
|
||||
|
||||
// 注入Service
|
||||
var serviceTypes = types.Where(t => t.GetCustomAttributes(typeof(ServiceAttribute), false).Length != 0);
|
||||
foreach (var serviceType in serviceTypes)
|
||||
{
|
||||
var interfaces = serviceType.GetInterfaces();
|
||||
builder.RegisterType(serviceType).As(interfaces).InstancePerDependency();
|
||||
}
|
||||
|
||||
// 注入数据库相关
|
||||
var mapperTypes = types.Where(t => t.GetCustomAttributes(typeof(MapperAttribute), false).Length != 0);
|
||||
foreach (var mapperType in mapperTypes)
|
||||
{
|
||||
var interfaces = mapperType.GetInterfaces();
|
||||
builder.RegisterType(mapperType).As(interfaces).InstancePerDependency();
|
||||
}
|
||||
|
||||
// 注入后台服务
|
||||
var componentTypes =
|
||||
types.Where(t => t.GetCustomAttributes(typeof(ComponentAttribute), false).Length != 0);
|
||||
foreach (var componentType in componentTypes)
|
||||
builder.RegisterType(componentType).AsSelf().As<IHostedService>().SingleInstance();
|
||||
}
|
||||
|
||||
// 如果不在在 Controller 层写构造函数可以打开这个,自动完成注入
|
||||
var controllerBaseType = typeof(ControllerBase);
|
||||
builder.RegisterAssemblyTypes(typeof(Program).Assembly)
|
||||
.Where(t => controllerBaseType.IsAssignableFrom(t) && t != controllerBaseType)
|
||||
.PropertiesAutowired(); //支持属性注入
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**主程序入口配置**
|
||||
|
||||
```csharp
|
||||
// 让控制器实例由容器创建
|
||||
builder.Services.Replace(ServiceDescriptor.Transient<IControllerActivator, ServiceBasedControllerActivator>());
|
||||
|
||||
// 如果将Service放在 WebApi同级目录下,可以完成Controller自动注入,不需要写构造函数
|
||||
builder.Services.Replace(ServiceDescriptor.Transient<IControllerActivator, ServiceBasedControllerActivator>());
|
||||
builder.Services.AddControllers().AddJsonOptions(options =>
|
||||
options.JsonSerializerOptions.Converters.Add(new JsonDateTimeConverter()));
|
||||
```
|
||||
|
||||
## 日志配置
|
||||
|
||||
### 数据库生成
|
||||
|
||||
在这里面有数据库生成内容
|
||||
|
||||
![image-20240902230702816](./images/image-20240902230702816.png)
|
||||
|
||||
如果需要写入数据库放开这个注释
|
||||
|
||||
![image-20240902230759404](./images/image-20240902230759404.png)
|
||||
|
||||
> **配置参考**
|
||||
>
|
||||
> ```xml
|
||||
> <?xml version="1.0" encoding="utf-8"?>
|
||||
> <log4net>
|
||||
> <!-- Define some output appenders -->
|
||||
> <appender name="RollingAppender" type="log4net.Appender.RollingFileAppender">
|
||||
> <file value="log4net\log4net.log"/>
|
||||
> <!--追加日志内容-->
|
||||
> <appendToFile value="true"/>
|
||||
>
|
||||
> <!--防止多线程时不能写Log,官方说线程非安全-->
|
||||
> <lockingModel type="log4net.Appender.FileAppender+MinimalLock"/>
|
||||
>
|
||||
> <!--可以为:Once|Size|Date|Composite-->
|
||||
> <!--Composite为Size和Date的组合-->
|
||||
> <rollingStyle value="Composite"/>
|
||||
>
|
||||
> <!--当备份文件时,为文件名加的后缀-->
|
||||
> <datePattern value="yyyyMMdd.TXT"/>
|
||||
>
|
||||
> <!--日志最大个数,都是最新的-->
|
||||
> <!--rollingStyle节点为Size时,只能有value个日志-->
|
||||
> <!--rollingStyle节点为Composite时,每天有value个日志-->
|
||||
> <maxSizeRollBackups value="20"/>
|
||||
>
|
||||
> <!--可用的单位:KB|MB|GB-->
|
||||
> <maximumFileSize value="3MB"/>
|
||||
>
|
||||
> <!--置为true,当前最新日志文件名永远为file节中的名字-->
|
||||
> <staticLogFileName value="true"/>
|
||||
>
|
||||
> <!--输出级别在INFO和ERROR之间的日志-->
|
||||
> <filter type="log4net.Filter.LevelRangeFilter">
|
||||
> <param name="LevelMin" value="ALL"/>
|
||||
> <param name="LevelMax" value="FATAL"/>
|
||||
> </filter>
|
||||
> <layout type="log4net.Layout.PatternLayout">
|
||||
> <conversionPattern value="%date [%thread] %-5level %logger - %Message%newline"/>
|
||||
> </layout>
|
||||
> </appender>
|
||||
>
|
||||
> <!--SqlServer形式-->
|
||||
> <!--log4net日志配置:http://logging.apache.org/log4net/release/config-examples.html -->
|
||||
> <appender name="AdoNetAppenderSqlServer" type="log4net.Appender.AdoNetAppender">
|
||||
> <!--日志缓存写入条数 设置为0时只要有一条就立刻写到数据库-->
|
||||
> <bufferSize value="0"/>
|
||||
> <!--日志数据库连接串-->
|
||||
> <connectionType
|
||||
> value="System.Data.SqlClient.SqlConnection,System.Data.SqlClient, Version=4.6.1.3, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"/>
|
||||
> <connectionString
|
||||
> value="Data Source=192.168.3.98;Initial Catalog=LogManager;Persist Security Info=True;User ID=sa;Password=abc1234."/>
|
||||
> <commandText
|
||||
> value="INSERT INTO Log4Net ([Date],[Thread],[Level],[Logger],[Message],[Exception]) VALUES (@log_date, @thread, @log_level, @logger, @Message, @exception)"/>
|
||||
> <parameter>
|
||||
> <parameterName value="@log_date"/>
|
||||
> <dbType value="DateTime"/>
|
||||
> <layout type="log4net.Layout.RawTimeStampLayout"/>
|
||||
> </parameter>
|
||||
> <parameter>
|
||||
> <parameterName value="@thread"/>
|
||||
> <dbType value="String"/>
|
||||
> <size value="255"/>
|
||||
> <layout type="log4net.Layout.PatternLayout">
|
||||
> <conversionPattern value="%thread"/>
|
||||
> </layout>
|
||||
> </parameter>
|
||||
> <parameter>
|
||||
> <parameterName value="@log_level"/>
|
||||
> <dbType value="String"/>
|
||||
> <size value="50"/>
|
||||
> <layout type="log4net.Layout.PatternLayout">
|
||||
> <conversionPattern value="%level"/>
|
||||
> </layout>
|
||||
> </parameter>
|
||||
> <parameter>
|
||||
> <parameterName value="@logger"/>
|
||||
> <dbType value="String"/>
|
||||
> <size value="255"/>
|
||||
> <layout type="log4net.Layout.PatternLayout">
|
||||
> <conversionPattern value="%logger"/>
|
||||
> </layout>
|
||||
> </parameter>
|
||||
> <parameter>
|
||||
> <parameterName value="@Message"/>
|
||||
> <dbType value="String"/>
|
||||
> <size value="4000"/>
|
||||
> <layout type="log4net.Layout.PatternLayout">
|
||||
> <conversionPattern value="%Message"/>
|
||||
> </layout>
|
||||
> </parameter>
|
||||
> <parameter>
|
||||
> <parameterName value="@exception"/>
|
||||
> <dbType value="String"/>
|
||||
> <size value="2000"/>
|
||||
> <layout type="log4net.Layout.ExceptionLayout"/>
|
||||
> </parameter>
|
||||
> </appender>
|
||||
>
|
||||
> <appender name="ConsoleAppender" type="log4net.Appender.ConsoleAppender">
|
||||
> <layout type="log4net.Layout.PatternLayout">
|
||||
> <!-- 自定义日志格式 -->
|
||||
> <conversionPattern value="%date [%thread] %-5level %logger - %message%newline"/>
|
||||
> </layout>
|
||||
> </appender>
|
||||
>
|
||||
> <root>
|
||||
>
|
||||
> <!--控制级别,由低到高: ALL|DEBUG|INFO|WARN|ERROR|FATAL|OFF-->
|
||||
> <!--OFF:0-->
|
||||
> <!--FATAL:FATAL-->
|
||||
> <!--ERROR: ERROR,FATAL-->
|
||||
> <!--WARN: WARN,ERROR,FATAL-->
|
||||
> <!--INFO: INFO,WARN,ERROR,FATAL-->
|
||||
> <!--DEBUG: INFO,WARN,ERROR,FATAL-->
|
||||
> <!--ALL: DEBUG,INFO,WARN,ERROR,FATAL-->
|
||||
> <priority value="ALL"/>
|
||||
> <!-- TODO 修改成你自己的类型 -->
|
||||
> <level value="INFO"/>
|
||||
>
|
||||
> <!-- 写入文本文件 -->
|
||||
> <appender-ref ref="RollingAppender"/>
|
||||
> <!-- 写入数据库 -->
|
||||
> <appender-ref ref="AdoNetAppenderSqlServer"/>
|
||||
> <!-- 控制台输出 -->
|
||||
> <appender-ref ref="ConsoleAppender"/>
|
||||
> </root>
|
||||
> </log4net>
|
||||
> ```
|
||||
|
||||
## 统一日期返回格式
|
||||
|
||||
对于控制器来说,需要指定返回日期格式可以看下这个,
|
||||
|
||||
```csharp
|
||||
/// <summary>
|
||||
/// 自定义Json转换器,用于将DateTime类型转换为JSON格式
|
||||
/// </summary>
|
||||
public class JsonDateTimeConverter : JsonConverter<DateTime>
|
||||
{
|
||||
/// <summary>
|
||||
/// 重写读取方法,将JSON数据转换为DateTime类型
|
||||
/// </summary>
|
||||
/// <param name="reader">JSON读取器</param>
|
||||
/// <param name="typeToConvert">要转换的目标类型</param>
|
||||
/// <param name="options">JSON序列化选项</param>
|
||||
/// <returns>转换后的DateTime对象</returns>
|
||||
public override DateTime Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
|
||||
{
|
||||
return DateTime.TryParse(reader.GetString(), out var date) ? date : default;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 重写写入方法,将DateTime对象转换为JSON格式并写入JSON写入器
|
||||
/// </summary>
|
||||
/// <param name="writer">JSON写入器</param>
|
||||
/// <param name="value">要写入的DateTime对象</param>
|
||||
/// <param name="options">JSON序列化选项</param>
|
||||
public override void Write(Utf8JsonWriter writer, DateTime value, JsonSerializerOptions options)
|
||||
{
|
||||
// 将DateTime对象转换为特定格式的字符串并写入JSON写入器
|
||||
writer.WriteStringValue(value.ToString(LocalDateTimeConstant.DefaultDateTimeSecondFormat));
|
||||
}
|
||||
}
|
||||
```
|
||||
|
Binary file not shown.
After Width: | Height: | Size: 15 KiB |
Binary file not shown.
After Width: | Height: | Size: 114 KiB |
Binary file not shown.
After Width: | Height: | Size: 30 KiB |
Binary file not shown.
After Width: | Height: | Size: 17 KiB |
Binary file not shown.
After Width: | Height: | Size: 11 KiB |
Loading…
Reference in New Issue