CSharp-Single-EFCore/Bunny.WebApi/ReadMe/ReadMe.md

332 lines
12 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

## 基础配置
基础配置可以看下这个,里面整合几乎这个模板所有的配置。
![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));
}
}
```