Статьи

Управление настройками приложения для конкретной среды с помощью компонента ColdSpring

Когда я разрабатываю свои приложения ColdFusion, я работаю в двух разных средах. Я разрабатываю приложения на своем локальном компьютере, а затем внедряю их на сервер, когда достигаю определенных этапов или когда он готов к ограниченному пользовательскому тестированию. Несмотря на то, что я максимально имитирую серверную среду на своем локальном компьютере, все еще существуют определенные аспекты приложения, которые отличаются при запуске на сервере. Например, мой локальный компьютер не настроен на отправку и получение электронной почты, но я хочу, чтобы мое приложение (когда оно работает в рабочей среде) отправляло электронную почту при выполнении определенных функций.

Для решения этой проблемы я использовал запуск ряда функций с помощью функции onApplicationStart () в Application.cfc, которая определяла бы, где выполняется приложение (разработка или производство), записывал этот факт в переменную области приложения, называемую «locale», а затем задайте ряд дополнительных переменных области приложения в зависимости от текущей среды. Затем я бы кодировал определенные аспекты своих приложений, например, те, которые отвечают за отправку электронной почты, чтобы проверить значение переменной application.locale, чтобы определить, должна ли выполняться определенная функция, а затем использовать любые другие параметры уровня приложения, необходимые для фактической выполнение (например, адрес электронной почты, связанный с приложением).

Недавно я начал использовать Model-Glue в качестве моей прикладной среды, и, поскольку Model-Glue использует ColdSpring для управления некоторыми своими внутренними настройками, я решил пересмотреть свою технику, чтобы также использовать преимущества ColdSpring.

Вот код appConfig.cfc, который я создал для управления настройками приложения:

<cfcomponent displayname="appConfig" hint="I provide the configuration settings for the application dependent on where the application is running.">

    <cffunction name="init" access="public" returntype="any" hint="I accept all of the possible setting configurations">
        <cfargument name="universalSettings" type="struct" required="true" hint="A struct of all of the configuration settings that are true regardless of environment" />
        <cfargument name="localSettings" type="struct" required="true" hint="A struct of all of the configuration settings for the local environment" />
        <cfargument name="remoteSettings" type="struct" required="true" hint="A struct of all of the configuration settings for the remote environment" />
        <cfset var loc= StructNew()>
        <cfset variables.config= StructNew()>
        <cfloop collection="#arguments.universalSettings#" item="loc.ukey">
            <cfset variables.config[loc.ukey]= arguments.universalSettings[loc.ukey]>
        </cfloop>	
		
        <cfset loc.env= determineEnvironment()>
		
        <cfloop collection="#arguments[loc.env]#" item="loc.ekey">
            <cfset variables.config[loc.ekey]= arguments[loc.env][loc.ekey]>
        </cfloop>
		
        <cfreturn this />
    </cffunction>
	
    <cffunction name="determineEnvironment" access="private" output="false" returntype="string" hint="I determine the application environment">
        <cfif Left(cgi.cf_template_path,6) EQ "/Users">
            <cfreturn "localSettings" />
        <cfelse>
            <cfreturn "remoteSettings" />
        </cfif>
    </cffunction>
	
    <cffunction name="getConfig" access="public" output="false" returntype="any" hint="I return a config setting">
        <cfargument name="configName" type="string" required="true" hint="The name of the configuration setting">
        <cfreturn variables.config[arguments.configName]>
    </cffunction>
	
    <cffunction name="setConfig" access="public" output="false" returntype="void" hint="I set a config setting">
        <cfargument name="configName" type="string" required="true" hint="The name of the configuration setting">
        <cfargument name="configValue" type="any" required="true" hint="The value/data to store in the configuration setting">
        <cfset variables.config[arguments.configName]= arguments.configValue>
    </cffunction>
	
</cfcomponent>

Функция конструктора init () принимает три структуры в качестве аргументов: одна, которая содержит универсальные параметры приложения, которые являются одинаковыми независимо от среды, другая, которая содержит параметры конфигурации приложения для моей локальной среды / среды разработки, и другая, которая содержит параметры конфигурации, специфичные для моя удаленная / производственная среда. Универсальные настройки копируются в структуру «config» в области действия переменных, а затем вызывается вызов функции defineEnvironment () для определения текущей среды приложения. Функция defineEnvironment () использует cgi.cf_template_path, чтобы определить, работает ли текущий шаблон ColdFusion в системе Macintosh (мой рабочий ноутбук — Mac), и возвращает имя аргумента конструктора, который должен использоваться для заполнения оставшейся части » конфиг «структура.Функция getConfig () предоставляет средства для получения значения параметра конфигурации, в то время как функция setConfig () позволяет вам изменять параметр конфигурации.

