You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

189 lines
6.9 KiB
C#

// ============================================================================
// 【文件说明】HwPortalSearchOptions.cs - 搜索子系统配置选项
// ============================================================================
// 这个类定义了搜索子系统的所有配置项,对应配置文件中的 HwPortalSearch 节点。
//
// 【配置绑定机制】
// 在 Startup.cs 中通过 services.AddConfigurableOptions<HwPortalSearchOptions>() 注册。
// 框架会自动从配置文件(如 Search.json读取配置并绑定到这个类。
//
// 【与 Java Spring Boot 的对比】
// Java Spring Boot:
// @ConfigurationProperties(prefix = "hwportal.search")
// @Configuration
// public class HwPortalSearchProperties {
// private String engine = "es";
// private Boolean enableLegacyFallback = true;
// // ... getter/setter
// }
//
// ASP.NET Core + Furion:
// public sealed class HwPortalSearchOptions : IConfigurableOptions<HwPortalSearchOptions>
//
// 两者概念相同:都是把配置文件的值映射到类的属性。
// ============================================================================
using Microsoft.Extensions.Configuration;
namespace Admin.NET.Plugin.HwPortal;
/// <summary>
/// hw-portal 搜索子系统配置。
/// <para>
/// 【C# 语法知识点 - sealed 密封类】
/// sealed 表示"密封类",不能被继承。
/// 配置类通常不需要继承,密封可以防止意外扩展。
///
/// 对比 Java
/// Java 通常用 final 关键字public final class HwPortalSearchOptions { ... }
/// </para>
/// <para>
/// 【C# 语法知识点 - IConfigurableOptions&lt;T&gt; 接口】
/// IConfigurableOptions&lt;T&gt; 是 Furion 框架的配置接口。
/// 实现这个接口后,框架会:
/// 1. 自动从配置文件读取配置
/// 2. 绑定到类的属性
/// 3. 调用 PostConfigure 方法进行后处理
///
/// 对比 Java Spring Boot
/// Java 用 @ConfigurationProperties 注解实现类似功能。
/// </para>
/// </summary>
public sealed class HwPortalSearchOptions : IConfigurableOptions<HwPortalSearchOptions>
{
/// <summary>
/// 搜索引擎标识。
/// <para>
/// 【业务说明】
/// 支持多种搜索引擎:
/// - "es"Elasticsearch推荐性能最好
/// - "indexed"MySQL 索引表(当前实现)
/// - "mysql_fulltext"MySQL 全文索引
/// - "mysql/legacy":原 MySQL 兜底 SQL兼容旧版
/// </para>
/// <para>
/// 【C# 语法知识点 - 属性默认值】
/// = "es" 是属性的默认值。
/// 如果配置文件没有设置这个字段,就使用默认值 "es"。
///
/// 对比 Java
/// Java 需要在字段声明或构造函数中设置默认值:
/// private String engine = "es";
/// </para>
/// </summary>
public string Engine { get; set; } = "es";
/// <summary>
/// 新搜索失败或索引尚未建立时,是否回退旧 SQL 搜索。
/// <para>
/// 【降级策略】
/// 这是"优雅降级"的设计:
/// 1. 优先使用新搜索引擎(性能更好)
/// 2. 如果失败,自动回退到旧 SQL保证可用性
///
/// 对比 Java 若依:
/// 若依的搜索也有类似的降级机制,但通常在代码中硬编码。
/// 这里通过配置控制,更灵活。
/// </para>
/// </summary>
public bool EnableLegacyFallback { get; set; } = true;
/// <summary>
/// 搜索专用连接串。
/// <para>
/// 【数据库隔离策略】
/// 搜索功能可以:
/// 1. 使用独立的数据库(推荐,隔离搜索负载)
/// 2. 复用主库连接(简单,但不适合高并发搜索场景)
///
/// 这个配置项设置独立的搜索数据库连接字符串。
/// 如果为空,会根据 UseMainDbConnectionWhenEmpty 决定是否回退。
/// </para>
/// </summary>
public string ConnectionString { get; set; }
/// <summary>
/// 连接串为空时,是否复用主业务库连接。
/// </summary>
public bool UseMainDbConnectionWhenEmpty { get; set; } = true;
/// <summary>
/// 全量重建时的批处理大小。
/// <para>
/// 【批量处理说明】
/// 搜索索引重建时,不是一次性加载所有数据,
/// 而是分批处理,避免内存溢出和数据库压力过大。
///
/// 默认 200 条/批,可根据服务器内存调整。
/// </para>
/// </summary>
public int BatchSize { get; set; } = 200;
/// <summary>
/// 单次搜索最多返回多少条候选记录。
/// <para>
/// 【性能保护】
/// 限制返回条数,避免:
/// 1. 用户搜索太宽泛的关键词(如"a")返回过多结果
/// 2. 前端渲染大量数据卡顿
/// 3. 网络传输过大的响应
/// </para>
/// </summary>
public int TakeLimit { get; set; } = 500;
/// <summary>
/// 是否在运行时自动初始化搜索表结构。
/// <para>
/// 【自动建表】
/// 如果开启,应用启动时会检查并创建搜索表。
///
/// 生产环境建议关闭,由 DBA 手动管理表结构。
/// 开发/测试环境可以开启,方便快速启动。
/// </para>
/// </summary>
public bool AutoInitSchema { get; set; } = true;
/// <summary>
/// 配置后处理方法。
/// <para>
/// 【C# 语法知识点 - PostConfigure 模式】
/// PostConfigure 是 IConfigurableOptions 接口的方法。
/// 框架在绑定配置后会调用这个方法,用于:
/// 1. 校验配置值是否合法
/// 2. 设置默认值
/// 3. 修正不合理的配置
///
/// 对比 Java Spring Boot
/// Java 通常用 @PostConstruct 或 @Validated 注解实现类似功能:
/// @PostConstruct
/// public void init() {
/// if (batchSize < 1 || batchSize > 1000) {
/// batchSize = 200;
/// }
/// }
/// </para>
/// <para>
/// 【Math.Clamp 方法】
/// Math.Clamp(value, min, max) 把值限制在 [min, max] 范围内:
/// - 如果 value &lt; min返回 min
/// - 如果 value &gt; max返回 max
/// - 否则返回 value
///
/// 这是 .NET Core 2.0 引入的便捷方法,比手写 if-else 更简洁。
/// </para>
/// </summary>
/// <param name="options">配置选项实例</param>
/// <param name="configuration">配置对象</param>
public void PostConfigure(HwPortalSearchOptions options, IConfiguration configuration)
{
// 限制 BatchSize 在 1-1000 范围内,防止配置错误。
options.BatchSize = Math.Clamp(options.BatchSize, 1, 1000);
// 限制 TakeLimit 在 20-1000 范围内。
options.TakeLimit = Math.Clamp(options.TakeLimit, 20, 1000);
// 如果 Engine 为空或空白,使用默认值 "es"。
options.Engine = string.IsNullOrWhiteSpace(options.Engine) ? "es" : options.Engine.Trim();
}
}