ColdFusion-何时使用"请求"范围?

时间:2020-03-05 18:42:44  来源:igfitidea点击:

遍历了我前任的代码,并经常看到"请求"范围的用法。此范围的适当用法是什么?

解决方案

回答

代码的任何部分都可以使用几个作用域:会话,客户端,Cookie,应用程序和请求。不建议以某些方式使用某些方法(例如,在自定义标签或者CFC中使用"请求"或者"应用程序"范围;这是耦合的,违反了封装原则,被认为是不好的做法),还有一些方法有特殊目的:Cookie保留在客户端机器作为物理Cookie,会话范围变量是特定于用户的,并且随用户在网站上的会话而终止。

如果变量极不可能更改(对于所有意图和目的而言都是恒定的)并且可以在应用程序启动时简单地初始化并且不再写入,则通常应将其放入"应用程序"范围,因为这会在每个用户和每个会话之间保持不变。正确实施后,它将被写入一次,并被读取N次。

在Application.cfm中正确实现Application变量可能如下所示:

<cfif not structKeyExists(application, "dsn")>
    <cflock scope="application" type="exclusive" timeout="30">
        <cfif not structKeyExists(application, "dsn")>
            <cfset application.dsn = "MyDSN" />
            <cfset foo = "bar" />
            <cfset x = 5 />
        </cfif>
    </cflock>
</cfif>

请注意,在锁定前后检查应用程序范围中变量的存在,因此,如果两个用户在应用程序启动时创建了竞争条件,则其中只有一个最终将设置应用程序变量。

这种方法的好处是,它不会在每次请求时不断刷新这些存储的变量,从而浪费了用户的时间和服务器的处理周期。权衡是它有点冗长而复杂。

通过添加Application.cfc,可以大大简化此操作。现在,我们可以指定在应用程序启动时创建哪些变量,而不必担心锁定和检查是否存在以及所有这些有趣的东西:

<cfcomponent>
    <cfset this.name = "myApplicationName" />

    <cffunction name="onApplicationStart" returnType="boolean" output="false">
        <cfset application.dsn = "MyDSN" />
        <cfset foo = "bar" />
        <cfset x = 5 />
        <cfreturn true />
    </cffunction>
</cfcomponent>

有关Application.cfc的更多信息,包括所有可用的各种特殊功能以及有关使用方法和使用方法的每一个小细节,我建议在Raymond Camden的博客上发表此文章。

总而言之,请求范围可在代码中的任何地方使用,但这并不一定使在任何地方使用它都"正确"。前任可能会使用它来破坏封装,并且重构起来可能很麻烦。我们可能最好保持原样,但是了解哪个范围是完成这项工作的最佳工具肯定可以使我们将来的代码变得更好。

回答

这是一个非常主观的问题,甚至有人认为,在现代ColdFusion应用程序中使用请求范围从来都不是"合适的"。

有了这个免责声明,让我们定义请求范围是什么以及在什么地方有用。

请求范围是单个ColdFusion页面请求中的绝对全局范围。它不是共享作用域,例如应用程序,服务器,客户端和会话作用域,因此不必进行锁定即可使其具有线程安全性(除非我们使用CF8的CFTHREAD标记从单个请求中生成工作线程)。作为全局作用域,这是一种非常方便的方法,可以将变量保留在请求堆栈中的任何级别上,而不必将其从父级传递给调用方。这是在较旧的CF应用程序中通过嵌套或者递归自定义标签持久保存变量的一种常见方法。

请注意,尽管许多应用程序使用此范围存储应用程序级变量(例如,配置设置),但请求范围和应用程序范围之间的巨大差异(有时是细微的差异)是,相同的请求范围变量的值可以在各个页面请求之间有所不同。

我猜想前任使用此范围作为一种手段来方便地设置变量,以使其在代码的封装或者嵌套单元之间的跳转中幸免,而不必显式传递它们。

回答

好的,我只想评论代码。如果我看起来疯了,请原谅我。但是我们已经在开始时验证了structKeyExists。既然我们知道这将是真的,那么再进行一次检查就没有意义了。所以我的版本是这个……但那只是我。

<cfif not structKeyExists(application, "dsn")>
    <cflock scope="application" type="exclusive" timeout="30">
            <cfset application.dsn = "MyDSN" />
            <cfset foo = "bar" />
            <cfset x = 5 />
    </cflock>
</cfif>

好吧。