Поэтому заполнение этого объекта appConfig правильными параметрами конфигурации приложения — это просто вопрос предоставления трех различных структур конфигурации в аргумент конструктора init (). Вот где ColdSpring вступает в игру: ColdSpring идеально подходит для управления и документирования данных и объектов, которые необходимо внедрить в одноэлементные объекты. Вот пример определения компонента ColdSpring (в файле ColdSpring.xml) для объекта appConfig:

<bean id="appConfig" class="myApp.model.csBeans.appConfig">
    <constructor-arg name="universalSettings">  
        <map>
            <entry key="ds"><value>myDatasource</value></entry>
            <entry key="appName"><value>myApp</value></entry>
            <entry key="approot"><value>/myApp</value></entry>
        </map>
    </constructor-arg>
    <constructor-arg name="localSettings">  
        <map>
            <entry key="locale"><value>local</value></entry>
            <entry key="emailNotification"><value>false</value></entry>
            <entry key="uploadDirectory"><value>/Users/Brian/Websites/myApp/fileRepo/</value></entry>
        </map>
    </constructor-arg>
    <constructor-arg name="remoteSettings">  
        <map>
            <entry key="locale"><value>remote</value></entry>
            <entry key="emailNotification"><value>true</value></entry>
            <entry key="errorSenderName"><value>myApp System</value></entry>
            <entry key="errorSenderEmail"><value>myApp@domain.org</value></entry>
            <entry key="errorDefaultSubject"><value>An error has occurred in the myApp system</value></entry>
            <entry key="uploadDirectory"><value>/wwwroot/myApp/uploadedFiles/</value></entry>
        </map>
    </constructor-arg>
</bean>

Как видите, определение bean-компонента ColdSpring содержит три XML-блока <constructor-arg>, по одному для каждого аргумента, передаваемого в appConfig.cfc во время создания экземпляра, а каждый аргумент конструктора содержит XML-блок <map>, который определяет переменную структуры за этот аргумент.

В чем преимущество определения этих настроек в ColdSpring? Как только объект appConfig определен как bean-компонент ColdSpring, я могу внедрить bean-компонент appConfig в любой другой объект одноэлементного компонента, который я определил в ColdSpring, или получить appConfig из объекта ColdSpring beanFactory (который обычно создается во время запуска приложения). Кроме того, Model-Glue позволяет очень просто вводить bean-компоненты ColdSpring в любой из ваших объектов контроллера, просто передавая список имен bean-компонентов ColdSpring в атрибут «beans» либо в & lt; cfcontroller & gt; контроллера тег или начальный & lt; контроллер & gt; тег блока XML контроллера в файле ModelGlue.xml приложения (см. « Как использовать Bean Injection»«на странице документации Model-Glue для получения более подробной информации об этом.) И имеет смысл поместить параметры конфигурации моего приложения вместе с параметрами конфигурации Model-Glue в ColdSpring, так что есть только один файл, к которому я должен обратиться для своих данных конфигурации.

Конечный результат? Я получаю объект appConfig, содержащий правильные настройки приложения для текущей среды, из которых мой код может извлекать переменные настройки всякий раз, когда поведение функции зависит от среды приложения.

Этот метод, который я только что обрисовал, работает для меня, потому что я являюсь индивидуальным разработчиком только с двумя средами приложений, простым способом определения среды, в которой выполняется приложение, и, как правило, только небольшим количеством параметров приложения, зависящих от среды. с. Если вы работаете в команде или с несколькими средами приложений, вам нужен более надежный подход. Одним из вариантов, который вы можете рассмотреть, является проект Environment Config на RIAForge.org . Проект также позволяет использовать ColdSpring для определения переменных среды, но предоставляет больше возможностей для разграничения между различными средами приложений и большую гибкость в структурировании и получении информации о конфигурации приложения. Он все еще находится в бета-версии, но выглядит многообещающе.