HTTP Сервисы: Путь к своему сервису. Часть 4









Продолжение статьи «HTTP Сервисы: Путь к своему сервису. Часть 3». В предыдущих частях мы уже о многом поговорили. В этой части поговорим про размер сообщений, о файлах, о порциях и немножко, о регламентах.
  • В первой части мы создали каркас для Get метода в расширении конфигурации. 
  • Во второй части мы поработали с OData и создали обработку, получающую через HTTP-Сервис используя метод Get данные сформированные при помощи СКД.
  • В третьей части мы поработали со всеми методами. Сделали пример формирующий данные при помощи СКД, работающий как через Get, так и через Post. Также поработали с длительными операциями.

В этой части поговорим о такой важной вещи как порционная передача данных. Работать будем в основном с методами GET и POST, немножко затронем OData.

HTTP-сервис будет в расширении конфигурации БСП 3.0.1.231 на платформе 8.3.12.1595.

Начнем.

Немножко про OData и порции.

Есть у OData сильный недостаток, если хотите его испытать сделайте запрос к самому большему объекту в вашей боевой базе, ну и попробуйте поработать. Вскоре пользователи прибегут к вам сами.

Для того чтобы такого не происходило нужно делать следующие вещи:

  1. Делайте выборку только по тем реквизитам, которые вам нужны. Для этого используйте $select.
  2. Перед тем как делать запрос уточните количество записей. Для этого используйте $count.
  • count — Позволяет получить в качестве результата запроса размер выборки. При успешном выполнении, тело ответа должно содержать только число элементов коллекции, отформатированное как обычное число.
  1. Если записей много забирайте их порциями через $top и $skip.
  • top — Ограничивает количество записей, возвращаемых при обращении к ресурсу.
  • skip — Позволяет исключить из результата запроса первые несколько записей. Если параметры $top и $skip указываются одновременно, то параметр $skip будет применен раньше, чем параметр $top. Приоритет применения параметров не зависит от порядка их указания в теле запроса.
  1. Я бы еще рекомендовал использовать JSON, так как меньше весит, но тут на вкус и цвет…

Предлагаю сделать небольшую обработку, которая будет забирать порциями данные из справочника КлассификаторБанков, он самый большой в БСП. Порция по умолчанию будет равна 1000 элементов.

Воспользуемся обработкой Доступный состав стандартного интерфейса OData и дадим доступ к нужному нам справочнику.

Узнаем сколько в справочнике элементов. Наш запрос будет таким: http://127.0.0.1/DemoSSL3_0_1_231/odata/standard.odata/Catalog_КлассификаторБанков/$count?$select=Ref_Key,Description,Code,DeletionMark,IsFolder&$format=json;odata=nometadata

4774 элемента. Далее набросаем обработку.

Создаем реквизиты:

  • КоличествоСтраниц – Число. Получаем путем округления в большую сторону количество элементовПорцию
  • КоличествоЭлементов – Число. Количество элементов полученных по OData.
  • ОбъектКонфигурации – Строка. Представление элемента в OData.
  • Порция – Число. Количество элементов на странице.
  • Результат – Строка.
  • ТекущаяСтраница – Число.
  • Селект — Строка. Кусок запроса с параметрами выборки. В нашем примере "$select=Ref_Key,Description,Code,DeletionMark,IsFolder&"

Создаем Команды:

  • НачальнаяЗагрузка – Загружаем количество элементов и рассчитываем количество страниц.
  • Вперед – Загружаем следующую порцию.
  • Назад – загружаем предыдущую порцию.

 

 Модуль формы

 

 Результат

Таким образом мы организовали порционное считывание данных по OData.

Ограничения по размеру файловданных. Дробление и порции.

В третьей части мы вскользь уже говорили о том, что по средствам метода POST можно передавать большие объемы данных, но ограничение в объеме все же есть и у данного метода. Настройка ограничения по умолчанию в IIS равна 30000000(байт) или 28,61(мегабайт) и находится тут:

Для Apache по ограничениям не скажу, не использую его более 5-ти лет, поэтому не знаю, что там за это время изменилось.

 

 Пример дробления файла

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

Что делать, если нам нужно получить некий объем данных, невзирая на ограничения, но с возможностью чтения данных по частям?

