Потребление API REST с (облачным) ABAP
Поместите метод вызов
При работе с APIS REST использует API REST для связи между приложениями. В этой статье мы рассмотрим, как потреблять API REST, используя ABAP, в частности, с функциональностью Cloud ABAP. Вот ключевые моменты, которые вам нужно знать:
- API означает интерфейс прикладного программирования и позволяет двум приложениям общаться друг с другом.
- API REST – это схема построения API с использованием протокола HTTP и отправки/получения данных JSON или XML через URIS.
- Odata, популярная в мире SAP, является типом API REST.
- В ABAP доступна ограниченная информация о потреблении внешних API, особенно API -интерфейсов для Cloud ABA.
- В этом уроке мы будем использовать API API -администратора JSON для демонстрации.
- Поставщик API предлагает ресурсы, такие как сообщения, комментарии, альбомы, фотографии, Todos и пользователи.
- Мы сосредоточимся на ресурсе постов для простоты.
- Пост имеет идентификатор, заголовок, тело и идентификатор пользователя.
- Чтобы употреблять API REST в ABAP, мы будем использовать API с белым списком, называемым IF_WEB_HTTP_CLIENT.
- Мы также будем использовать библиотеку XCO для работы с JSON.
Вопросы:
- Что означает API?
API означает интерфейс программирования приложений. - Что такое API REST?
API REST – это схема построения API с использованием протокола HTTP и отправки/получения данных JSON или XML через URIS. - Что такое Одата?
Odata – это тип REST API, который популярен в мире SAP. - Есть ли много информации о потреблении внешних API в ABAP?
Нет, доступна ограниченная информация, особенно для API -интерфейсов белых списков для облака ABAP. - Какой провайдер API мы будем использовать в этом уроке?
Мы будем использовать API json Placeholder для демонстрационных целей. - Какие ресурсы предлагают API API JSON?
API JSON Placeholder предлагает такие ресурсы, как сообщения, комментарии, альбомы, фотографии, Todos и пользователи. - На каком ресурсе мы сосредоточимся в этом уроке?
Мы сосредоточимся на ресурсе постов для простоты. - Какие атрибуты имеют сообщение?
Пост имеет идентификатор, заголовок, тело и идентификатор пользователя. - Какой белый ABAP API мы будем использовать для употребления API Rest API?
Мы будем использовать API if_web_http_client. - Какую библиотеку мы будем использовать для работы с JSON?
Мы будем использовать библиотеку XCO.
Подробные ответы:
- Что означает API?
API означает интерфейс программирования приложений. Это набор стандартов, который позволяет двум приложениям общаться друг с другом. - Что такое API REST?
REST API – это схема построения API с использованием протокола HTTP. Они позволяют приложениям отправлять и получать данные JSON или XML через URIS. API REST на основе JSON широко используются. - Что такое Одата?
Odata – это тип REST API, который очень популярен в мире SAP. Это позволяет получить легкий доступ и манипулирование данными, хранящимися в системах SAP. - Есть ли много информации о потреблении внешних API в ABAP?
Нет, имеется ограниченная информация о потреблении внешних API в ABAP, особенно для API белых списков, которые можно использовать с облачным ABAP. Этот учебник направлен на предоставление руководства по потреблению API REST с использованием облачного ABAP. - Какой провайдер API мы будем использовать в этом уроке?
Мы будем использовать API json Placeholder, который представляет собой фальшивый API онлайн-отдыха для тестирования и прототипирования. Это позволяет нам выполнять действия CRUD (создавать, читать, обновить, удалить). - Какие ресурсы предлагают API API JSON?
API JSON Placeholder предлагает такие ресурсы, как сообщения, комментарии, альбомы, фотографии, Todos и пользователи. В этом уроке мы сосредоточимся на ресурсе постов. - На каком ресурсе мы сосредоточимся в этом уроке?
Мы сосредоточимся на ресурсе сообщений от API JSON Placeholder API. Это позволит нам продемонстрировать, как выполнять действия CRUD на API REST, используя API -интерфейсы ABAP с белым списком в облачной платформе SAP. - Какие атрибуты имеют сообщение?
Пост имеет идентификатор, заголовок, тело и идентификатор пользователя. Идентификатор представляет уникальный идентификатор поста, а идентификатор пользователя представляет идентификатор пользователя, который создал сообщение. - Какой белый ABAP API мы будем использовать для употребления API Rest API?
Чтобы употреблять API REST в ABAP, мы будем использовать API if_web_http_client. Это белый список ABAP API, который разрешается использовать на облачной платформе SAP. - Какую библиотеку мы будем использовать для работы с JSON?
Для работы с JSON мы будем использовать издание Cloud Platform Library XCO (Extension Components). Эта библиотека обеспечивает полезную функциональность для преобразования данных JSON между различными соглашениями о именовании, такими как Camelcase to ande_score, и наоборот.
Следуя этому учебному пособию, вы сможете потреблять API REST, используя ABAP, в частности, с функциональностью Cloud ABAP.
Потребление API REST с (облачным) ABAP
Вызовать метода публикации ->
Использует ли SAP API REST?
Охто
Мы аррегировали подоаджолгн. SpoMOщHщ эtOй straoniцы mы smosememememopredetath, чto -aprosы otpra. То, что нужно?
Эta -steraniцa otobrana -overshy -aTeх -stuчah -obra -aTeх -stu -y -y -ogdaTomAtiчeskymi -stri -stri -rah -strhe -strhe -strhe -stri -stri -stri -stri -stri -stri -rah -rah -stristriouri Котора. Straoniцa -oprepaneTeTeTeTeTOTOTOTO -opobrasthep -apoSle -o, kak -эat. ДО СОМОМОНТА.
Иошнико -а -а -а -в -впологовый схлк -а -апросов. Esli-yspolheoute obhщiй dostup-vanterneTTHETHETHETHETHET,. Охраторс. Подеб.
Проверка, в котором я, eSli -voAchephephephephe -yvodyte -sloжne -apro Эмами, Или,.
Потребление API REST с (облачным) ABAP
API означает интерфейс прикладного программирования и содержит набор стандартов, которые позволяют двум приложениям общаться друг с другом. REST API – это определенная схема строительства API. Они основаны на протоколе HTTP, отправляя и получая данные JSON или XML через URI (унифицированный идентификатор ресурсов). API-интерфейсы REST на основе JSON распространены. Мы также будем использовать такой в этом уроке.
Odata, которая очень популярна в мире SAP, сама по себе является REST API. Есть много информации о том, как предоставить API отдыха от ABAP (я.эн., Чтобы опубликовать услугу Odata). Но есть не’много о том, как потреблять внешний API в ABAP. И из того, что есть, он включает в себя небезолищные ABAP API, я.эн., Они не могут быть использованы с облаком ABAP. Итак, я решил написать этот урок об употреблении API REST с использованием Cloud ABAP.
Сценарий
Поставщик API
Мы будем работать с JSON Placeholder – “бесплатно использовать фальшивый онлайн -API REST для тестирования и прототипирования”. Это позволит нам выполнить все действия CRUD (создать, читать, обновить, удалить). Чтобы быть справедливым, создание, обновление и удаление на самом деле не сработает, но сервер подделает его, как если бы они это сделали. Что достаточно для нашего варианта использования!
Ресурсы
Наш поставщик API выставляет посты, Комментарии, альбомы, фотографии, тодос, и пользователи. Для простоты’Sake, мы будем использовать только посты ресурс и притворяться остальным’T там. Основная идея моего учебника – предоставить чрезвычайно простое руководство о том, как выполнить действия CRUD на API REST. И сделать это с помощью API ABAP с белым списком в платформе SAP Cloud (CP). Это означает, что вы можете запустить этот код на пробной учетной записи SAP CP.
Посты ресурс
Пост имеет идентификатор, заголовок, тело и идентификатор пользователя, что означает идентификатор пользователя, который создал сообщение. Мы представляем это в ABAP следующим образом:
Типы: начало post_s, user_id type i, id type i, строка типа заголовка, строка типа корпуса, конец post_s, таблица типа post_tt post_s с пустой ключом, начало post_without_id_s, пользователь_ тип i, тип заголовка, строка типа корпуса, конец post_without_id_s.
Нам нужна структура без идентификатора, потому что идентификатор сообщения автоматически назначается API REST. Это означает, что мы не предоставляем его при создании нового поста.
Используются API ABAP облачных ABAP
Отправка HTTP -запросов
Как я упоминал ранее, небольшое количество существующих учебных пособий для употребления API REST в ABAP в первую очередь используют APIS не побеждаемого ABAP. Например, if_http_client Один, чье использование не разрешено в облаке ABAP. Способ проверить ABIS с белым списком ABAP для облачной платформы SAP – это просмотреть Выпущенные объекты списки. Он доступен в инструментах разработки Eclipse ABAP (ADT) -> Project Explorer -> Выпущенные объекты. Итак, готовый к облаку API ABAP для отправки HTTP-запроса-это if_web_http_client. Мы определяем следующий метод, чтобы получить клиента:
Методы: CREATE_CLIENT ИМПОМПАНИТЬСЯ ИМФОРМИРОВАНИЕ Тип типа Строка возвращающего значения (Результат) Тип ref to if_web_http_client Повышение CX_STATIC_CHECK
Метод create_client. Data (dest) = cl_http_destination_provider => create_by_url (url). result = cl_web_http_client_manager => create_by_http_destination (dest). Endmethod.
Обратите внимание, что URL -адрес является входным параметром. Возвращенным результатом является созданный клиент Web HTTP.
Работа с JSON
Чтобы работать с JSON, мы будем использовать издание XCO Cloud PlatformУдлинительные компоненты) библиотека. Узнайте больше об этом здесь и здесь. Конкретный класс, относящийся к нашему варианту использования xco_cp_json. Что -то чрезвычайно ценное, которое он обеспечивает, – это способность преобразовать различные соглашения об именах. Например, Camelcase to Under_score, а наоборот.
Потребление API отдыха
Прежде чем добраться до забавной части, нам просто нужно определить несколько констант. Конечно, это не необходимо строго, но работа с констант, а не струнные литералы, является лучшей практикой и позволяет использовать повторное использование.
Константы: BASE_URL TYPE Значение https: // jsonplaceholder.Типичный.com/posts ', content_type type string value' content-type ', json_content type string value' application/json; charset = utf-8 '.
Базовый URL – это просто адрес посты ресурс. Последние две константы, которые нам нужны для тех случаев, когда мы будем отправлять данные (я.эн., Создать и обновить) на сервер, используя API REST. Мы должны сообщить серверу, что мы отправляем JSON.
Прочитайте все сообщения
URL для чтения всех сообщений – это просто базовый URL. Итак, мы создаем для него клиента, используем клиента для выполнения запроса GET, закрыть клиента и конвертировать полученный JSON в таблицу сообщений. Таблица типа постов определена в Сообщения ресурса Раздел выше. Вы также можете обратиться к полному коду в конце.
read_posts возвращающе
Метод read_posts. "Получите JSON всех сообщений DATA (URL) = |< base_url >|. Data (client) = create_client (url). Data (response) = client-> execute (if_web_http_client => get)-> get_text (). Клиент-> close (). «Преобразовать JSON в публикацию таблицы XCO_CP_JSON => data-> from_string (response)-> Apply (value #((xco_cp_json => Transformation-> camel_case_to_underscore)))-> write_to (ref #(result))). Endmethod.
Прочтите отдельный пост
Метод для чтения одного поста похож, с различиями, которые мы принимаем в качестве ввода идентификатор поста, и возвращаем структуру (i.эн., один пост,) вместо таблицы (я.эн., Список сообщений). Остальные API’S URL чтения одного поста заключается в следующем:
read_single_post Импорт идентификатор типа I Тип I возвращающего значения (результат) Тип post_s Повышение CX_STATIC_CHECK
Метод read_single_post. «Получить JSON для данных идентификатора ввода (URL) = |< base_url >/< id >|. Data (client) = create_client (url). Data (response) = client-> execute (if_web_http_client => get)-> get_text (). Клиент-> close (). «Преобразовать json в публикацию структуры xco_cp_json => data-> from_string (response)-> Apply (value #((xco_cp_json => Transformation-> camel_case_to_underscore)))-> write_to (ref #(result))). Endmethod.
Создать пост
Как объяснялось ранее, сообщения’ Идентификаторы автоматически назначаются API REST. Итак, чтобы создать пост, мы будем использовать post_without_id_s тип. Это будет наш входной параметр. Мы собираемся преобразовать из этой структуры ABAP в JSON, снова используя библиотеку XCO. Оттуда мы создаем клиента. Затем мы установили тело HTTP-запроса, который мы отправим в то, что мы только что создали, и мы сообщим серверу, что мы будем отправлять тип контента JSON. Наконец, мы выполняем запрос POST и возвращаем сервер’S Ответ. Если все прошло хорошо, сервер’S -ответ вернет нам наш пост вместе с его недавно сгенерированным идентификатором (101, потому что в настоящее время есть 100 сообщений).
CREATE_POST IMPORTING POST_WITHOUT_ID TYPE POST_WITHOUT_ID_S возвращающе
Метод create_post. "Преобразовать входное сообщение в JSON DATA (JSON_POST) = XCO_CP_JSON => DATA-> FROD_ABAP (POST_WITHOUT_ID)-> APPLIC. «Отправьте JSON POST на сервер и верните данные ответа (URL) = |< base_url >|. Data (client) = create_client (url). Data (req) = client-> get_http_request (). req-> set_text (json_post). req-> set_header_field (i_name = content_type i_value = json_content). result = client-> execute (if_web_http_client => post)-> get_text (). Клиент-> close (). Endmethod.
Обновление сообщения
Мы будем обновлять с помощью запроса PUT. Это означает, что мы предоставим полный пост. Патч, с другой стороны, позволяет нам предоставлять только обновленное поле (e.г., только заголовок). Если вы найдете это интересным, вы можете попытаться сделать патч попросить самостоятельно – это не должно’это слишком тяжело с предоставленными здесь ресурсами!
Мы следим за аналогичной логикой, как и с создавать действие. Мы также предоставляем сообщение в качестве входного параметра, но на этот раз мы используем полную структуру (с идентификатором после). URL -адрес для обновления сообщения – это то же самое, что доступ к этому (одинокому) сообщению:
Итак, единственные отличия от создавать Включите измененный тип параметра ввода Post, URL и метода HTTP -запроса (PUT).
Update_post Импорт Post type post_s возвращающе
Метод Update_post. "Преобразовать входное сообщение в JSON DATA (JSON_POST) = XCO_CP_JSON => DATA-> FROD_ABAP (post)-> Apply (значение #((XCO_CP_JSON => Transformation-> Underscore_TO_CAMEL_CASE)))-> to_String (). «Отправьте JSON POST на сервер и верните данные ответа (URL) = |< base_url >/< post-id >|. Data (client) = create_client (url). Data (req) = client-> get_http_request (). req-> set_text (json_post). req-> set_header_field (i_name = content_type i_value = json_content). result = client-> execute (if_web_http_client => put)-> get_text (). Клиент-> close (). Endmethod.
Удалить пост
Удаление поста – самый простой запрос. Мы просто принимаем удостоверение личности и отправляем запрос DELETE HTTP на URL -адрес конкретного поста. Чтобы позволить пользователю, если что -то пойдет не так, мы проверяем сервер’S код ответа (должен быть 200 – означает ОК).
DELETE_POST IMPORTING ID ID Тип I Повышение CX_STATIC_CHECK
Метод delete_post. Данные (URL) = |< base_url >/< id >|. Data (client) = create_client (url). Data (response) = client-> execute (if_web_http_client => delete). Если ответ-> get_status () -code ne 200. Поднимите тип исключения CX_WEB_HTTP_CLIENT_ERROR. Эндиф. Endmethod.
Тестирование нашего кода
Теперь, когда мы предоставили все функции CRUD, пусть’S проверьте их! Для этого мы будем реализовать if_oo_adt_classrun интерфейс, который позволяет запускать класс в качестве приложения консоли. У него есть основной метод, который будет выполняться – аналогично Java.
Метод if_oo_adt_classrun ~ main. ПЫТАТЬСЯ. «Читать данные (all_posts) = read_posts (). Data (first_post) = read_single_post (1). "Create Data (create_Response) = create_post (значение #(user_id = 7 title = 'Привет, мир!'Body =' :) ')). "Обновление first_post-user_id = 777. Data (update_response) = update_post (first_post). "DELETE DELETE_POST (9). "Печать результатов out-> write (all_posts). out-> write (first_post). out-> write (create_response). out-> write (update_response). Поймать CX_ROOT в данные (EXC). out-> write (exck-> get_text ()). Эндтри. Endmethod.
Запуск с отпечатками F9 Следующий вывод:
Начало вывода в консоли ABAP
Конец вывода в консоли ABAP
Заключение
Это заканчивает учебник о том, как употреблять API REST в облаке ABAP. Я надеюсь, что это было полезно для вас. Если ты себя там чувствуешь’S любые моменты улучшений, или у вас есть какие -либо вопросы или отзывы для меня, дайте мне знать в комментариях!
Полный код
Class ZSS_TESTER_2 Определение Public Final Create Public. Публичный раздел. Интерфейсы: if_oo_adt_classrun. Типы: начало post_s, user_id type i, id type i, строка типа заголовка, строка типа корпуса, конец post_s, таблица типа post_tt post_s с пустой ключом, начало post_without_id_s, пользователь_ тип i, тип заголовка, строка типа корпуса, конец post_without_id_s. Методы: CREATE_CLIENT ИМПИМИМАРИВАНИЕ ОБРАЗОВАНИЯ ЗНАКИ ВОЗВРАЩЕНИЯ ЗНАКИ (Результат) Тип ref to if_web_http_client Повышение CX_STATIC_CHECK, read_posts возвращающе _ID_S возвращающее значение (результат) Тип строки Повышение CX_STATIC_CHECK, UPDATE_POST ИМПИМИМПУРТИВАНИЕ POST TIPE POST_S возвращающе. Частный раздел. Константы: BASE_URL TYPE Значение https: // jsonplaceholder.Типичный.com/posts ', content_type type string value' content-type ', json_content type string value' application/json; charset = utf-8 '. Endclass. Класс ZSS_TESTER_2 реализация. Метод if_oo_adt_classrun ~ main. ПЫТАТЬСЯ. «Читать данные (all_posts) = read_posts (). Data (first_post) = read_single_post (1). "Create Data (create_Response) = create_post (значение #(user_id = 7 title = 'Привет, мир!'Body =' :) ')). "Обновление first_post-user_id = 777. Data (update_response) = update_post (first_post). "DELETE DELETE_POST (9). "Печать результатов out-> write (all_posts). out-> write (first_post). out-> write (create_response). out-> write (update_response). Поймать CX_ROOT в данные (EXC). out-> write (exck-> get_text ()). Эндтри. Endmethod. Метод create_client. Data (dest) = cl_http_destination_provider => create_by_url (url). result = cl_web_http_client_manager => create_by_http_destination (dest). Endmethod. Метод read_posts. "Получите JSON всех сообщений DATA (URL) = |< base_url >|. Data (client) = create_client (url). Data (response) = client-> execute (if_web_http_client => get)-> get_text (). Клиент-> close (). «Преобразовать JSON в публикацию таблицы XCO_CP_JSON => data-> from_string (response)-> Apply (value #((xco_cp_json => Transformation-> camel_case_to_underscore)))-> write_to (ref #(result))). Endmethod. Метод read_single_post. «Получить JSON для данных идентификатора ввода (URL) = |< base_url >/< id >|. Data (client) = create_client (url). Data (response) = client-> execute (if_web_http_client => get)-> get_text (). Клиент-> close (). «Преобразовать json в публикацию структуры xco_cp_json => data-> from_string (response)-> Apply (value #((xco_cp_json => Transformation-> camel_case_to_underscore)))-> write_to (ref #(result))). Endmethod. Метод create_post. "Преобразовать входное сообщение в JSON DATA (JSON_POST) = XCO_CP_JSON => DATA-> FROD_ABAP (POST_WITHOUT_ID)-> APPLIC. «Отправьте JSON POST на сервер и верните данные ответа (URL) = |< base_url >|. Data (client) = create_client (url). Data (req) = client-> get_http_request (). req-> set_text (json_post). req-> set_header_field (i_name = content_type i_value = json_content). result = client-> execute (if_web_http_client => post)-> get_text (). Клиент-> close (). Endmethod. Метод Update_post. "Преобразовать входное сообщение в JSON DATA (JSON_POST) = XCO_CP_JSON => DATA-> FROD_ABAP (post)-> Apply (значение #((XCO_CP_JSON => Transformation-> Underscore_TO_CAMEL_CASE)))-> to_String (). «Отправьте JSON POST на сервер и верните данные ответа (URL) = |< base_url >/< post-id >|. Data (client) = create_client (url). Data (req) = client-> get_http_request (). req-> set_text (json_post). req-> set_header_field (i_name = content_type i_value = json_content). result = client-> execute (if_web_http_client => put)-> get_text (). Клиент-> close (). Endmethod. Метод delete_post. Данные (URL) = |< base_url >/< id >|. Data (client) = create_client (url). Data (response) = client-> execute (if_web_http_client => delete). Если ответ-> get_status () -code ne 200. Поднимите тип исключения CX_WEB_HTTP_CLIENT_ERROR. Эндиф. Endmethod. Endclass.
Создание API REST (вызов метода GET & POST)
API REST API является репрезентативным интерфейсом прикладного программирования приложений.
Наиболее распространенными методами являются: Get, Post, Pul и Delete,
Эти методы будут использоваться, запрос GET для получения записи, запрос на создание его, запрос на установку для обновления записи и запрос удаления для удаления
Сценарий -> Необходимо предоставить детали драйвера на основе идентификатора драйвера.
Шаг 1 ->
Базовая таблица данных драйвера.
Шаг 2 ->
Создать класс обработчика запросов ‘Zcl_driver_req_handler’ и наследовать стандартным классом ‘Cl_resthttp_handler’
Примечание -> обязательно реализовать метод GET_ROOT_HANDLER, в противном случае он даст ошибку синтаксиса.
Шаг 3 ->
Создать класс поставщика запросов ‘Zcl_driver_req_provider’ и наследовать стандартным классом ‘Cl_rest_resource’
Шаг 4 -> Теперь реализуйте if_rest_resource ~ Получить метод чтения данных.
После прочтения метода Data Call /UI2 /CL_JSON => serialize () для преобразования структуры ABAP в формат JSON.
Шаг 5 -> Реализация метода GET_ROOT_HANDLER класса обработчика запросов.
Здесь нам нужно связать класс обработчиков и поставщиков запросов с помощью маршрутизатора с помощью маршрутизатора.
Шаг 6 -> Создать сервисный элемент, tcode sicf
Шаг 7 -> Список обработчиков ссылок, здесь нам нужно определить наш класс обработчиков запросов ‘Zcl_driver_req_handler’.
Шаг 8 -> Активировать обслуживание.
Шаг 9 -> Тестовая служба.
Результат -> Здесь мы передаем драйвер и на основе данных идентификатора отображаются в формате JSON.
Вызовать метода публикации ->
Сценарий -> Нам нужно создать новые детали драйвера в базе данных. Как вы можете увидеть идентификатор драйвера ‘002’ существует только в системе, а теперь новый удостоверение личности ‘001’ должен быть создан.
В переменной lv_data данные поступают в строке json
CALL /UI2 /CL_JSON => Deserialize () Метод для преобразования строки JSON в структуру ABAP.
Вот новая запись с удостоверением личности ‘001’
Заключение ->
После прочтения этого блога вы сможете создать простой API REST, и у вас также будет представление о чтении параметров в классе поставщика запросов.
Пожалуйста, не стесняйтесь предположить, необходимо ли какое -либо исправление 🙂
Разработка API REST в ABAP
В двух недавних блогах я продемонстрировал, как написать веб -клиенты API REST – с XML (демонстрационное приложение здесь) или JSON (демонстрационное приложение здесь) в качестве формата передачи данных. В этом блоге я сосредоточусь на стороне сервера: как реализовать API REST в качестве обработчика запроса ABAP. Вы можете осмотреть весь код, который я обсуждаю здесь, на веб -сайте Migros BSP: IT’S все в классе zcl_job_data .
Дерево ICF
Обработчики запросов – это классы, реализующие интерфейс if_http_extension, который состоит из одного отдельного метода handle_request. Класс обработчика запроса может быть прикреплен к пути в транзакции SICF. Входящий HTTP -запрос будет проанализирован в рамках интернет -связи, пытаясь сопоставить путь запроса против пути SICF. Процесс соответствия останавливается, как только найденный узел с прикрепленным обработчиком запроса. Если это так, будет создан экземпляр класса обработчика, и будет вызван метод handle_request.
Наш пример сервиса прикреплен к пути /работа/атрибуты. Класс ZCL_JOB_DATA объявляется, что несет ответственность за все входящие запросы, в которых начался путь запроса /работа/атрибуты :
Первая стратегия: метод HTTP -запроса
Реализация метода интерфейса if_http_extension ~ harder_request () формирует самый верхний уровень обработки. Таким образом, реализация дает только грубый скелет обработки: экземпляр для операций базы данных, а также экземпляр для обработки операции остального. Такая ситуация должна привести к ответу HTTP с кодом состояния ‘ошибка 400, неверный запрос’.
В этом месте мы используем шаблон дизайна стратегии: в зависимости от метода HTTP (get, prop, post, delete, options), создается конкретный экземпляр. Каждый возможный экземпляр соответствует конкретной стратегии.
Метод if_http_extension ~ harder_request . Данные: lo_db type ref to lif_db, lo_rest type ref to lif_rest, lo_invalid_method type ref to zcx_error, lv_reess type string строка. пытаться. * Объект для операций базы данных LO_DB ?= get_db (io_server = server). * Получите правильный экземпляр обработчика Rest, в зависимости от глагола (get, pot, post, options, delete) lo_rest ?= get_rest (io_server = server io_db = lo_db). * Сделайте операцию lo_rest-> harder_request (). поймать zcx_not_found в lo_invalid_method. lv_reason = lo_invalid_method-> get_text (). Server-> response-> set_status (code = 400 "Bad Request Consection = lv_reason). Эндтри. Endmethod.
Мы используем соглашение об именах для определения экземпляра: класс LCL_REST_GET будет связан с HTTP -глаголом GET, LCL_REST_PUT с путом и т. Д. Все эти классы реализуют интерфейс LIF_REST. Таким образом, мы можем использовать создание динамического экземпляра. В качестве альтернативы, мы могли бы написать большой случай … заявление со многими, когда’с. Преимущество случая заключается в том, что Создать объект Заявление может быть статически проверено на синтаксическую правильность. Я выбрал динамический вариант, так как считаю его более ясным и читаемым, чем куча, когда ветви.
Обратите внимание, что метод HTTP -запроса (Get, POT, POST,…) доступен в качестве поле Pseudo Header с именем ‘~ request_method’:
Метод get_rest. Данные: LV_CLASSNAME TYPE SEOCLSNAME, LV_METHOD TYPE Строка, LV_MESSAGE TYPE TEXT255. lv_method = io_server-> request-> get_header_field ('~ request_method'). concatenate 'lcl_rest_' lv_method в lv_classname. пытаться. Создать объект eo_rest type (lv_classname) Экспорт io_request = io_server-> запрос io_response = io_server-> response io_db = io_db. Поймать cx_sy_create_object_error. lv_message = 'method' '&' 'не поддерживается' (001). заменить '&' в lv_message с lv_method. _RAISE_WITH_TEXT ZCX_NOT_FOUND LV_MESSAGE. Эндтри. Endmethod.
Вторая стратегия: формат передачи данных
Теперь у нас есть разные классы обработчиков для различных методов HTTP -запроса. Но для всех этих обработчиков есть некоторые общие задачи. Одна из этих общих задач заключается в том, чтобы определить текущий формат передачи данных и преобразовать вход – если доступно – в данные ABAP, и наоборот: для преобразования данных результатов ABAP в вывод с нуждемным форматом передачи данных (XML или JSON).
Теперь некоторые методы запроса, такие как Get, не требуют никакого контента запроса. Таким образом, преобразование входящих данных выполняется теми обработчиками метода, которые знают, что требуют данных контента. С другой стороны, всегда будет результат следующего типа данных:
Типы: начало TY_RESULT, MSGTYPE TYPE SYMSGTY, Тип сообщения C Длина 255, Тип заданий ZJOBS_TAB, конец TY_RESULT.
Не всегда могут быть записи в столе работы. Но не каждый компонент этой структуры будет начальным. Если таблица работы нет, то обычно будет сообщение. Таким образом, преобразование результата всегда можно выполнить.
Имеет смысл работать с классом абстрактного конвертера, конкретные подклассы, содержащие алгоритмы конверсии на тип контента. Это второе применение схемы стратегии.
Класс LCL_CONVERTER определение. Публичный раздел. класс-методы get_instance Импорт IV_Accept Тип строки возвращающего значения (EO_INSTANCE) Тип рефери в lcl_converter. Методы content_type абстрактное возвращающее значение (ev_content_type) тип строки. Методы get_entered_data Аннотация Импорт IV_CDATA Тип строки Экспорт ES_JOB TYPE ZJOBS Повышение ZCX_PARSE_ERROR. Методы result_to_cdata Аннотация Импорт IS_RESULT TYPE TY_RESULT Экспорт ev_cdata Тип строки. Endclass. "Определение lcl_converter
Статический метод lcl_converter => get_instance () делает различие в зависимости от Принимать Поле заголовка HTTP -запроса:
Класс LCL_Converter Реализация. Метод get_instance. Если iv_accept cs 'application/json'. Создать объект eo_instance type lcl_json_converter. еще. Создать объект eo_instance type lcl_xml_converter. эндиф. Endmethod. "GET_INSTANCE ENDCLASS. "Реализация LCL_Converter
Общий сюжет для всех запросов
Мы можем извлечь общие задачи в суперкласс LCL_REST всех конкретных обработчиков методов, реализуя интерфейс life_rest ~ harder_request () один раз для всех подклассов.
Общий код в SuperClasse должен быть смешан с конкретным кодом, реализованным в подклассе и определение конкретного поведения этого подкласса. Чтобы достичь этого, мы называем в желаемой точке времени в life_rest ~ harder_request (), абстрактный метод делать( ), который должен быть переопределен в подклассах. Этот метод do () будет содержать конкретное действие.
Теперь общая реализация life_rest ~ harder () в суперклассе только определяет поток обработки, оставляя конкретные действия в подклассы или делегировать подобные go_converter:
- Выполнить конкретное действие, вызывая делать(),
- Обработка ошибок, с кодом ошибки HTTP 400 “Плохой запрос” В случае ошибки преобразования (неправильные входящие данные) или настройка данных ответа для сообщения об ошибке в случае ошибки приложения,
- Структура результата отображается со структурой данных ответа (XML или JSON), используя соответствующий экземпляр преобразователя,
- Наконец, данные ответа помещаются в корпус ответа HTTP, а также установлен соответствующий тип ответа: Application/json, или Text/xml.
Это общий набросок – обработка ответов, которая действительна для все HTTP -методы запроса и для все Типы контента (XML, а также JSON). Детали содержатся в называемых методах.
Метод lif_rest ~ harder_request. Данные: тип LO_EX REF TO CX_ROOT, LV_CDATA Тип строки, LS_RESULT TYPE TY_RESULT. пытаться. * Выполнить конкретную операцию do (импорт es_result = ls_result). поймать zcx_parse_error в lo_ex. go_response-> set_status (code = 400 "плохой запрос причин = lo_ex-> get_text ()). set_response_parameters (). возвращаться. поймать zcx_error в lo_ex. ls_result-message = lo_ex-> get_text (). ls_result-msgtype = 'e'. Эндтри. * Преобразовать структуру результата в JSON или XML, соответственно, метод вызова GO_Converter-> result_to_cdata Экспорт is_result = ls_result importing ev_cdata = lv_cdata. * Поместите результат в метод вызова тела ответа SET_RESPONSE EXPORTING IV_CONTENT_TYPE = GO_CONVERTER-> content_type () iv_cdata = lv_cdata. Endmethod. "handle_request
Конкретная задача – запрос на пут
Позволять’S Посмотрите на конкретную задачу для иллюстрации: запрос POT – который всегда является задачей обновления или вставки атрибутов задания для данного идентификатора в базе данных. Следующим образом, существует собственный локальный класс LCL_REST_PUT RADENLING. На самом деле, для этого обработчика запроса был только делать Сам метод для реализации (который является абсолютным минимумом для конкретного класса задач для реализации: делать() Аннотация в родительском классе. Без реализации нельзя построить никаких случаев.):
Класс LCL_REST_PUT Определение наследства от LCL_REST. Защищенный раздел. Методы делают переопределение. Endclass. "LCL_REST_PUT DEFINITION
Реализация заключается в следующем:
- Задание с указанным идентификатором считывается из базы данных (если Был указан идентификатор – для новых заданий это не так),
- Введенные данные будут проанализированы в структуру LS_JOB, используя соответствующую go_converter пример,
- И наконец, сохранять() Метод называется. Он реализован в SuperClass, поскольку другие методы запроса также используют его.
Класс LCL_REST_PUT реализация. Метод. Данные: ls_job type zjobs, lv_id type zjobs-id. пытаться. get_job_by_id (импорт es_job = ls_job). lv_id = ls_job-id. поймать zcx_not_found. Эндтри. Очистить ls_job. Метод вызова go_converter-> get_entered_data Экспорт iv_cdata = go_request-> get_cdata () импорт es_job = ls_job. Если ls_job не является начальным. Если LV_ID не является начальным. ls_job-id = lv_id. эндиф. Сохранить (изменение cs_job = ls_job). ES_RESULT-MESSAGE = 'JOW & была сохранена' (002). Заменить '&' in es_result-message с LS_JOB-ID. es_result-msgtype = 's'. "Сообщение об успехе вставьте ls_job в таблицу es_result-jobs. эндиф. Endmethod. "Do Endclass. "Реализация lcl_rest_put
Обратите внимание, что реализация этой задачи не выполняет’T Care о структуре данных http, фактически используемом формате, а также о деталях формата передачи данных. Он просто работает со структурами данных ABAP ls_job для ввода и es_result для вывода.
Сессия, личность и блокировка
В тестовых приложениях (ни в приложении JSON, ни в приложении XML) не существует ни входа в систему, ни внедрение данных. Поскольку приложения открыты для всех, это работает только с тех пор, как я дону’Т Действительно работать в таблице базы данных zjobs. На самом деле, каждый клиент, который называет приложение, работает с собственными данными сеанса, так что он не делает’T Конфликт с другими пользователями’ операции, и сам не беспокоит другие пользователи. Данные сеанса сохраняются для него в качестве куки-файлов на стороне сервера, пережив один шаг диалога (например, перезагрузка страницы воспроизводит текущее состояние данных).
Когда веб-клиент написан как BSP, в атрибуте доступен идентификатор сеанса, доступный Время выполнения-> server_id. Этот идентификатор сеанса идентифицирует конкретный экземпляр браузера, который сделал запрос. На стороне клиента этот идентификатор сеанса всегда содержится в файле cookie под названием SAP-APPCONTEXT. Если в приложении есть состояние, которое необходимо сохранить с помощью идентификатора сеанса, идентификатор должен быть извлечен из файла cookie sap-appcontext и должен быть передан в виде параметра запроса со всеми запросами Ajax. Вот функция, которая извлекает SAP-AppContext из cookie:
функция get_appcontext () < var lAppcontextCookie = document.cookie.match(/sap-appcontext=(.*?)(?:;|$)/); return lAppcontextCookie && ( lAppcontextCookie.length >= 2) && unescape (lappcontextcookie [1]) || ""; >
AppContext, возвращенный из этой функции, может быть передан в виде параметра запроса с каждым запросом AJAX. На стороне сервера идентификатор сеанса может быть извлечен из этого параметра:
Метод get_session_id. Данные: LV_APP_CONTEXT TYPE Строка, LV_APP_CONTEXT64 Тип строки. * Прочтите поле формы, предоставленное AJAX Request LV_APP_CONTEXT64 = IO_SERVER-> request-> get_form_field ('sap_appcontext'). Если LV_APP_CONTEXT64 не является начальным. * BASE64 DECODE LV_APP_CONTEXT = CL_HTTP_UTILITY => DECODE_BASE64 (LV_APP_CONTEXT64). * Извлеките сеанс-ID Найти regex 'sap-sessionid = ([^;]+) (?:; | $) 'в lv_app_context submatches ev_session_id. эндиф. Если ev_session_id является начальным. ev_session_id = io_server-> session_id. эндиф. Endmethod.
В качестве запасного, в строке 22, используется сервер-> session_id. Тем не менее, будет новый сервер-> session_id для каждого запроса, который приводит к свежим данным сеанса с каждым шагом диалога. Если вам действительно нужно управление сеансом, важно, чтобы идентификатор сеанса был передан на сервер.
Это хорошая идея, чтобы объединить идентификатор сеанса с процедурой входа в систему: если пользователь аутентифицирует, его браузер получает идентификатор сеанса с ограниченной достоверностью. Этот сеанс должен быть прошел с каждой последовательной операцией отдыха. В ABAP его можно использовать для хранения и извлечения данных, специфичных для сеанса, в таблице баз данных Scookie через класс доступа к базе данных CL_BSP_SERVER_SIDE_COUKIE.
Эта связь идентификатора сеанса с входом в систему – примерно – как работает API REST для Центра качества HP.
Использование ABAP’S встроенный конвертер JSON
В то время как экземпляр конвертера XML довольно прост в реализации -вызов преобразования XSLT для XML -> ABAP, и еще один для обратного пути -это может быть удивительным, что преобразование JSON можно обрабатывать точно так же: с преобразованием. Это возможно, так как вызовать преобразование Заявление поддерживает формат JSON (по крайней мере, согласно SAP_BASIS 702). JSON автоматически определяется и проанализируется в промежуточный формат JSON-XML. Это может быть обработано с помощью произвольного преобразования XSLT и преобразовано в другие документы XML или для данных ABAP.
Например, запрос PUT из нашего тестового приложения может отправить следующие данные JSON на сервер:
Если строка с этим контентом передается как “Источник XML” чтобы ABAP’S CALL CALLERSTACTIONS, JSON будет проанализирован в XML -представление, подобное этому (формат легко понять – я думаю, что здесь не требуется объяснение
При обработке произвольного преобразования XSLT, с оператором преобразования вызовов и передачей строки JSON в качестве источника, XSLT будет работать на этом внутреннем представлении JSON-XML. Легко преобразовать такой документ JSON-XML в данные ABAP-быть более точным: преобразовать его в ASXML-представление данных ABAP. Например, рассмотрим следующее преобразование XSLT:
При применении к строке JSON он даст следующий результат:
0001 RSNAST00 Uxpd_kube_kv 2 Икс Рейнер Зуэфол Вывод всех подтверждений заказа на продажу
Это действительное описание данных ABAP. Если преобразование называется ZJSON2JOB, данные могут быть просто импортированы в структуру данных ABAP с идентификатором компонентов, повторным и т. Д.
Класс LCL_JSON_CONVERTER Реализация. Метод get_entered_data. Данные: LO_EX Тип REF TO CX_TRANSFormation_ERROR. чистый es_job. Проверьте IV_CDATA CN SPACE. пытаться. преобразование вызова ZJSON2JOB Источник XML IV_CDATA Результат job = es_job. поймать cx_transformation_error в lo_ex. rast_parse_error (lo_ex). Эндтри. Endmethod. "get_Entered_data
Многие вещи можно сделать с идентификатором преобразования идентичности, без необходимости определять собственное преобразование XSLT вообще. Если вы можете навязать структуру данных JSON для использования в веб -приложении, необходимо использовать такой “канонический” состав. Например, рассмотрите возможность завершения хэша JSON с помощью атрибутов работы в другой хеш, что делает его значением для некоторого символического ключа “РАБОТА”:
Затем данные могут быть проанализированы в структуру без необходимости разработки пользовательского преобразования XSLT, просто с использованием идентичности:
Источник идентификатора преобразования вызова XML IV_CDATA Результат job = es_job.
В этом примере, поскольку я написал веб-клиент и обработку на стороне сервера, я мог бы выбрать это больше “канонический” формат. Но, не выбрав это, я научился работать с более гибкими форматами данных JSON.
Есть несколько причин для работы с “неканонический” JSON представления данных ABAP:
- Формат JSON может быть разработан в пользу веб -приложения – для оптимизации читаемости кода клиента JavaScript, работающего на данных.
- Могут быть клиентские компоненты, требующие определенных форматов JSON. Например, DataTable JQUERY требует передачи данных таблицы в виде массива массивов: http: // www.DataTables.Net/Release-Datatables/Примеры/DATA_SOURCES/AJAX.HTML
- Слуедные услуги на основе JSON могут быть вызваны со стороны ABAP (с объектом клиента HTTP)
- Данные ABAP могут быть прогнозируется На основе основных данных сокращение размера сообщений до данных, которые действительно необходимы.
Просто чтобы проиллюстрировать, пусть’S посмотрите на другое преобразование – выход с сервера к клиенту. Опять формат немного отличается от “канонический” Формат JSON, который значительно упростит обработку на стороне ABAP. Как уже упоминалось, структура данных результата содержит
- сообщение,
- тип сообщения,
- и таблица атрибутов работы:
Типы: начало TY_RESULT, MSGTYPE TYPE SYMSGTY, Тип сообщения C Длина 255, Тип заданий ZJOBS_TAB, конец TY_RESULT.
Следующий формат будет идеальным подвеской JSON для этой структуры. Это может быть просто произведено с преобразованием идентичности, проходя как “Результат источника = ls_result” (где ls_result это структура типа ty_result):
- Все имена компонентов идеально совпадают с именами ключей хэша JSON,
- Внутренняя таблица отображается в виде массива хеш, каждый хеш, представляющий одну запись таблицы,
- И есть хэш на верхнем уровне с символическим именем “РЕЗУЛЬТАТ” Для полной вещи:
Но формат JSON, который поддерживает API REST, на самом деле отличается в некоторых деталях:
- Работы разработаны не как массив, а как хэш, с идентификатором как хэш -ключ.
- Нет избыточного хэша, охватывающего все это в качестве значения для некоторого ключа.
- Компонент для msgtype отличается. Это просто называется типом.
Вот пример экземпляра:
< "JOBS": < "0001": < "REPID": "RSNAST00", "VARID": "UXPD_KUBE_KV", "PRIO": "2", "RESTART": "X", "CONTACT": "Rainer Zufall", "DESCR": "Output all sales order confirmations" >, "0002": < "REPID": "RBDAPP01", "VARID": "UXPD_EDI_GUT02", "PRIO": "3", "RESTART": "X", "CONTACT": "Herbert Hurtig", "DESCR": "Credit Memos" >>, "Сообщение": "", "type": "">
Мы продолжаем так же, как и выше, только в другом направлении: на основе типа данных ABAP ty_result, Мы пишем преобразование XSLT, чтобы получить внутренний формат JSON-XML, соответствующий этой строке данных JSON.
Формат данных JSON-XML желаемой строки данных JSON выглядит так:
Так что это цель, которую необходимо получить в результате преобразования. С другой стороны, формат ASXML структуры TY_RESULT выглядит так:
0001 RSNAST00 Uxpd_kube_kv 2 Икс Рейнер Зуэфол Вывод всех подтверждений заказа на продажу 0002 RBDAPP01 Uxpd_edi_gut02 3 Икс Герберт Херчиг Кредитные записки Тест я
И это программа XSLT, которая выполнит преобразование:
Мы видим, что в основном для каждого отклонения от “канонический” Представление данных JSON ABAP, в обработке преобразования XSLT обрабатывает это отклонение. Например, различный тип имени вместо msgtype в цели обрабатывается с помощью шаблона
Идентификатор должен быть перестановлен: от простого атрибута структуры данных Zjobs, он должен быть повышен на один уровень выше, чтобы стать ключом к хэш. Все остальные атрибуты, кроме идентификатора, копируются в виде строковых узлов в результат. Для этого необходимы эти два шаблона:
Сопоставление объекта данных TY_RESULT в строку JSON ожидаемого формата теперь выполняется в ABAP со следующим кодом:
Метод result_to_cdata. Данные: lo_writer type ref to cl_sxml_string_writer. lo_writer = cl_sxml_string_writer => create (type = if_sxml => co_xt_json). преобразование вызова zjobs2json исходные данные = is_result result xml lo_writer. ev_cdata = cl_abap_codepage => convert_from (lo_writer-> get_output ()). Endmethod. "result_to_cdata
Что’S All: EV_CDATA будет затем содержать строку данных JSON, которая будет размещена в корпусе ответа HTTP.
Краткое содержание
Я обрисовал некоторые типичные темы, касающиеся реализации API REST в ABAP. Можно сохранить отдельные проблемы в отдельных (локальных или глобальных) классах, применяя такие шаблоны, как стратегия. Вот как организован класс ZCL_JOB_DATA, обслуживающий мой Demo Rest API (основные идеи обсуждались в этом блоге):
Как создать API REST с SAP ABAP и применить маршрутизацию MVC1
В этом сообщении я хотел бы показать, как создать API REST и как применять маршрутизацию MVC1 для обработки различных запросов просто из класса контроллера.
Для этого сначала мы создадим класс обработчиков и контроллера для структуры отдыха. Затем мы добавим класс контроллера MVC1 и класс модели для обработки бизнес -логики.
И, наконец, мы создадим услугу для обработки запросов отдыха.
В конце поста есть веб -браузер, почтальон и ABAP, потребляющие примеры для одного и того же API отдыха.
Чтобы узнать больше о SAP REST, посмотрите урок для отдыха.
Создать следующие структуры;
- ZREST_S_RESP_STATE
- ZREST_S_RESPONSE
- ZREST_S_REQUEST
- ZREST_S_RESP_STATE
- ZREST_S_RESPONSE
Теперь мы будем Создать классы.
Позвоните в стек для вызова
- ZREST_CL_DEFS
- ZREST_CL_MODEL
- ZREST_CL_REQ_CONTROLLER
- ZREST_CL_REQ_HTTP_HANDLER
- ZREST_CL_HTTP_HANDLER
Класс ZREST_CL_DEFS Определение публично . Публичный раздел. Константы C_STATE_SUCCESS TYPE WAR1 Значение 'S' ## NO_TEXT. Константы C_STATE_WARNING TYPE war1 value 'w' ## no_text. Константы C_STATE_ERROR TYPE WAR1 Значение 'e' ## no_text. Защищенный раздел. Частный раздел. Endclass. Класс ZREST_CL_DEFS реализация. Endclass.
Класс Zrest_cl_model определение публика . Публичный раздел. Методы get_dateTime Экспорт !response_body type zrest_s_response-body !Тип состояния ZREST_S_RESPONSE-State . Защищенный раздел. Частный раздел. Endclass. Класс ZREST_CL_MODEL реализация. * ---------------------------------------------------------------------------------------+ * | Общедоступный метод экземпляра ZREST_CL_MODEL-> GET_DATETIME * + --------------------------------------------------------------------------------------------- + * | [Метод get_datetime. Данные: exref type ref to cx_root. ПЫТАТЬСЯ . Типы: начало ty_res, datetime type tzntimestp, конец ty_res. Данные: res type ty_res. res-dateTime = sy-datum && sy-uzeit. response_body = /ui2 /cl_json => serialize (экспорт data = res). State-State = ZREST_CL_DEFS => C_STATE_SUCCESS. Поймать cx_root в exref. State-State = ZREST_CL_DEFS => C_STATE_ERROR. state-state_text = exref-> get_text (). Эндтри. Endmethod. Endclass.
Класс ZREST_CL_REQ_CONTROLLER ОПРЕДЕЛИТЬ . Публичный раздел. Методы Process_Request Импорт !REQ_JSON TYPE Экспорт строки !response_json тип строки !response_stc type Zrest_s_response . Защищенный раздел. Частный раздел. Константы: C_REQ_GET_DATETIME TYPE ZREST_E_REQ_ID Значение '1001'. Методы conv_stc_to_json importing response_stc type zrest_s_response возвращающееся значение (результат) Тип строка. Endclass. Класс ZREST_CL_REQ_CONTROLLER Реализация. * ---------------------------------------------------------------------------------------+ * | Приятный метод экземпляра ZREST_CL_REQ_CONTROLLER-> CONV_STC_TO_JSON * + ------------------------------------------------------------------------------------------------- + * | [--->] response_stc type Zrest_s_response * | [Метод conv_stc_to_json. Данные: exref type ref to cx_root. ПЫТАТЬСЯ . result = /ui2 /cl_json => serialize (экспорт data = response_stc). Поймать CX_ROOT. result = exref-> get_text (). Эндтри. Endmethod. * ---------------------------------------------------------------------------------------+ * | Экземпляр публичный метод ZREST_CL_REQ_CONTROLLER-> PROCEST_REQUEST * + ------------------------------------------------------------------------------------------------- + * | [--->] req_json type String * | [Метод Process_request. Данные: exref type ref to cx_root. ПЫТАТЬСЯ . DATA REQ_STC Тип ZREST_S_REQUEST. /ui2/cl_json => deserialize (экспорт json = req_json изменение data = req_stc). Если REQ_STC-ID не является начальным. DATA (MODEL) = NEW ZREST_CL_MODEL (). Если req_stc-id EQ C_REQ_GET_DATETIME. Model-> get_datetime (импорт response_body = response_stc-body state = response_stc-state). ЕЩЕ. response_stc-state = Zrest_cl_defs => c_state_warning. Сообщение S001 (ZREST_MSG) в repply_stc-state-state_text. Эндиф. ЕЩЕ. "Заполните фиктивное содержание как образец REQ_STC-ID = 999999. req_stc-body = 'некоторое содержание JSON'. response_stc-body = /ui2 /cl_json => serialize (экспорт data = req_stc). response_stc-state = Zrest_cl_defs => c_state_warning. Сообщение S002 (ZREST_MSG) в repply_stc-state-state_text. Эндиф. response_json = conv_stc_to_json (response_stc = response_stc). Поймать CX_ROOT. response_stc-state = Zrest_cl_defs => c_state_error. response_stc-state_text = exref-> get_text (). response_json = conv_stc_to_json (response_stc = response_stc). Эндтри. Endmethod. Endclass.
Класс ZREST_CL_REQ_HTTP_HANDLER Определение публично наследуя от CL_REST_RESOURCE . Публичный раздел. Методы if_rest_resource ~ Получить переопределение . Методы if_rest_resource ~ post переопределение . Защищенный раздел. Частный раздел. Endclass. Класс ZREST_CL_REQ_HTTP_HANDLER реализация. * ---------------------------------------------------------------------------------------+ * | Общественный метод экземпляра Zrest_cl_req_http_handler-> if_rest_resource ~ get * + --------------------------------------------------------------------------------------------- + * +-------------------------------------------------------------------------------------- Метод if_rest_resource ~ Get. Data (req_json) = mo_request-> get_uri_query_parameter (iv_name = 'req' iv_encoded = abap_false). DATA (CONTROLLER) = NEW ZREST_CL_REQ_CONTROLLER (). Controller-> process_request (экспорт req_json = req_json importing response_json = data (response_json))). mo_response-> create_entity ()-> set_string_data (iv_data = response_json). Endmethod. * ---------------------------------------------------------------------------------------+ * | Общедоступный метод экземпляра Zrest_cl_req_http_handler-> if_rest_resource ~ post * + --------------------------------------------------------------------------------------------- + * | [--->] io_entity тип ref to if_rest_entity * +-------------------------------------------------------------------------------------- Метод if_rest_resource ~ post. Data (req_json) = mo_request-> get_entity ()-> get_string_data (). DATA (CONTROLLER) = NEW ZREST_CL_REQ_CONTROLLER (). Controller-> process_request (экспорт req_json = req_json importing response_json = data (response_json))). mo_response-> create_entity ()-> set_string_data (iv_data = response_json). Endmethod. Endclass.
CSRF отключен в обработке ниже. Отключение его из параметров обслуживания GUI не работает. Вам нужно реализовать harder_csrf_token, чтобы отключить его для отдыха.
Класс ZREST_CL_HTTP_HANDLER Определение публично наследуя от CL_REST_HTTP_HANDLER CREATE PUBLE . Публичный раздел. "Обеспечивает маршрутизацию. Пути маршрутизации присваиваются контроллерам в этом методе методах if_rest_application ~ get_root_handler Refinition . Защищенный раздел. "Если вы хотите отключить, переопределите этот метод. Как пустой метод. Методы handle_csrf_token переосмысление . Частный раздел. Endclass. Класс ZREST_CL_HTTP_HANDLER реализация. * ---------------------------------------------------------------------------------------+ * | Метод защиты экземпляра ZREST_CL_HTTP_HANDLER-> HARDE_CSRF_TOKEN * + ------------------------------------------------------------------------------------------------- + * | [--->] io_csrf_handler type ref to if_rest_csrf_handler * | [--->] io_request type ref to if_rest_request * | [--->] io_response type ref to if_rest_response * +-------------------------------------------------------------------------------------- Метод handle_csrf_token. * Метод вызова Super-> harder_csrf_token * exporting * io_csrf_handler = * io_request = * io_response = * . Endmethod. * ---------------------------------------------------------------------------------------+ * | Экземпляр публичный метод ZREST_CL_HTTP_HANDLER-> IF_REST_APPLICATION ~ GET_ROOT_HANDLER * + --------------------------------------------------------------------------------------------- + * | [Метод if_rest_application ~ get_root_handler. "Обеспечивает маршрутизацию. «Путь службы/SAP/BC/RET?SAP-Client = 001 & req = data (root_handler) = new cl_rest_router (). root_handler-> atture (экспорт iv_template = '/rest' "единое имя для ресурсов iv_handler_class = 'Zrest_cl_req_http_handler'" Имя типа объекта). * «Вы можете добавить больше классов обработчиков запросов *»?SAP-Client = 001 & req = * root_handler-> attra ( * exporting * iv_template = '/rest2' "Unified name для ресурсов * iv_handler_class = 'Zrest_cl_req_http_handler2'" Имя типа объекта *). ro_root_handler = root_handler. Endmethod. Endclass.
И последний шаг, Создать сервис.
Откройте sicf tcode и запустите.
Перейдите в/SAP/BC/REST и добавьте новый суббол
Добавить описание и перейдите к вкладке «Список обработчиков» и нашем классе, ZREST_CL_HTTP_HANDLER, как обработчик.
Активировать обслуживание. Служба щелкните правой кнопкой мыши и нажмите тест. Он откроет браузер. Изменить URL для обработки /отдыха.
В моем случае http: // vhcalnplci: 8000/sap/bc/rest/Zrest/Отдых
Если вы хотите передать некоторые параметры в запросе GET, добавьте такие параметры строки запроса, как ‘http: // vhcalnplci: 8000/sap/bc/rest/Zrest/rest?SAP-Client = 001 & req =’
Если вы не отключите CSRF на обработчике, у вас будут проблемы, вызывая методы не гнездовых, такие как методы публикации от почтальника или от клиента, отличного от самого сервера.
Поэтому в моем примере я отключил CSRF.
Почтальон. Примеры
Основные параметры аутентификации
Получить пример и результат
Отправить пример и результат
Потреблять из ABAP
Мы будем использовать httpclient для вызова, и мы будем анализировать JSON в структуре ABAP с примером get_dateTime.
Http клиент -код
Класс Zutil_cl_rest_ws определение публики . "Класс -обертка для раздела веб -сервис Rest Calls Calls Calls Calls. "Константы Константы: C_CONTENT_TYPE_JSON TYPE Строка Значения 'Application/json; charset = utf-8', c_content_type_xml type string value 'application/xml; charset = utf-8', c_request_method_get type string 'get', c_request_method_post. "Сделает методы вызова WS CALL_WS Импорт значения (i_url) Тип строки (i_content_type) Тип строки по умолчанию c_content_type_json value (i_request_method) тип строки default c_request_method_get value (i_username) zepress value value value (i_username) zpass values value (i_username) zpass vally value (i_userame) zpass value (i_pay valultrogulting) util_cl_defs => gty_state value (e_response_str) type String. Защищенный раздел. Частный раздел. Данные http_client type ref to if_http_client. Методы fill_warning возвращающееся значение (состояние) введите zutil_cl_defs => gty_state. Endclass. Класс Zutil_Cl_rest_WS реализация. * ---------------------------------------------------------------------------------------+ * | Общедоступный метод экземпляра zutil_cl_rest_ws-> call_ws * + --------------------------------------------------------------------------------------------- + * | [--->] I_URL Type String * | [--->] i_content_type type String (default = c_content_type_json) * | [--->] i_request_method Type String (по умолчанию = C_REQUEST_METHOD_GET) * | [--->] i_username Тип строки (необязательно) * | [--->] I_PASSWORD Тип строки (необязательно) * | [--->] i_payload Тип строки (необязательно) * | [Gty_state * | [Метод call_ws. Данные: exref type ref to cx_root. ПЫТАТЬСЯ. «Использование этого create_by_url может упростить определенные аспекты использования этого класса бесплатно http_client. cl_http_client => create_by_url (экспорт url = i_url importing client = http_client Exceptions Argiry_not_found = 1 plugin_not_active = 2 internal_error = 3 других = 4). Если sy-subrc <> 0. e_state-State = fill_warning (). ВОЗВРАЩАТЬСЯ. Эндиф. «Моя логика изначально использовалась, но вы должны быть в состоянии изменить, чтобы опубликовать http_client-> request-> set_method (i_request_method). http_client-> request-> set_content_type (i_content_type). "Не забудьте аутентифицировать, если i_username не является начальным или i_password не является начальным. http_client-> authenticate (username = i_username password = i_password). Эндиф. «Если существует, подготовьте полезную нагрузку и назначьте, если i_payload не является начальной. "Преобразовать эту полезную нагрузку в XString. Data lv_payload_x type xstring. Функция вызова 'SCMS_STRING_TO_XSTRING' Экспорт TEXT = I_PAYLOAD ИМПИМИМПЕТИЙ Buffer = LV_PAYLOAD_X Исключения не удалось = 1 Другое = 2. Если sy-subrc <> 0. e_state-State = Zutil_cl_defs => c_state_warning. E_STATE-State = 'Ошибка кодирования!'. ВОЗВРАЩАТЬСЯ. ЕЩЕ. http_client-> request-> set_data (lv_payload_x). "Бинарные данные endif. Эндиф. "Отправка запроса http_client-> send (исключения http_communication_failure = 1 http_invalid_state = 2). Если sy-subrc <> 0. e_state-State = fill_warning (). ВОЗВРАЩАТЬСЯ. Эндиф. «Получение ответа http_client-> cheact (исключения http_communication_failure = 1 http_invalid_state = 2 http_processing_failed = 3). Если sy-subrc <> 0. e_state-State = fill_warning (). ВОЗВРАЩАТЬСЯ. Эндиф. "Проверьте ответ. Надеюсь, вы получите ответ JSON. e_response_str = http_client-> response-> get_cdata (). Если e_response_str является начальным. e_response_str = http_client-> response-> get_data (). Эндиф. E_STATE = ZUTIL_CL_DEFS => C_STATE_SUCCESS. e_state-state_text = 'успешно завершен.'. Поймать cx_root в exref. E_STATE-State = ZUTIL_CL_DEFS => C_STATE_ERROR. e_state-State_text = exref-> get_text (). Эндтри. Endmethod. * ---------------------------------------------------------------------------------------+ * | Приватный метод экземпляра Zutil_cl_rest_ws-> fill_warning * + ------------------------------------------------------------------------------------------------- + * | [Gty_state * +-------------------------------------------------------------------------------------- Метод fill_warning. State-State = Zutil_cl_defs => c_state_warning. http_client-> get_last_error (импорт сообщений = data (msg) "Сообщение об ошибке). State-State_Text = MSG. Endmethod. Endclass.
Код потребительского класса. Сначала разворачивать структуру ответа и проверяет состояние. Если это успех, то разворачивает часть тела JSON для результата Call ID 1001.
Класс ZREST_CL_CONSUMER Определение . Публичный раздел. Методы get_datetime exporting cate type type zutil_cl_defs => gty_state dt type tzntimestp. Защищенный раздел. Частный раздел. Endclass. Класс ZREST_CL_CONSUMER реализация. * ---------------------------------------------------------------------------------------+ * | Экземпляр публичный метод Zrest_cl_consumer-> get_datetime * + ------------------------------------------------------------------------------------------------- + * | [Gty_state * | [Метод get_datetime. "Пример метода потребления данных Web API REST: ExRef Type REF TO CX_ROOT. ПЫТАТЬСЯ. "Constants: C_UNAME TYPE Значение строки" Разработчик ", тип C_PASS. "Построить данные вызова: url -тип строки string 'http: // vhcalnplci: 8000/sap/bc/rest/Zrest/rest?SAP-Client = 001 '. DATA REQ_STC Тип ZREST_S_REQUEST. req_stc-id = '1001'. Data (req_json) = /ui2 /cl_json => serialize (экспорт data = req_stc). url = url && '& req =' && req_json. «Позвоните в Web API New Zutil_Cl_rest_ws ()-> call_ws (экспорт i_url = url i_username = c_uname i_password = c_pass importing e_state = состояние e_response_str = data (json_response))). Если государственное состояние eq zutil_cl_defs => c_state_success. Данные: resp_stc type Zrest_s_response. /ui2/cl_json => deserialize (экспорт json = json_response изменение данных = resp_stc). Если resp_stc-State-State eq zutil_cl_defs => c_state_success. Типы: начало ty_res, datetime type tzntimestp, конец ty_res. Данные: resp_1001 Type ty_res. /ui2/cl_json => deserialize (экспорт json = resp_stc изменение данных = resp_1001). dt = resp_1001-dateTime. Эндиф. Эндиф. Поймать cx_root в exref. State-State = ZUTIL_CL_DEFS => C_STATE_ERROR. state-state_text = exref-> get_text (). Эндтри. Endmethod. Endclass.
Вот и все. Таким образом, вы можете интегрировать любую среду, систему в SAP.
надеюсь, это поможет.
Спасибо за прочтение.
Ссылки по теме