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#

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

// ============================================================================
// 【文件说明】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();
}
}