Естественно речь идет про некую структуру данных в формате JSON или XML (есть варианты и других форматов, но нам это сейчас неинтересно). Будем использовать порции.

Предлагаю сделать через методы POST и GET нечто подобное, что мы сделали выше по OData.

Решим данную задачку двумя методами. Вариантов решения много, но я решил показать вариант, через запрос и вариант через план обмена.

1 Вариант. Через запрос.

 

 Суть метода

Для начала давайте нарисуем сервис возвращающий количество элементов и массив последних ссылок в порциях. При этом массив с последними ссылками оставим на стороне сервера хранящего данные в справочнике PAPI_ХранилищеРезультатов, созданном в предыдущей статье (Часть 3). Сервис будет называться «ПолучитьКоличествоЭлементовВариантЗапрос», наименование объекта будем подавать параметром ItemName, количество объектов в порции будем подавать параметром top. Затем создадим метод «ПолучитьПорциюЭлементовВариантЗапроса» и будем подавать в него те же параметры, что и в предыдущем методе и номер страницы (порции) параметром page.

Правим справочник PAPI_ХранилищеРезультатов.

Добавляем реквизиты:

  • МетодЗапроса – Строка(200).
  • ПараметрыЗапроса – Строка(200).
  • ДатаЗапроса – Дата и время. Будем считать, что данные актуальны в течение дня

Правим модуль PAPI_ОбщиеПроцедурыИФункции. Добавим в него несколько функций и процедуру по получению элементов. И вынесем в него часто встречающийся код по преобразованию в формат JSON.

 

 Код модуля PAPI_ОбщиеПроцедурыИФункции

Правим модули PAPI_ОбработкаМетодовGET и PAPI_ОбработкаМетодовPOST и PAPI_ОбработкаУниверсальныхМетодов. Добавляем в него наши методы.

 

 Код модуля PAPI_ОбработкаМетодовGET

 

 Код модуля PAPI_ОбработкаМетодовPOST

 

 Код модуля PAPI_ОбработкаУниверсальныхМетодов

Правим обработку, которую делали ранее для примера с OData. 

Создаем реквизит:

  • МетодСервиса – Строка. Будет хранить список значений (Пример 1 — OData(1_1), Пример 1 — Get(1_2), Пример 1 — Post(1_3))

Добавляем декорацию (ДекорацияРазмерОтвета) для вывода "Content-Length" из заголовка ответа и меняем модуль формы.

 

 Модуль формы

 

 Результат

  • На самом деле можно еще было бы создать регламент при помощи дополнительной обработки по очистке старых результатов.
  • Или создать механизм, который собирал бы количество обращений в день в разрезе параметров запроса и метода, а далее с утра регламентом подготавливал результаты для самых "горячих запросов".
  • Так же можно было создать, например регистр сведений, который хранил порции по результатам и тогда вычисления на сервере сводились бы к минимуму по данным запросам.

Данный метод плох тем, что если в базе часто создаются элементы, тогда результат будет непредсказуемым!

2 Вариант. Через Планы обмена.

Тут все просто. Регистрируем все на узле и бьем на сообщения в зависимости от порции.

Давайте нарисуем сервис возвращающий количество элементов и регистрирующий элементы справочника на узле. Будет использован план обмена _ДемоАвтономнаяРабота из БСП. Сервис будет называться «ПолучитьКоличествоЭлементовВариантПланОбмена», наименование объекта будем подавать параметром ItemName, количество объектов в порции будем подавать параметром top. Затем создадим метод «ПолучитьПорциюЭлементовВариантПланОбмена» и будем подавать в него те же параметры, что и в предыдущем методе и номер страницы (порции) параметром page.

Правим модуль PAPI_ОбщиеПроцедурыИФункции. Добавим в него Область РаботаСПланОбмена и Вспомогательную процедуру.

 

 Код модуля PAPI_ОбщиеПроцедурыИФункции

Правим модули PAPI_ОбработкаМетодовGET и PAPI_ОбработкаМетодовPOST и PAPI_ОбработкаУниверсальныхМетодов. Добавляем в него наши методы.

 

 Код модуля PAPI_ОбработкаМетодовGET

 

 Код модуля PAPI_ОбработкаМетодовPOST

 

 Код модуля PAPI_ОбработкаУниверсальныхМетодов

