You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何向每个TWebModule实例传递主单元读取的INI布尔配置值

问题:WebBroker服务中跨WebModule实例访问全局INI配置值的实现方案

我搭建的Web服务结构如下:
主单元(类型为TForm):

private
  FWebBrokerBridge: TIdHTTPWebBrokerBridge;

// 构造函数内逻辑
  FWebBrokerBridge := TIdHTTPWebBrokerBridge.Create(Self);    // TIdHTTPWebBrokerBridge 定义于 IdHTTPWebBrokerBridge.pas,继承自TIdCustomHTTPServer
  FWebBrokerBridge.RegisterWebModuleClass(TWebModuleWebServices);
  FWebBrokerBridge.... // 其他属性配置
  FWebBrokerBridge.DefaultPort := FPort;
  FWebBrokerBridge.Active := True;

TWebModuleWebServices定义在如下单元:

unit DMWebServices;

interface

type
   TWebModuleWebServices = class(TWebModule)
      procedure WebModuleCreate(Sender: TObject);

      procedure WebModuleAfterDispatch(Sender: TObject; Request: TWebRequest;
        Response: TWebResponse; var Handled: Boolean);
      procedure WebModuleBeforeDispatch(Sender: TObject; Request: TWebRequest;
        Response: TWebResponse; var Handled: Boolean);
        
      procedure WebModuleWebServicesTTInfoAction(Sender: TObject;
        Request: TWebRequest; Response: TWebResponse; var Handled: Boolean);
      // 其他Action定义

主单元会从INI配置文件读取一个布尔类型配置值,需要在每一个TWebModuleWebServices实例中都能访问到该值,现有几个待选思路:

  • WebModuleCreate事件的Sender是TWebModuleWebServices实例本身,看起来没法通过这个事件传参,是否可以重写Create构造方法实现传值?
  • 是否可以借助TWebModuleWebServices的Tag属性传递该配置值?
  • 是否可以直接用全局变量或者单例模式存储该值?毕竟只是一个简单的全局布尔配置,逻辑不复杂。

以上哪种实现更合理优雅?有没有更优方案?


回答

先逐个说下三个待选思路的实际问题:

  • 重写带参Create构造传值:走不通
    TIdHTTPWebBrokerBridge内部是靠注册的WebModule类引用,通过无参构造反射创建实例的。就算写了带参数的构造,桥接组件根本不会调用,完全没用。如果硬改无参构造去外部拉配置,本质还是要找公共存储位置,多此一举。
  • 用Tag属性传值:走不通
    Tag是实例属性,注册WebModule的时候只传了类,后续每个请求进来才会动态创建实例,根本没有提前给实例设置Tag的时机。
  • 全局变量/单例存储:能用,但别写在主窗体单元
    别图省事在主窗体单元定义全局变量,会让DMWebServices单元和主窗体单元产生循环引用,后期改代码牵一发动全身。

推荐实现

对单布尔值的简单场景,根本不需要搞复杂的传参或者重写逻辑,直接在DMWebServices单元定义单元级变量即可:

unit DMWebServices;

interface

var
  GYourBoolConfig: Boolean; // 对应INI里读出来的布尔配置项

type
   TWebModuleWebServices = class(TWebModule)
      // 原有所有事件、Action定义完全不用改
      procedure WebModuleCreate(Sender: TObject);
      procedure WebModuleAfterDispatch(Sender: TObject; Request: TWebRequest;
        Response: TWebResponse; var Handled: Boolean);
      procedure WebModuleBeforeDispatch(Sender: TObject; Request: TWebRequest;
        Response: TWebResponse; var Handled: Boolean);
      procedure WebModuleWebServicesTTInfoAction(Sender: TObject;
        Request: TWebRequest; Response: TWebResponse; var Handled: Boolean);
      // 其余Action
   end;

implementation

// 原有业务逻辑不动,任何WebModule实例的事件里直接读GYourBoolConfig即可
procedure TWebModuleWebServices.WebModuleCreate(Sender: TObject);
begin
  if GYourBoolConfig then
  begin
    // 对应配置下的初始化逻辑
  end;
end;

end.

主窗体单元只需要引用DMWebServices,在启动HTTP服务之前,把INI读出来的配置值直接赋给GYourBoolConfig就完事。
如果后续配置项变多,就把这些配置封成一个TAppConfig记录或者轻量单例类,放在独立的公共配置单元,所有WebModule直接访问即可。

注意:WebBroker的WebModule是请求级实例,每个请求进来都会新建一个,请求处理完就释放,绝对不要在WebModule内部存储全局状态,所有跨请求的全局配置、公共状态统一存在单元级变量/独立配置类里,避免出现状态串扰的问题。


内容的提问来源于stack exchange,提问作者Jan Doggen

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.29 12:15:28