Параметры сеанса в 1С 8.3: где задать значение, чтобы оно было доступно сразу при обращении
Содержание
Параметры сеанса в 1С инициализируют в модуле сеанса, в процедуре-обработчике УстановкаПараметровСеанса(ТребуемыеПараметры). Платформа вызывает её при старте сеанса с ТребуемыеПараметры = Неопределено, а потом — каждый раз, когда код обращается к параметру, у которого ещё нет значения. Тогда в ТребуемыеПараметры приходит массив имён, и обработчик обязан установить каждый из них.
Механизм общий для платформы 8.3 и не зависит от конфигурации. Различается только обвязка: в своей конфигурации вы пишете обработчик целиком, а в типовых на БСП регистрируете свою процедуру в общем механизме. Ниже — оба варианта, типы значений, права и приёмы отладки.
Как устроены параметры сеанса и для чего их заводят
Параметр сеанса — это значение, которое живёт ровно столько, сколько живёт сеанс пользователя. Оно хранится на сервере, у каждого сеанса своё, и другие сеансы его не видят.
Чаще всего в параметры сеанса кладут то, что нужно постоянно и что дорого вычислять каждый раз:
- 👤 ссылку на текущего пользователя из справочника
Пользователи; - 🏢 основную организацию или склад пользователя;
- 🔐 значения для ограничения доступа на уровне записей (RLS);
- ⚙️ признаки режима работы: обмен, загрузка данных, работа в сервисе.
Главная особенность — параметры сеанса доступны в текстах ограничений доступа ролей. В условии RLS к параметру обращаются через амперсанд, например &ТекущийПользователь. Поэтому без правильно проинициализированного параметра ломается не только прикладной код, но и права.
| Чем отличается | Параметр сеанса | Глобальная переменная модуля приложения | Общий модуль с повторным использованием |
|---|---|---|---|
| Где хранится | На сервере, в сеансе | На клиенте | Кеш на клиенте или сервере |
| Доступен в RLS | Да | Нет | Нет |
| Можно изменить из кода | Да, при наличии права | Да | Только сбросом кеша |
| Виден фоновому заданию | Нет, у задания свой сеанс | Нет | Нет |
Объявление параметра сеанса в конфигураторе
Прежде чем что-то инициализировать, параметр нужно описать в метаданных.
- Откройте конфигуратор и дерево конфигурации.
- Разверните ветку
Общие → Параметры сеанса. - Нажмите
Добавитьи задайтеИмя, напримерТекущийСклад. - Укажите
Тип. Для склада —СправочникСсылка.Склады. - Откройте нужные роли и выставьте для параметра права
Получениеи, если пользователь должен менять значение сам,Установка. - Обновите конфигурацию базы данных.
У параметра сеанса нет свойства «значение по умолчанию». Пока обработчик не присвоил значение, параметр считается неустановленным. Это не то же самое, что пустая ссылка или Неопределено.
Права на параметр сеанса в ролях часто забывают. Код модуля сеанса работает и без них, а вот чтение из обычного серверного кода у пользователя с урезанной ролью упадёт с нарушением прав доступа.
Какой тип выбрать
Параметр сеанса не может хранить изменяемые коллекции. Массив, структуру или соответствие перед записью превращают в фиксированный аналог:
МассивОрганизаций = ПолучитьДоступныеОрганизации();
ПараметрыСеанса.ДоступныеОрганизации = Новый ФиксированныйМассив(МассивОрганизаций);
Тип параметра в метаданных при этом задают как ФиксированныйМассив. Если нужно сохранить что-то более сложное, используют ХранилищеЗначения, но такой параметр нельзя использовать в условиях RLS.
Инициализация значений в модуле сеанса
Модуль сеанса открывают из контекстного меню корня конфигурации: команда Открыть модуль сеанса. В нём объявляют процедуру-обработчик с фиксированным именем.
Два режима вызова
| Значение ТребуемыеПараметры | Когда приходит | Что делать |
|---|---|---|
Неопределено | Один раз при старте сеанса | Установить то, что нужно всегда, или ничего |
| Массив строк с именами | При первом обращении к неустановленному параметру | Установить каждый параметр из массива |
Первый режим соблазняет заполнить всё сразу. Делать так не стоит: каждый запрос в старте сеанса замедляет вход пользователя, а половина параметров в этом сеансе может так и не понадобиться. Надёжнее «ленивая» схема: при старте ничего не делаем, параметр вычисляется в момент первого обращения.
Рабочий шаблон обработчика
Процедура УстановкаПараметровСеанса(ТребуемыеПараметры)
Если ТребуемыеПараметры = Неопределено Тогда
// Старт сеанса: параметры заполняются по требованию
Возврат;
КонецЕсли;
Для Каждого ИмяПараметра Из ТребуемыеПараметры Цикл
Если ИмяПараметра = "ТекущийПользователь" Тогда
ПараметрыСеанса.ТекущийПользователь = НайтиТекущегоПользователя();
ИначеЕсли ИмяПараметра = "ТекущийСклад" Тогда
ПараметрыСеанса.ТекущийСклад = ОпределитьСкладПользователя();
ИначеЕсли ИмяПараметра = "ДоступныеОрганизации" Тогда
ПараметрыСеанса.ДоступныеОрганизации =
Новый ФиксированныйМассив(ПолучитьДоступныеОрганизации());
КонецЕсли;
КонецЦикла;
КонецПроцедуры
Функции ОпределитьСкладПользователя и ПолучитьДоступныеОрганизации пишутся там же, в модуле сеанса, или в серверном общем модуле. Пример поиска пользователя для конфигурации, где у справочника Пользователи есть реквизит ИдентификаторПользователяИБ типа УникальныйИдентификатор:
Функция НайтиТекущегоПользователя()
ПользовательИБ = ПользователиИнформационнойБазы.ТекущийПользователь();
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ ПЕРВЫЕ 1
| Пользователи.Ссылка КАК Ссылка
|ИЗ
| Справочник.Пользователи КАК Пользователи
|ГДЕ
| Пользователи.ИдентификаторПользователяИБ = &Идентификатор";
Запрос.УстановитьПараметр("Идентификатор", ПользовательИБ.УникальныйИдентификатор);
Выборка = Запрос.Выполнить().Выбрать();
Если Выборка.Следующий() Тогда
Возврат Выборка.Ссылка;
КонецЕсли;
Возврат Справочники.Пользователи.ПустаяСсылка();
КонецФункции
Неопределено против пустой ссылки
Путаница здесь типичная. Неопределено в аргументе обработчика — это сигнал «идёт старт сеанса», а не значение параметра.
Если пользователь не найден, не оставляйте параметр без значения и не пытайтесь записать в ссылочный параметр Неопределено. Запишите пустую ссылку нужного типа. Тогда остальной код проверяет понятное условие Значение.Пустая(), а обработчик не будет вызываться снова и снова при каждом обращении.
Если обработчик получил имя в массиве, но не установил этот параметр, платформа выдаст ошибку прямо в месте обращения. Ветка ИначеЕсли для каждого объявленного параметра обязательна.
Как установить и изменить значение параметра сеанса из кода
Записать значение можно не только в модуле сеанса. Это обычное присваивание на сервере:
ПараметрыСеанса.ТекущийСклад = НовыйСклад;
Ограничения такие:
- 🖥️ Свойство
ПараметрыСеансаесть на сервере, во внешнем соединении и в толстом клиенте. В тонком и веб-клиенте его нет — читать и писать придётся через серверную процедуру, вызываемую с клиента. - 🔑 Для записи нужно право
Установка. Модуль сеанса выполняется в привилегированном режиме, поэтому там проверок нет. В остальном коде, если у роли права нет, оборачивайте присваивание в привилегированный режим. - 🧩 Значение должно соответствовать объявленному типу.
Шаблон смены склада по команде пользователя:
&НаСервереБезКонтекста
Процедура УстановитьТекущийСкладНаСервере(Склад)
УстановитьПривилегированныйРежим(Истина);
ПараметрыСеанса.ТекущийСклад = Склад;
УстановитьПривилегированныйРежим(Ложь);
КонецПроцедуры
Не открывайте право «Установка» на параметры, участвующие в RLS. Если пользователь может сам записать ТекущийПользователь, он подменит себе ограничения доступа. Такие параметры меняют только в привилегированном режиме из проверенного кода.
Как сбросить значение, если исходные данные изменились
Значение вычисляется один раз. Если администратор поменял пользователю основной склад в справочнике, у уже работающего сеанса параметр останется старым до перезахода.
Есть два способа это исправить:
- 🔄 при записи справочника, где хранится настройка, сразу перезаписать параметр в текущем сеансе (если правку делает сам пользователь);
- 🚪 для чужих сеансов — попросить пользователя перезапустить программу: менять параметры другого сеанса из кода нельзя.
Область видимости и жизненный цикл значения
Значение параметра принадлежит сеансу. Отсюда несколько следствий, которые регулярно ловят на практике.
Фоновые задания. Каждое фоновое задание — отдельный сеанс. Параметры сеанса оно не наследует от запустившего его пользователя: в задании снова вызывается УстановкаПараметровСеанса, а пользователь там может быть другим. Нужные значения передавайте в задание явно, массивом параметров метода ФоновыеЗадания.Выполнить.
Регламентные задания. Выполняются от имени пользователя, указанного в свойствах задания. Если пользователь не задан, обработчик должен корректно отработать без него — например, записать пустую ссылку.
Внешнее соединение и HTTP-сервисы. Каждое подключение начинает свой сеанс, и обработчик срабатывает так же, как при интерактивном входе. Тяжёлый код при старте сеанса здесь особенно заметен.
Запросы. В тексте ограничения доступа параметр сеанса подставляется сам. В обычном запросе надёжнее передать его явно:
Запрос.УстановитьПараметр("Склад", ПараметрыСеанса.ТекущийСклад);
Инициализация параметров сеанса в типовых конфигурациях и расширениях
В БП 3.0, ЗУП 3.1, УТ 11 и других конфигурациях на Библиотеке стандартных подсистем модуль сеанса уже занят. Он передаёт управление в БСП, а та вызывает зарегистрированные обработчики. Править модуль сеанса типовой не нужно.
Свой параметр регистрируют в процедуре ПриДобавленииОбработчиковУстановкиПараметровСеанса общего модуля ОбщегоНазначенияПереопределяемый:
Процедура ПриДобавленииОбработчиковУстановкиПараметровСеанса(Обработчики) Экспорт
Обработчики.Вставить("ТекущийСклад", "МойМодульСервер.УстановкаПараметровСеанса");
КонецПроцедуры
Сам обработчик в экспортном серверном модуле получает имя параметра и структуру уже установленных:
Процедура УстановкаПараметровСеанса(ИмяПараметра, УстановленныеПараметры) Экспорт
Если ИмяПараметра = "ТекущийСклад" Тогда
ПараметрыСеанса.ТекущийСклад = ОпределитьСкладПользователя();
УстановленныеПараметры.Добавить(ИмяПараметра);
КонецЕсли;
КонецПроцедуры
Тип второго аргумента и порядок регистрации сверяйте с документацией вашей версии БСП: сигнатура менялась между редакциями библиотеки. Посмотреть живой пример проще всего в самой конфигурации — найдите глобальным поиском по модулям строку ПриДобавленииОбработчиковУстановкиПараметровСеанса и откройте любой типовой обработчик.
Если доработка идёт через расширение
Параметр сеанса можно добавить прямо в расширение и там же проинициализировать. Для этого в модуле сеанса расширения перехватывают УстановкаПараметровСеанса с аннотацией &После:
&После("УстановкаПараметровСеанса")
Процедура Расш1_УстановкаПараметровСеанса(ТребуемыеПараметры)
Если ТребуемыеПараметры = Неопределено Тогда
Возврат;
КонецЕсли;
Если ТребуемыеПараметры.Найти("Расш1_ТекущийСклад") <> Неопределено Тогда
ПараметрыСеанса.Расш1_ТекущийСклад = Расш1_ОпределитьСклад();
КонецЕсли;
КонецПроцедуры
Префикс расширения в имени параметра защищает от конфликта с объектами типовой при обновлении.
Отладка инициализации и частые промахи разработчиков
Отлаживать модуль сеанса сложнее обычного: код срабатывает до того, как вы успеваете подключиться отладчиком к уже запущенному клиенту.
Как поймать обработчик в отладчике
- Поставьте точку останова в
УстановкаПараметровСеанса. - Запустите клиент из конфигуратора командой
Отладка → Начать отладку. Так отладчик подключён с первой секунды сеанса. - Для серверной базы убедитесь, что отладка на сервере разрешена, иначе серверные точки останова не сработают.
- Если процедура вызывается лениво, точка сработает в момент первого обращения к параметру, а не при входе.
Вычисление выражения ПараметрыСеанса.ТекущийСклад в табло отладчика само по себе запускает обработчик, если параметр ещё не установлен. Отладчик меняет поведение программы — помните об этом, когда разбираете «плавающую» ошибку.
Промахи, которые встречаются чаще прочих
- 🔁 Взаимная зависимость. Параметр А вычисляется через параметр Б, а Б — через А. Обработчик вызывает сам себя, пока не упадёт стек. Разорвите цепочку: пусть один из них считается без обращения к другому.
- 🐢 Запросы в цикле при старте. Пять параметров по запросу на каждый — пять обращений к базе на входе. Ленивая схема убирает их из старта.
- 🧱 Изменяемая коллекция. Попытка записать
Массивв параметр типаФиксированныйМассивзаканчивается ошибкой. Оборачивайте вНовый ФиксированныйМассив(...). - 🙈 Параметр для RLS без значения. Если обработчик не заполнил параметр, который используется в ограничении доступа, пользователь получает ошибку при открытии любого списка с этим ограничением.
- 🗂️ Кеш вместо параметра. Для настроек, которые меняются чаще, чем раз за сеанс, параметр сеанса не подходит. Лучше читать значение по месту или использовать модуль с повторным использованием на время вызова.
Частые вопросы
Можно ли задать параметру сеанса значение по умолчанию в конфигураторе?
УстановкаПараметровСеанса.Сохраняется ли значение параметра сеанса после выхода из программы?
Как прочитать параметр сеанса из модуля управляемой формы?
ПараметрыСеанса нет.