Правим обработку. Реквизиту МетодСервиса добавляем 2 значения Пример 2 — Get(2_1) и Пример 2 — Post(2_2)
Меняем модуль формы.

 

 Модуль формы

 

 Результат

Посмотрим запросом, что лежит на узле:

ВЫБРАТЬ
КлассификаторБанковИзменения.Ссылка КАК Ссылка,
КлассификаторБанковИзменения.НомерСообщения КАК НомерСообщения
ИЗ
Справочник.КлассификаторБанков.Изменения КАК КлассификаторБанковИзменения
ГДЕ
КлассификаторБанковИзменения.Узел = &Узел

УПОРЯДОЧИТЬ ПО
НомерСообщения
ИТОГИ
КОЛИЧЕСТВО(РАЗЛИЧНЫЕ Ссылка)
ПО
НомерСообщения

  • В методе «ПолучитьКоличествоЭлементовВариантПланОбмена» я чищу узел и перезаполняю его, но лучше нарисовать регламент и все новые элементы распределять на новые сообщения либо прямо в методе проверять есть ли новые элементы без номеров сообщений.

Метод с узлами более правильный, чем метод запросом!

Четвертую часть заканчиваю. Мы рассмотрели с Вами методы порционной передачи данных на примере OData и методов GET и POST. Файлы мы рассмотрели вскользь, по крайней мере у меня потребность передачи файлов встречается очень редко.

Надеюсь данные примеры будут полезны в Вашей работе!

Статьи из данного цикла:

HTTP Сервисы: Путь к своему сервису. Часть 1

HTTP Сервисы: Путь к своему сервису. Часть 2

HTTP Сервисы: Путь к своему сервису. Часть 3

