Разработка и Конфигурация · 12 мин
Как объявить глобальную переменную на сервере в 1С
Как объявить глобальную переменную на сервере в 1С: модуль сеанса, Экспорт, разделители, параметры сеанса. Примеры кода, ошибки и проверка результата.
Во встроенном языке 1С нет привычных «глобальных переменных приложения» в стиле других языков: нельзя просто написать ГлобальнаяПеременная = Значение; в произвольном месте и читать её отовсюду. Область видимости переменной определяется модулем, в котором она объявлена, и директивами компиляции. Чтобы получить значение, доступное на сервере из разных процедур и модулей, используют несколько законных механизмов: экспортные переменные модуля сеанса, общие серверные модули с функциями-кешами, параметры сеанса и константы.
Выбор механизма зависит от трёх вопросов: нужно ли значение только на время сеанса или между сеансами, должно ли оно различаться для разных пользователей, и допустимо ли хранить его в базе данных. Неправильный выбор приводит либо к потере данных при перезапуске сеанса, либо к лишним обращениям к базе на каждый вызов, либо к ошибкам компиляции «переменная не определена».
Ниже разобраны рабочие способы объявить серверную «глобальную» переменную с примерами кода, ограничениями каждого подхода и проверкой результата. Все примеры применимы к управляемому приложению на платформе 8.3.
Почему в 1С нет классических глобальных переменных
Переменная, объявленная через Перем внутри процедуры или функции, существует только в ней. Переменная, объявленная в разделе описания переменных модуля (вне процедур), доступна во всех процедурах этого модуля, но не за его пределами. Ключевое слово Экспорт делает такую переменную доступной из других модулей — но только если сам модуль существует в нужном контексте выполнения.
На сервере контекст формируется по-другому, чем на клиенте. Модуль приложения в управляемом режиме исполняется на клиенте, поэтому объявленная там переменная на сервере недоступна в принципе — это частая причина ошибки «Переменная не определена» при вызове серверной процедуры. Серверный контекст верхнего уровня формирует модуль сеанса и общие модули с флагом «Сервер».
Поэтому задача «объявить глобальную переменную на сервере» на практике сводится к выбору одного из четырёх контейнеров: модуль сеанса, общий серверный модуль, параметр сеанса или объект метаданных (константа, регистр). Каждый вариант разберём отдельно.
Способ 1: экспортная переменная модуля сеанса
Модуль сеанса — самый близкий аналог глобальной переменной на сервере. Он компилируется в серверном контексте, а его экспортные переменные видны из общих модулей, модулей объектов и серверных процедур форм в течение всего сеанса.
Чтобы создать такую переменную, откройте конфигуратор, найдите в дереве конфигурации «Общие → Модуль сеанса» и объявите переменную с ключевым словом Экспорт:
Перем ТекущийКурсВалюты Экспорт;
Перем ПризнакОбменаВыполняется Экспорт;
Обращение к переменной из любого серверного кода выполняется напрямую по имени, без префикса модуля:
// В общем серверном модуле или модуле объекта
ТекущийКурсВалюты = ПолучитьКурсИзРегистра(Валюта, ТекущаяДатаСеанса());
Важное ограничение: значение живёт только в рамках сеанса. При завершении сеанса, перезапуске сервера 1С или разрыве соединения переменная теряется. Кроме того, у каждого сеанса — свой экземпляр значения: два пользователя не «увидят» чужие значения, что одновременно и преимущество (изоляция), и ограничение (нельзя разделить данные между сеансами).
Инициализация при старте сеанса
Начальное значение удобно задавать в обработчике УстановкаПараметровСеанса или в отдельной экспортной процедуре, которую вызывают при первом обращении. Учтите, что УстановкаПараметровСеанса выполняется очень рано — до аутентификации и до готовности части прикладных объектов, поэтому тяжёлые запросы к базе там лучше не выполнять.
Способ 2: общий серверный модуль с кеширующей функцией
Более управляемый вариант — общий модуль с установленными флагами «Сервер» и, при необходимости, «Вызов сервера». Вместо открытой переменной создают пару «закрытая переменная модуля + экспортная функция-геттер», которая вычисляет значение при первом обращении и дальше возвращает кешированное.
// Общий модуль ОбщегоНазначенияСервер (Сервер = Истина)
Перем КешНастроекОбмена;
Функция НастройкиОбмена() Экспорт
Если КешНастроекОбмена = Неопределено Тогда
КешНастроекОбмена = ЗагрузитьНастройкиИзБазы();
КонецЕсли;
Возврат КешНастроекОбмена;
КонецФункции
Такой подход даёт контроль над чтением: можно добавить логирование, проверку прав, сброс кеша отдельной процедурой СброситьКеш(). Переменная модуля без Экспорт недоступна снаружи, и случайно перезаписать её из чужого кода нельзя — это защищает от трудноуловимых ошибок.
Обратите внимание на свойство модуля «Повторное использование возвращаемых значений». Если установить его в «На время вызова» или «На время сеанса», платформа сама кеширует результат функций без параметров (и с одинаковыми параметрами). Это штатный механизм кеширования, который часто избавляет от необходимости вручную заводить переменные-кеши.
Способ 3: параметры сеанса
Если «глобальное» значение должно различаться по пользователям и устанавливаться при входе, правильный инструмент — параметры сеанса (ветка «Общие → Параметры сеанса» в конфигураторе). Это типизированные значения, доступные на чтение и запись из серверного кода через ПараметрыСеанса.ИмяПараметра.
// В модуле сеанса
Процедура УстановкаПараметровСеанса(ТребуемыеПараметры) Экспорт
ПараметрыСеанса.ТекущееПодразделение = НайтиПодразделениеПользователя();
КонецПроцедуры
// В любом серверном коде
Если ПараметрыСеанса.ТекущееПодразделение = Шапка.Подразделение Тогда
// ...
КонецЕсли;
Преимущество перед переменной модуля сеанса: параметры сеанса участвуют в механизме разделения данных и могут использоваться в ограничениях доступа к данным (RLS) на уровне запросов. Недостаток — тип параметра фиксируется в метаданных, и хранить там произвольные структуры нельзя, только значения указанных типов.
Способ 4: константы и хранение между сеансами
Если значение должно переживать перезапуск сеанса и сервера, никакая переменная не поможет — данные нужно писать в базу. Для одиночных значений (признак режима работы, текущий номер, настройка) предназначены константы: Константы.ИмяКонстанты.Установить(Значение) и Константы.ИмяКонстанты.Получить().
Для значений, различающихся по пользователям или измерениям, подойдёт регистр сведений. Чтение константы — это обращение к базе, поэтому в циклах и массовых обработках её значение принято читать один раз в локальную переменную, а не дёргать на каждой итерации.
Сравнение вариантов
Быстрый доступ без обращения к базе, живёт до конца сеанса. Не переживает перезапуск, не разделяется между сеансами.
Контролируемый кеш через функцию-геттер, можно сбросить. Требует аккуратности с флагами компиляции модуля.
Индивидуален для пользователя, работает в RLS. Тип фиксирован в метаданных, структуры хранить нельзя.
Хранится в базе, переживает перезапуск, общая для всех. Каждое чтение — обращение к БД, не подходит для частого доступа в циклах.
Пошагово: создаём серверную глобальную переменную
Ниже — полный порядок действий для самого востребованного сценария: значение, вычисляемое один раз и доступное всему серверному коду в течение сеанса.
- 1Откройте конфигуратор и перейдите: Общие → Модуль сеанса.
- 2Объявите переменную: Перем МоеЗначение Экспорт;
- 3В процедуре УстановкаПараметровСеанса или отдельной экспортной процедуре задайте начальное значение.
- 4Обновите конфигурацию базы данных (F7) — иначе изменения не попадут в серверный контекст.
- 5Из серверного кода обратитесь к переменной по имени и проверьте значение через отладчик или запись в журнал регистрации.
Проверка результата выполняется отладчиком: поставьте точку останова в серверной процедуре, которая читает переменную, и убедитесь, что значение заполнено. Если отладка сервера не настроена, временно выведите значение через ЗаписьЖурналаРегистрации и посмотрите его в журнале регистрации.
Как проверить результат
Конфигурация обновляется без ошибок «Переменная не определена»
Ошибка компиляции — переменная объявлена не в том модуле или без Экспорт
В серверной процедуре переменная содержит ожидаемое значение
Неопределено — инициализация не выполнилась или сеанс пересоздан
Значение сохраняется между вызовами в рамках сеанса
Значение теряется — где-то идёт переинициализация или обращение не к той переменной
Типичные ошибки и ограничения
Самая частая ошибка — объявление переменной в модуле приложения и попытка читать её на сервере. В управляемом приложении модуль приложения исполняется на клиенте, и серверный контекст его не видит. Вторая по частоте — пропущенное слово Экспорт: переменная компилируется, но снаружи модуля недоступна.
Ещё одна группа проблем связана с ожиданием, что переменная будет общей для всех пользователей. Серверные переменные изолированы по сеансам: если нужно «общее для всех» значение, используйте константу или регистр сведений, а не переменную. Обратная ошибка — хранение пользовательских данных в константе, из-за чего пользователи перезаписывают значения друг друга.
Отдельно стоит упомянуть фоновые задания и web-сервисы: они выполняются в собственных сеансах, поэтому переменные, установленные в интерактивном сеансе пользователя, там недоступны. Данные в фоновое задание передают через параметры метода ФоновыеЗадания.Выполнить, а не через «глобальные» переменные.
Как выбрать механизм
Частые вопросы
Можно ли объявить глобальную переменную, общую для всех пользователей?
Переменной — нет: серверные переменные изолированы по сеансам. Для общего значения используйте константу или регистр сведений, а для ускорения чтения — кеширующую функцию в общем модуле с повторным использованием возвращаемых значений.
Почему серверная процедура не видит переменную из модуля приложения?
В управляемом приложении модуль приложения компилируется и исполняется на клиенте. Серверный контекст формируют модуль сеанса и общие модули с флагом «Сервер». Перенесите переменную в модуль сеанса или в общий серверный модуль.
Чем параметр сеанса лучше переменной модуля сеанса?
Параметр сеанса типизирован в метаданных, может использоваться в ограничениях доступа к данным (RLS) и в механизме разделителей. Переменная гибче по типам, но не участвует в этих механизмах и не контролируется платформой.
Сохранится ли значение переменной после перезапуска сервера 1С?
Нет. Любые переменные модулей живут только в памяти рабочего процесса в рамках сеанса. Для хранения между перезапусками данные нужно записывать в базу — константы, регистры сведений, справочники.
Как передать значение в фоновое задание?
Через массив параметров метода ФоновыеЗадания.Выполнить — фоновое задание работает в отдельном сеансе и не видит переменных сеанса пользователя. Результат фонового задания возвращают через временное хранилище (помещение значения по адресу).
Где объявить переменную, доступную и на клиенте, и на сервере?
Одной переменной это сделать нельзя — контексты разделены. Практический подход: значение вычисляется на сервере и передаётся на клиент как реквизит формы или результат вызова серверной функции, после чего клиент работает со своей копией.
Что важно запомнить
Глобальных переменных в 1С нет — есть экспортные переменные модуля сеанса, кеш-функции общих серверных модулей, параметры сеанса и константы. Переменные живут только в рамках сеанса и изолированы между пользователями; для хранения между сеансами данные пишут в базу. Выбирайте механизм по времени жизни значения и области его видимости.