2

我在我的 ColdFusion 应用程序中广泛使用组件,并且经常遇到我的组件未定义的错误,尽管它们确实已定义。

我在 Application.cfc 文件中定义组件。

 <cfset cfcList = "component1,component2,component3">
 <cfloop list="#cfcList#" index="local.thisCfcName">
      <cfset application.cfc[local.thisCfcName] = createObject(
        "component",
        "#application.cfcPath##local.thisCfcName#"
      )>
  </cfloop>

我已经能够确定:在我的 onRequestStart 函数中,我在遇到'init' url 变量时重新启动应用程序:

<cfif structKeyExists(url, "init")>
  <cfset onApplicationStart()>
</cfif>

似乎在应用程序重新初始化时,任何其他尝试访问该组件的用户都会收到以下错误(失败的组件可能会有所不同)。

[diag]=元素 CFC.COMPONENT1 在类 [Ljava.lang.String; 类型的 Java 对象中未定义;引用为 ''

我在这里做错了什么可以解决这个问题吗?我每天都会多次收到这些错误,并且必须有解决方案,但我无法找到有关此特定问题的任何信息。

4

1 回答 1

3

要回答您的问题,您几乎肯定会遇到竞争条件。CF 仅在应用程序首次启动时锁定应用程序范围:

当 ColdFusion 收到应用程序中的第一个页面请求时运行

之后,如果您OnApplicationStart()明确调用:

... ColdFusion 不启动应用程序;它确实执行方法代码,但在方法执行时不锁定应用程序范围

因此,任何其他尝试从应用程序范围读取的线程/请求都可能会出错,因为第一个线程仍在同时修改范围。您需要一个独占应用程序 cflock以防止任何其他线程访问范围,直到修改完成。

顺便说一句,虽然它不会完全消除竞争条件的可能性,但使用单独的变量进行初始化,并且仅在完成时分配,会减少发生冲突的机会窗口:

 <cfloop ...> 
     <cfset local.someVariable[key] = ....>
 </cfloop>

 <cfset application.someVariable = local.someVariable>

说了这么多,我同意你肯定希望如此频繁地刷新应用程序范围。

于 2018-12-22T07:32:03.543 回答