13 Comments

  1. apostal86

    Сейчас пока добавил в избранное. Но подсказывает интуиция, что «не за горой» момент, когда опыт, изложенный в данной публикации, может пригодиться.

    Reply ↓
  2. nicxxx

    Вместо метода ПолучитьДатуВремяИзСтроки() можно применить платформенный XMLЗначение():

    XMLDate = СтруктураЗапроса.ПараметрыЗапроса.Получить(«Date»);

    Date = XMLЗначение(Тип(«Дата»), XMLDate);

    Reply ↓
  3. dsdred

    (2)Вариантов масса. Можно и в ПрочитатьJSON указать тип

    Reply ↓
  4. user805602

    На Java работа с Web-сервисами проще. А в 1С, после ваших статей, я выберу для обмена Com.

    Обмен через блокнот, выглядит проще.

    Reply ↓
  5. dsdred

    (4)

    На Java работа с Web-сервисами проще.

    Чем проще?

    А в 1С, после ваших статей, я выберу для обмена Com.

    Обмен через блокнот, выглядит проще.

    Это только выглядит. Чем Вас так напугали http-сервисы?

    Reply ↓
  6. user805602

    (5) Статья мне понравилась.

    На первый взгляд я не увидел шаблонизаторов, помогающих делать веб-страницу. У вас данные возвращаются в текстовом виде.

    А в самом 1с много чего не хватает. Например, коллекций, приходится в основном всё пихать в таблицу значений.

    Про выгрузку в текстовый документ я упомянул потому, что результат будет такой же, только не надо разворачивать IIS/Apache

    Reply ↓
  7. dsdred

    (6)

    Про выгрузку в текстовый документ я упомянул потому, что результат будет такой же, только не надо разворачивать IIS/Apache

    С файлами тоже свои заморочки. Вообще надо смотреть по ситуации, нет решений которые как пилюля от всего.

    С кассами чаще всего через файлы работал, люблю для этого делать доп обработку с хранимыми параметрами работающую в режиме регламента или ручном используя БСП: Доп обработки и отчеты.

    Одно скажу, Com уже более 4-х лет не использую. Показываю только для того чтобы оценили их тормознутость и согласились идти другими способами. Показывал как то один тестовый пример, обходил справочник используя Com проверяя реквизит на определенное значение. Тоже самое делал по OData.

    В итоге Com молотил 30 с чем то минут, OData около 3 минут. Удивленные лица многого стоят.

    Reply ↓
  8. newbigrator

    Я вот что не понял в варианте с планом обмена — вы понаписали кучу функций и кода, ок.

    Но ведь подразумевается что при использовании OData 1C просто открывает свои объекты, доступные по этому интерфейсу. А тут получается что все равно нужно дописывать функции.

    То есть я всегда воспринимал OData как вариант, когда ничего делать не надо. А тут получается надо и только тогда взлетает.

    Чем тогда он отличается от веб сервисов то..

    Reply ↓
  9. dsdred

    (8)Odata показывал только вариант с использованием $top и $skip напрямую к справочнику без использования плана обмена. Соответственно код был только для организации порционного вывода в обработке.

    Если вы откроете Результат, то увидите там непосредственно ссылки которые формируются для получения данных.

    Запрос: http://127.0.0.1/DemoSSL3_0_1_231/odata/standard.odata/Catalog_КлассификаторБанков/$count?$select=Ref_Key,Description,Code,DeletionMark,IsFolder&$format=json;odata=nometadata

    Запрос: http://127.0.0.1/DemoSSL3_0_1_231/odata/standard.odata/Catalog_КлассификаторБанков?$top=1000&$skip=0&$select=Ref_Key,Description,Code,DeletionMark,IsFolder&$format=json;odata=nometadata

    …

    Запрос: http://127.0.0.1/DemoSSL3_0_1_231/odata/standard.odata/Catalog_КлассификаторБанков?$top=1000&$skip=4000&$select=Ref_Key,Description,Code,DeletionMark,IsFolder&$format=json;odata=nometadata

    По сути можно просто обратится по этим ссылкам и получить результат, я лишь сделал программное формирование ссылки в зависимости от порции и обработку результата.

    Вариант с планом который я показал, был через http-сервис. (Не по OData)

    Поясню:

    По Odata мы открываем объекты, можем даже план обмена открыть, но в плане есть атворегистрация и программная регистрация. Чаще всего авторегистрация не годится для нормального обмена с разными складамимагазинамиорганизациями, так как нужна некая фильтрация данных в разрезе Складаорганизациимагазина и тут в принципе без программного вмешательства не обойтись чтобы раскидывать по узлам.

    Reply ↓
  10. newbigrator

    (9) Теперь понял.

    Но хочу уточнить, все таки при OData не годится для случая когда нужно вычитать какую то Изменившуюся порцию.

    Вы согласны?

    Ваш пример про top и skip хорош и в целом позволяет читать порции, но это количественные порции.

    А прочитать изменившуются порцию через OData как я понимаю не получится, ну то есть подключить функционал плана обмена и через него соединится с таблицами изменениями.. или все таки можно?

    Reply ↓
  11. dsdred

    (10)Можно по ODate получать из Плана изменившуются порцию -> https://its.1c.ru/db/v8314doc#bookmark:dev:TI000001394

    Пробовал года 2 назад через postman с бухгалтерии получать, вот пример запроса:

    http://127.0.0.1/BuhObmenVesi/odata/standard.odata/SelectChanges?DataExchangePoint=‘http://127.0.0.1/BuhObmenVesi/odata/standard.odata/ExchangePlan_ПоОрганизации(guid’1c95d6bd-4942-11e7-8430-d897ba0899c9’)’&MessageNo=0&$format=json;odata=nometadata

    Не помню почему сделал в итоге через http-сервис… Давно было,. не вспомню.

    Reply ↓
  12. Diversus

    Добрый день. Спасибо за цикл статей. Скажите, а вы не сталкивались с вопросом авторизации в http-сервисе и выхода из режима авторизации? Скажем так: если при работе с Http-сервисом ввести логин и пароль пользователя, то для того, чтобы выйти из этого режима и снова попросить авторизацию необходимо перезапустить apache/IIS.

    Если сталкивались поделитесь решением. Сейчас это нигде не освещено.

    Reply ↓
  13. dsdred

    (12)Честно говоря не сталкивался. Можно будет поэкспериментировать.

    Reply ↓

Leave a Comment

Ваш адрес email не будет опубликован. Обязательные поля помечены *