如何向每个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
相关产品推荐
相关产品推荐

