8

我需要一个现实检查 - 并希望一个解释(如果我的现实是错误的)。

CF 应用程序框架评估事物的方式是这样的(我的理解)——请求被传递给 cfserver

  • cf 查找 application.cfm 或 cfc(基于遍历规则)

  • application.cfc 执行(如果找到)

  • 设置了THIS范围(可以在此处设置一系列特定于应用程序的变量,但

有些是必需的 - 例如“applicationTimeout” - 然后会发生一系列事件 - 如果需要,会触发方法。

-- onApplicationStart()

----onSessionStart()

------onRequestStart()

等等

所以我的问题

1)这个设置发生在每个页面请求上 - 在其他任何事情之前?

2)如果我在 onApplicationStart() 中设置了一个应用程序变量 - 它在之后发生的任何进程中都可用 - 并且应该在内存中持续存在 applicationTimeout() 的长度 - 对吗?

3)所以如果我做这样的事情......

if ( isdefined("application.myvar" ) { this.something = application.myvar; }

它应该在启动应用程序范围的初始请求之后处理任何页面请求。

但是它似乎没有这样做。

我问的原因是这个 - 有一些有趣的应用程序杠杆设置需要在这个范围内设置......其中一些可能是“密集的”(至少从执行每个请求的角度来看 - 所以我想要只做一次,在持久内存中设置一个结构,然后将它们作为 THIS 使用。

我做了一些错误的假设吗?

谢谢

4

5 回答 5

3

There's two things at play here: when code runs, and when variable scopes are availed and how long they last.

  • The code outwith any method (ie: the "pseudoconstructor") runs every request. Obviously minimise the amount of code in this part of the CFC.
  • Code in various event handlers run as indicated by the event handler name, eg: onApplicationStart() code runs only once, when the application starts. Ditto onSessionStart() only runs once per new session.

Scopes:

  • this scope is available throughout the CFC. Behaves exactly like the this-scope in any other CFC, except some this-scoped variables have special meaning (like this.name, this.datasource, etc). Those special-meaning variables can be changed per session or per request in the relevant handlers, but seem to apply to the entire system (ie: not for the specific session or request making the setting change). In normal CFCs, the this scope is used to expose public variables, but as there is no public instance of Application.cfc, there is no point using the this scope beyond making those special settings. If one wants to have variables available to all methods within the CFC, use the variables scope as one normally would. Contrary to someone's advice here, this-scoped variables are NOT the same as application-scoped variables.
  • The request scope is also available throughout the CFC (pseudo constructor and methods). These will also be available to the calling code of templates called later in the request, like any other request-scoped variables.
  • Application scope: not available in the pseudo-constructor, even after the this.name setting is made. Only becomes available in onApplicationStart() and thenceforth from there.
    • Session scope: similarly, not available in the pseudo-constructor or onApplicationStart()l and not until onSessionStart().

I've demonstrated this in a blog post (test code provided), over here. it's too lengthy to include here, but the stuff above summarises it.

于 2012-08-15T23:08:12.043 回答
3

ColdFusion Application.cfc 文档包含以下知识:

当请求执行时,ColdFusion 按以下顺序运行 CFC 方法:

  1. onApplicationStart(如果之前没有为此应用程序运行)
  2. onSessionStart(如果之前没有为此会话运行)
  3. onRequestStart
  4. onRequest/onCFCRequest
  5. 请求结束

onApplicationEnd、onSessionEnd 和 onError CFC 由特定事件触发。

整个请求顺序(至少)还有两个步骤。

0:执行所有cfcomponent不在 a 中的代码cffunction
0.5:运行相当于cfapplication创建应用程序的标签

因此,您的问题的答案是:

  1. 如果您在步骤 0 中设置这些变量,那么可以。
  2. 正确的。
  3. 这取决于您在哪里设置变量。如果您尝试更改的值列在Application.cfc 的应用程序变量文档页面上,则它们必须在步骤 0 中。在其他位置设置它们将更新this范围,但不会在步骤 0.5 中生效。
于 2012-08-14T09:21:37.967 回答
1

请查看评论,因为它看起来像下面的帖子有效,但它没有。如果您转储 this 范围,则会显示您的新值,但它实际上不会更改任何应用程序设置。

您可以随心所欲地更改任何应用程序设置;但是,由于每次请求页面时都会运行伪构造函数,因此您需要在伪构造函数运行后不断更改设置。应用程序范围在伪构造函数中不可用,因此您可以在 onRequestStart 或 onRequest 函数中执行此操作。我已经完成了一个简单的测试,根据 onRequestStart 函数中的条件重新分配 customtagpaths。当您第一次访问该页面时,您会注意到自定义标签文件夹将是“customtags”,其他请求将显示“someOtherCustomtagsFolder”附带说明,如果您的应用程序设置基于每个用户更改,您的全局应用程序设置将被翻转并可能导致其他用户设置不正确。

<cfcomponent>
<!--- pseudo constructor --->
<cfset this.customtagpaths = expandPath('./customtags')>

<!--- onRequestStart --->
<cffunction name = "onRequestStart" returnType="void">
     <cfif structKeyExists(application,'testSetting')>
          <cfset this.customtagpaths = expandPath('./someOtherCustomtagsFolder')>
     </cfif>
</cffunction>

<!--- onRequest --->
<cffunction name = "onRequest" returntype="void">
     <cfargument name="targetPage" type="String" required = "true" />
     <cfdump var = "#this#" label = "this">
     <cfset application.testSetting = "foo">
     <cfinclude template="#Arguments.targetPage#">
</cffunction>
</cfcomponent>
于 2012-08-14T11:50:15.057 回答
-1

Application.cfc 文件中此范围内的任何内容都将成为应用程序变量,并且每个应用程序生命周期仅创建一次。应用程序启动后,Application.cfc 中没有其他用户对此进行操作。

第一次运行 CF 应用程序时,onApplicationStart() 的内容在 onRequest/Start/End 之前运行(“CF10 中的新功能”onServerStart() 除外)。

在应用程序的任何位置设置的任何应用程序变量都存在,直到应用程序停止。

您来自 #3 的代码应该是

if ( !structKeyExists( application, "myvar" ) { application.myvar = foo; }

然后在需要的地方引用 application.myvar。

根据您的描述,不需要将任何内容添加到this范围,只需将其放入 application 范围即可。

于 2012-08-13T15:08:24.097 回答
-2

应用程序范围在 Application.cfc 伪构造函数中不可用,因为在设置 this.name 之前,无法将请求绑定到应用程序。

如果您担心创建应用程序映射的开销,一种方法是将它们缓存在可用的服务器范围内。

if(!structkeyexists(server, 'myappmappings')){ server.myappmappings = createMappings(); } this.mappings = server.myappmappings;

您也许还可以使用 cachePut/cache Get 将映射存储在 ehcache 中,但我没有在伪构造函数中尝试过。

于 2012-08-13T17:46:22.140 回答