Files
tfluceecrud/Application.cfc
T

165 lines
8.4 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!---
Application.cfc — конфигурация Lucee CRUD-приложения
Жизненный цикл:
1. OnApplicationStart — вызывается ОДИН раз при старте приложения
- читает TABLE_NAME из env vars (json_env в Terraform)
- создаёт таблицу CREATE TABLE IF NOT EXISTS
- сохраняет имя таблицы в application.tableName
2. OnRequestStart — вызывается ПЕРЕД каждым запросом
- копирует application.tableName → request.tableName
3. OnRequest — вызывает index.cfm с CRUD-логикой
Datasource: testds, конфигурируется из env vars с префиксом testds_
(testds_class, testds_connectionString, testds_username, testds_password, ...)
Terraform json_env должен содержать:
- TABLE_NAME — имя таблицы (по умолчанию check_point)
- testds_class — JDBC-драйвер
- testds_connectionString — строка подключения к PostgreSQL
- testds_username — имя пользователя БД
- testds_password — пароль пользователя БД
--->
<cfcomponent displayname="Application" output="true">
<!--- Идентификатор приложения для Lucee --->
<cfset this.Name = "tfluceecrud" />
<!--- Таймаут приложения: 3 часа бездействия → перезапуск (вызовет OnApplicationStart заново) --->
<cfset this.applicationTimeout = createTimeSpan(0, 0, 3, 0) />
<!--- Включаем сессии для защиты от CSRF (Lucee автоматически добавляет токены) --->
<cfset this.sessionmanagement = "Yes" />
<!--- Сессия живёт 2 часа неактивности --->
<cfset this.sessiontimeout = CreateTimeSpan(0, 0, 120, 0) />
<!--- Имя datasource по умолчанию — используется в cfquery без атрибута datasource --->
<cfset this.datasource = "testds" />
<!--- Конфигурируем datasource из env vars с префиксом testds_ --->
<cfset getDS(this.datasource, this.datasource) />
<!--- Отключаем отладку на проде, таймаут запроса 20 секунд --->
<cfsetting requesttimeout="20" showdebugoutput="false" />
<!---
OnApplicationStart — выполняется ОДИН раз при старте приложения.
Здесь: создаём таблицу если её нет, сохраняем имя в application scope.
application scope — живёт пока приложение не перезапустится (таймаут 3 часа).
Используем application а не request потому что request умирает после каждого запроса.
--->
<cffunction name="OnApplicationStart" access="public" returntype="boolean">
<!--- 1. Читаем имя таблицы из переменной окружения TABLE_NAME --->
<cfset var tableName = createObject("java", "java.lang.System").getEnv().get("TABLE_NAME") />
<!--- 2. Если переменная не задана в json_env — используем значение по умолчанию --->
<cfif NOT isDefined("tableName") OR NOT len(tableName)>
<cfset tableName = "check_point" />
</cfif>
<!--- 3. Сохраняем в application scope — доступно всем запросам этого приложения --->
<cfset application.tableName = tableName />
<!--- 4. Создаём таблицу если она ещё не существует --->
<!--- id: автоинкрементный первичный ключ --->
<!--- value: текстовое поле для CRUD-значений --->
<cftry>
<cfquery>
CREATE TABLE IF NOT EXISTS #tableName# (
id SERIAL PRIMARY KEY,
value TEXT NOT NULL DEFAULT ''
)
</cfquery>
<!--- Игнорируем ошибки: нет прав, БД недоступна --->
<cfcatch type="database"></cfcatch>
</cftry>
<cfreturn true />
</cffunction>
<!---
OnRequestStart — выполняется ПЕРЕД каждым HTTP-запросом.
Здесь: копируем имя таблицы из application в request scope.
request scope — живёт только в течение одного запроса.
Каждая страница (index.cfm) читает request.tableName.
--->
<cffunction name="OnRequestStart" access="public" returntype="boolean">
<!--- Если приложение уже стартовало — берём имя из application --->
<cfif isDefined("application.tableName")>
<cfset request.tableName = application.tableName />
<!--- Иначе (первый запрос до OnApplicationStart) — fallback --->
<cfelse>
<cfset request.tableName = "check_point" />
</cfif>
<cfreturn true />
</cffunction>
<!---
OnRequest — обработчик каждого запроса.
Включает целевой шаблон (index.cfm) с установленной кодировкой.
--->
<cffunction name="OnRequest" access="public" returntype="void">
<cfargument name="template" type="string" required="true" />
<!--- UTF-8 для форм и URL-параметров --->
<cfset setEncoding("FORM", "UTF-8") />
<cfset setEncoding("URL", "UTF-8") />
<!--- Вычисляем web-корень для ссылок --->
<cfset local.basePath = getDirectoryFromPath(getCurrentTemplatePath()) />
<cfset request.webRoot = "../" />
<cfset request.thisPage = Replace(ReplaceNoCase(expandPath(arguments.template), local.basePath, ""), "\", "/") />
<!--- Выполняем запрошенный шаблон (index.cfm) --->
<cfinclude template="#arguments.template#" />
</cffunction>
<!---
getDS — конфигурирует datasource Lucee из переменных окружения.
Соглашение об именах env vars:
{prefix}_{field} → параметр datasource
Пример для testds:
testds_class → JDBC-драйвер
testds_connectionString → jdbc:postgresql://host:5432/db
testds_username → пользователь
testds_password → пароль
Все параметры передаются через json_env в Terraform.
--->
<cffunction name="getDS" access="private" returntype="void">
<cfargument name="dsname" type="string" required="true" hint="Имя datasource (testds)" />
<cfargument name="prefix" type="string" default="#dsname#" hint="Префикс env vars" />
<!--- Java-объект для чтения переменных окружения --->
<cfset var system = createObject("java", "java.lang.System") />
<!--- Словарь параметров datasource --->
<cfset var ds = {} />
<!--- Перебираем все возможные поля datasource --->
<cfloop list="class,connectionString,username,password,bundleName,bundleVersion,connectionLimit,liveTimeout,validate" item="field">
<!--- Читаем env var: {prefix}_{field}, например testds_username --->
<cfset var value = system.getEnv("#arguments.prefix#_#field#") />
<!--- Если переменная задана и не пуста — добавляем в datasource --->
<cfif isDefined("value") AND len(value)>
<cfset structInsert(ds, field, value) />
</cfif>
</cfloop>
<!--- Регистрируем datasource в Lucee --->
<cfset THIS.datasources[dsname] = ds />
</cffunction>
</cfcomponent>